kbuild-3686/0000775000175000017500000000000015053010106012703 5ustar locutuslocutuskbuild-3686/dist/0000775000175000017500000000000015053010106013646 5ustar locutuslocutuskbuild-3686/dist/freebsd/0000775000175000017500000000000015053010106015260 5ustar locutuslocutuskbuild-3686/dist/freebsd/devel/0000775000175000017500000000000015053010106016357 5ustar locutuslocutuskbuild-3686/dist/freebsd/devel/kBuild/0000775000175000017500000000000015053010106017571 5ustar locutuslocutuskbuild-3686/dist/freebsd/devel/kBuild/pkg-plist0000664000175000017500000000556215053010106021436 0ustar locutuslocutusbin/kmk_sed bin/kmk bin/kmk_append bin/kmk_cat bin/kmk_chmod bin/kmk_cp bin/kmk_cmp bin/kmk_echo bin/kmk_expr bin/kmk_md5sum bin/kmk_mkdir bin/kmk_mv bin/kmk_install bin/kmk_ln bin/kmk_printf bin/kmk_redirect bin/kmk_rm bin/kmk_rmdir bin/kmk_sleep bin/kmk_test bin/kDepIDB bin/kmk_gmake bin/kmk_fgmake bin/kmk_ash bin/kDepPre bin/kObjCache bin/kmk_time %%DATADIR%%/footer.kmk %%DATADIR%%/header.kmk %%DATADIR%%/rules.kmk %%DATADIR%%/subfooter.kmk %%DATADIR%%/subheader.kmk %%DATADIR%%/up.kmk %%DATADIR%%/tools/ALP.kmk %%DATADIR%%/tools/BISON.kmk %%DATADIR%%/tools/FLEX.kmk %%DATADIR%%/tools/GCC.kmk %%DATADIR%%/tools/GCC3.kmk %%DATADIR%%/tools/GCC32.kmk %%DATADIR%%/tools/GCC3OMF.kmk %%DATADIR%%/tools/GCC3PLAIN.kmk %%DATADIR%%/tools/GCC4MACHO.kmk %%DATADIR%%/tools/GCC64.kmk %%DATADIR%%/tools/GXX.kmk %%DATADIR%%/tools/GXX3.kmk %%DATADIR%%/tools/GXX32.kmk %%DATADIR%%/tools/GXX3OMF.kmk %%DATADIR%%/tools/GXX3PLAIN.kmk %%DATADIR%%/tools/GXX4MACHO.kmk %%DATADIR%%/tools/GXX64.kmk %%DATADIR%%/tools/MASM510.kmk %%DATADIR%%/tools/MASM600.kmk %%DATADIR%%/tools/MASM610.kmk %%DATADIR%%/tools/MASM6PLUS.kmk %%DATADIR%%/tools/MASM710.kmk %%DATADIR%%/tools/MINGW32.kmk %%DATADIR%%/tools/MSLINK510.kmk %%DATADIR%%/tools/NASM.kmk %%DATADIR%%/tools/OPENWATCOM-16.kmk %%DATADIR%%/tools/OPENWATCOM-WL.kmk %%DATADIR%%/tools/OPENWATCOM.kmk %%DATADIR%%/tools/TAR.kmk %%DATADIR%%/tools/TARGZ.kmk %%DATADIR%%/tools/VAC308.kmk %%DATADIR%%/tools/VCC70.kmk %%DATADIR%%/tools/VCC80.kmk %%DATADIR%%/tools/VCC80AMD64.kmk %%DATADIR%%/tools/VCC80X86.kmk %%DATADIR%%/tools/WATCOMC11C-16.kmk %%DATADIR%%/tools/WATCOMC11C-WL.kmk %%DATADIR%%/tools/WATCOMC11C.kmk %%DATADIR%%/tools/WGET.kmk %%DATADIR%%/tools/XGCCAMD64LINUX.kmk %%DATADIR%%/tools/YACC.kmk %%DATADIR%%/tools/YASM.kmk %%DATADIR%%/tools/ZIP.kmk %%DATADIR%%/sdks/DXSDK.kmk %%DATADIR%%/sdks/DXSDKAMD64.kmk %%DATADIR%%/sdks/DXSDKX86.kmk %%DATADIR%%/sdks/LIBSDL.kmk %%DATADIR%%/sdks/MACOSX104.kmk %%DATADIR%%/sdks/MACOSX104INCS.kmk %%DATADIR%%/sdks/MACOSX105.kmk %%DATADIR%%/sdks/MACOSX105INCS.kmk %%DATADIR%%/sdks/NT4DDK.kmk %%DATADIR%%/sdks/OS2DDKBASE32.kmk %%DATADIR%%/sdks/W2K3DDK.kmk %%DATADIR%%/sdks/W2K3DDKAMD64.kmk %%DATADIR%%/sdks/W2K3DDKX86.kmk %%DATADIR%%/sdks/W32API.kmk %%DATADIR%%/sdks/WIN32SDK.kmk %%DATADIR%%/sdks/WIN32SDK2002.kmk %%DATADIR%%/sdks/WIN64SDK.kmk %%DATADIR%%/sdks/WINDDK.kmk %%DATADIR%%/sdks/WINDDKW2K.kmk %%DATADIR%%/sdks/WINDDKWLH.kmk %%DATADIR%%/sdks/WINDDKWNET.kmk %%DATADIR%%/sdks/WINDDKWXP.kmk %%DATADIR%%/sdks/WINPSDK.kmk %%DATADIR%%/sdks/WINPSDKINCS.kmk %%DATADIR%%/units/lex.kmk %%DATADIR%%/units/qt3.kmk %%DATADIR%%/units/qt4.kmk %%DATADIR%%/units/yacc.kmk %%DATADIR%%/msgstyles/brief.kmk %%DATADIR%%/templates/DUMMY.kmk %%DOCSDIR%%/QuickReference-kmk.txt %%DOCSDIR%%/QuickReference-kmk.html @dirrm %%DATADIR%%/msgstyles @dirrm %%DATADIR%%/sdks @dirrm %%DATADIR%%/templates @dirrm %%DATADIR%%/tools @dirrm %%DATADIR%%/units @dirrm %%DATADIR%% @dirrm %%DOCSDIR%% kbuild-3686/dist/freebsd/devel/kBuild/pkg-descr0000664000175000017500000000011715053010106021372 0ustar locutuslocutuskBuild is a makefile framework for writing simple makefiles for complex tasks. kbuild-3686/dist/freebsd/devel/kBuild/Makefile0000664000175000017500000000663115053010106021237 0ustar locutuslocutus# New ports collection makefile for: kbuild # Date created: Mon Jul 28 14:34:33 BST 2008 # Whom: Bruce Simpson # # $FreeBSD: ports/devel/kBuild/Makefile,v 1.4 2008/12/02 23:14:19 gahr Exp $ # PORTNAME= kBuild PORTVERSION= 0.1.5 CATEGORIES= devel MASTER_SITES= ftp://ftp.netlabs.org/pub/kbuild/ DISTNAME= ${PORTNAME}-${PORTVERSION}-src MAINTAINER= que_deseja@hotmail.com COMMENT= Makefile framework USE_AUTOTOOLS= automake:19 autoconf:261 USE_GMAKE= yes WRKSRC= ${WRKDIR}/${PORTNAME}-${PORTVERSION} KBUILD_ARCH= ${MACHINE_ARCH:S/i386/x86/} KBUILD_ENV= ACLOCAL=${ACLOCAL} \ AUTOMAKE=${AUTOMAKE} \ AUTORECONF=${AUTORECONF} KBUILD_STAGE= ${WRKSRC}/out/freebsd.${KBUILD_ARCH}/release${PREFIX} # KBUILD_BINS, KBUILD_DATA_FILES and KBUILD_DOC_FILES (generated). .include "kBuild-files.mk" # Override autotools run-autotools: do-configure: do-build: cd ${WRKSRC} && ${SETENV} ${KBUILD_ENV} ./kBuild/env.sh --full \ ${GMAKE} NIX_INSTALL_DIR=${PREFIX} -f bootstrap.gmk ${WRKSRC}/kBuild/env.sh --full-with-bin \ kmk -C ${WRKSRC} NIX_INSTALL_DIR=${PREFIX} do-install: .for file in ${KBUILD_BIN_FILES} ${INSTALL_PROGRAM} ${KBUILD_STAGE}/bin/${file} ${PREFIX}/bin/${file} .endfor ${MKDIR} ${DATADIR} .for file in ${KBUILD_DATA_FILES} ${MKDIR} `dirname ${DATADIR}/${file}` ${INSTALL_DATA} ${KBUILD_STAGE}/share/kBuild/${file} ${DATADIR}/${file} .endfor ${MKDIR} ${DOCSDIR} .for file in ${KBUILD_DOC_FILES} ${MKDIR} `dirname ${DOCSDIR}/${file}` ${INSTALL_DATA} ${KBUILD_STAGE}/share/doc/kBuild-${PORTVERSION}/${file} ${DOCSDIR}/${file} .endfor .include # # Helper rule to generate kBuild-files.mk and pkg-plist when updating the port. # kbuild-generate-files: echo '# Autogenerated by kbuild-generate-files in Makefile' > kBuild-files.mk echo '' >> kBuild-files.mk echo 'KBUILD_BIN_FILES = \' >> kBuild-files.mk ${WRKSRC}/kBuild/env.sh --full-with-bin --quiet \ kmk --no-print-directory -sC ${WRKSRC} NIX_INSTALL_DIR=${PREFIX} \ MY_INST_BIN=_keep_/ MY_INST_DATA=_drop_/ MY_INST_DOC=_drop_/ \ kbuild-show-install-files \ | sed -e '/^_drop_/d' -e 's/^_keep_\// /' -e 's/$$/ \\/' \ >> kBuild-files.mk echo '' >> kBuild-files.mk echo 'KBUILD_DATA_FILES = \' >> kBuild-files.mk ${WRKSRC}/kBuild/env.sh --full-with-bin --quiet \ kmk --no-print-directory -sC ${WRKSRC} NIX_INSTALL_DIR=${PREFIX} \ MY_INST_BIN=_drop_/ MY_INST_DATA=_keep_/ MY_INST_DOC=_drop_/ \ kbuild-show-install-files \ | sed -e '/^_drop_/d' -e 's/^_keep_\// /' -e 's/$$/ \\/' \ >> kBuild-files.mk echo '' >> kBuild-files.mk echo 'KBUILD_DOC_FILES = \' >> kBuild-files.mk ${WRKSRC}/kBuild/env.sh --full-with-bin --quiet \ kmk --no-print-directory -sC ${WRKSRC} NIX_INSTALL_DIR=${PREFIX} \ MY_INST_BIN=_drop_/ MY_INST_DATA=_drop_/ MY_INST_DOC=_keep_/ \ kbuild-show-install-files \ | sed -e '/^_drop_/d' -e 's/^_keep_\// /' -e 's/$$/ \\/' \ >> kBuild-files.mk echo '' >> kBuild-files.mk ${WRKSRC}/kBuild/env.sh --full-with-bin --quiet \ kmk --no-print-directory -sC ${WRKSRC} NIX_INSTALL_DIR=${PREFIX} \ 'MY_INST_BIN=bin/' 'MY_INST_DATA=%%DATADIR%%/' \ 'MY_INST_DOC=%%DOCSDIR%%/' kbuild-show-install-files \ > pkg-plist echo '@dirrm %%DATADIR%%/msgstyles' >> pkg-plist echo '@dirrm %%DATADIR%%/sdks' >> pkg-plist echo '@dirrm %%DATADIR%%/templates' >> pkg-plist echo '@dirrm %%DATADIR%%/tools' >> pkg-plist echo '@dirrm %%DATADIR%%/units' >> pkg-plist echo '@dirrm %%DATADIR%%' >> pkg-plist echo '@dirrm %%DOCSDIR%%' >> pkg-plist kbuild-3686/dist/freebsd/devel/kBuild/distinfo0000664000175000017500000000031615053010106021333 0ustar locutuslocutusMD5 (kBuild-0.1.5-src.tar.gz) = df7e0905232e67728643f97d63cbf3f3 SHA256 (kBuild-0.1.5-src.tar.gz) = db3b672da8f579949e4d8c41d023d6d1ca1ab5626a2e552970ba75e7a3af84b5 SIZE (kBuild-0.1.5-src.tar.gz) = 2431964 kbuild-3686/dist/freebsd/devel/kBuild/kBuild-files.mk0000664000175000017500000000411515053010106022435 0ustar locutuslocutus# Autogenerated by kbuild-generate-files in Makefile KBUILD_BIN_FILES = \ kmk_sed \ kmk \ kmk_append \ kmk_cat \ kmk_chmod \ kmk_cp \ kmk_cmp \ kmk_echo \ kmk_expr \ kmk_md5sum \ kmk_mkdir \ kmk_mv \ kmk_install \ kmk_ln \ kmk_printf \ kmk_redirect \ kmk_rm \ kmk_rmdir \ kmk_sleep \ kmk_test \ kDepIDB \ kmk_gmake \ kmk_fgmake \ kmk_ash \ kDepPre \ kObjCache \ kmk_time \ KBUILD_DATA_FILES = \ footer.kmk \ header.kmk \ rules.kmk \ subfooter.kmk \ subheader.kmk \ up.kmk \ tools/ALP.kmk \ tools/BISON.kmk \ tools/FLEX.kmk \ tools/GCC.kmk \ tools/GCC3.kmk \ tools/GCC32.kmk \ tools/GCC3OMF.kmk \ tools/GCC3PLAIN.kmk \ tools/GCC4MACHO.kmk \ tools/GCC64.kmk \ tools/GXX.kmk \ tools/GXX3.kmk \ tools/GXX32.kmk \ tools/GXX3OMF.kmk \ tools/GXX3PLAIN.kmk \ tools/GXX4MACHO.kmk \ tools/GXX64.kmk \ tools/MASM510.kmk \ tools/MASM600.kmk \ tools/MASM610.kmk \ tools/MASM6PLUS.kmk \ tools/MASM710.kmk \ tools/MINGW32.kmk \ tools/MSLINK510.kmk \ tools/NASM.kmk \ tools/OPENWATCOM-16.kmk \ tools/OPENWATCOM-WL.kmk \ tools/OPENWATCOM.kmk \ tools/TAR.kmk \ tools/TARGZ.kmk \ tools/VAC308.kmk \ tools/VCC70.kmk \ tools/VCC80.kmk \ tools/VCC80AMD64.kmk \ tools/VCC80X86.kmk \ tools/WATCOMC11C-16.kmk \ tools/WATCOMC11C-WL.kmk \ tools/WATCOMC11C.kmk \ tools/WGET.kmk \ tools/XGCCAMD64LINUX.kmk \ tools/YACC.kmk \ tools/YASM.kmk \ tools/ZIP.kmk \ sdks/DXSDK.kmk \ sdks/DXSDKAMD64.kmk \ sdks/DXSDKX86.kmk \ sdks/LIBSDL.kmk \ sdks/MACOSX104.kmk \ sdks/MACOSX104INCS.kmk \ sdks/MACOSX105.kmk \ sdks/MACOSX105INCS.kmk \ sdks/NT4DDK.kmk \ sdks/OS2DDKBASE32.kmk \ sdks/W2K3DDK.kmk \ sdks/W2K3DDKAMD64.kmk \ sdks/W2K3DDKX86.kmk \ sdks/W32API.kmk \ sdks/WIN32SDK.kmk \ sdks/WIN32SDK2002.kmk \ sdks/WIN64SDK.kmk \ sdks/WINDDK.kmk \ sdks/WINDDKW2K.kmk \ sdks/WINDDKWLH.kmk \ sdks/WINDDKWNET.kmk \ sdks/WINDDKWXP.kmk \ sdks/WINPSDK.kmk \ sdks/WINPSDKINCS.kmk \ units/lex.kmk \ units/qt3.kmk \ units/qt4.kmk \ units/yacc.kmk \ msgstyles/brief.kmk \ templates/DUMMY.kmk \ KBUILD_DOC_FILES = \ QuickReference-kmk.txt \ QuickReference-kmk.html \ kbuild-3686/dist/debian/0000775000175000017500000000000015053010106015070 5ustar locutuslocutuskbuild-3686/dist/debian/install0000664000175000017500000000002715053010106016460 0ustar locutuslocutusout/*.*/release/usr / kbuild-3686/dist/debian/manpages0000664000175000017500000000001515053010106016602 0ustar locutuslocutusdebian/kmk.1 kbuild-3686/dist/debian/kmk.pod0000664000175000017500000000106615053010106016361 0ustar locutuslocutus=head1 NAME kmk - framework for writing simple makefiles for complex tasks =head1 SYNOPSIS B [S>] =head1 DESCRIPTION kmk and its helper tools are an extension to GNU make to ease writing portable Makefile. There is not a lot of documentation though. A starting point is L. On Debian systems the kBuild binaries can be found in F, its data files in F and its documentation in F. =head1 SEE ALSO L =head1 AUTHOR Torsten Werner kbuild-3686/dist/debian/copyright0000664000175000017500000000330615053010106017025 0ustar locutuslocutusThis package was debianized by Torsten Werner on Sat May 5 14:23:24 CEST 2007. It was downloaded from http://svn.netlabs.org/kbuild Upstream Author: 2004-2010 knut st. osmundsen Copyright: (C) 2004-2010 knut st. osmundsen License: 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 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. On Debian systems, the complete text of the GNU General Public License can be found in `/usr/share/common-licenses/GPL'. kBuild ships modified sources of ash, make and sed. NetBSD ash is Copyright (C) 1993 The Regents of the University of California. ash is licensed under the BSD license, see `/usr/share/common-licenses/BSD'. GNU make is Copyright (C) 2007 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later GNU sed is Copyright (C) 2003 Free Software Foundation, Inc. licensed under the GPL, see `/usr/share/common-licenses/GPL`. The Debian packaging is (C) 2007, Torsten Werner and is licensed under the GPL, see `/usr/share/common-licenses/GPL'. kbuild-3686/dist/debian/patches/0000775000175000017500000000000015053010106016517 5ustar locutuslocutuskbuild-3686/dist/debian/orig-tar.sh0000775000175000017500000000057515053010106017162 0ustar locutuslocutus#!/bin/sh -e SVNROOT=$1 VERSION=$2 REVISION=$3 DIR=kbuild-$REVISION TAR=../kbuild_$VERSION.orig.tar.gz svn co -r $REVISION $SVNROOT $DIR tar -c -z --exclude '*/kBuild/bin*' --exclude '*/out/*' --exclude '*/.svn*' -f $TAR $DIR rm -rf $DIR # move to directory 'tarballs' if [ -r .svn/deb-layout ]; then . .svn/deb-layout mv $TAR $origDir echo "moved $TAR to $origDir" fi kbuild-3686/dist/debian/links0000664000175000017500000000305415053010106016135 0ustar locutuslocutus/usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_append.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_ash.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_cat.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_chmod.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_cmp.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_cp.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_echo.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_expr.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_gmake.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_install.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_ln.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_md5sum.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_mkdir.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_mv.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_printf.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_redirect.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_rm.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_rmdir.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_sed.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_sleep.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_test.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kmk_time.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kDepPre.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kDepIDB.1.gz /usr/share/man/man1/kmk.1.gz /usr/share/man/man1/kObjCache.1.gz kbuild-3686/dist/debian/rules0000775000175000017500000000322715053010106016154 0ustar locutuslocutus#!/usr/bin/make -f include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/rules/patchsys-quilt.mk YACC := YACC=/usr/bin/byacc BOOTSTRAP := ASH=/bin/bash ECHO=/bin/echo MKDIR=/bin/mkdir CP=/bin/cp \ RM=/bin/rm INSTALL=/usr/bin/install $(YACC) ifdef KBUILD_FROM_SVN SVNROOT := http://svn.netlabs.org/repos/kbuild/trunk REVISION := $(shell echo $(DEB_UPSTREAM_VERSION) | sed -e's,.*svn,,') makebuilddir:: SvnInfo.kmk SvnInfo.kmk: echo "KBUILD_SVN_URL := $(SVNROOT)" > $@ echo "KBUILD_SVN_REV := $(REVISION)" >> $@ endif build/kbuild:: debian/stamp-build debian/stamp-build: $(info DEBUG: macros defined by gcc:) -gcc -dM -E - < /dev/null kBuild/env.sh --full make -f bootstrap.gmk SRCDIR=`pwd` $(BOOTSTRAP) kBuild/env.sh kmk rebuild PATH_INS=`pwd` $(YACC) pod2man -c 'kBuild for Debian GNU/Linux' \ -r kBuild-$(DEB_UPSTREAM_VERSION) debian/kmk.pod > debian/kmk.1 touch $@ install/kbuild:: kBuild/env.sh kmk install NIX_INSTALL_DIR=/usr \ MY_INST_DOC=share/doc/kbuild/ LDFLAGS=-Wl,--as-needed clean:: -kBuild/env.sh kmk uninstall $(RM) -r debian/stamp-* debian/kmk.1 out kBuild/bin/*/* ifdef KBUILD_FROM_SVN $(RM) SvnInfo.kmk endif ## @todo fetch from ftp://ftp.netlabs.org/pub/kbuild or ## ftp://ftp.netlabs.org/incoming/kbuild when KBUILD_FROM_SVN isn't ## defined... (fetch the kBuild-x.y.z-src.tar.gz file) ifdef KBUILD_FROM_SVN get-orig-info: svn info $(SVNROOT) get-orig-source: sh debian/orig-tar.sh $(SVNROOT) $(DEB_UPSTREAM_VERSION) $(REVISION) else get-orig-source: wget -O ../tarballs/kbuild_$(DEB_UPSTREAM_VERSION).orig.tar.gz \ ftp://ftp.netlabs.org/incoming/kbuild/kBuild-$(DEB_UPSTREAM_VERSION)-src.tar.gz endif kbuild-3686/dist/debian/changelog0000664000175000017500000001445715053010106016755 0ustar locutuslocutuskbuild (1:0.1.5-1) unstable; urgency=low * New upstream version. * Adopted for tarball use. -- bird Thu, 22 Jan 2009 01:05:00 +0100 kbuild (1:0.1.5svn2062-1) unstable; urgency=low * new upstream version * Remove patch lazy.diff that has been applied upstream. -- Torsten Werner Wed, 12 Nov 2008 21:54:38 +0100 kbuild (1:0.1.5svn2059-2) unstable; urgency=low * Create SvnInfo.kmk during build process because the upstream svn does not ship it anymore. -- Torsten Werner Sat, 08 Nov 2008 09:17:10 +0100 kbuild (1:0.1.5svn2059-1) unstable; urgency=low * new upstream version * Add patch lazy.diff to fix build process. * Add more manpage symlinks. -- Torsten Werner Fri, 07 Nov 2008 23:25:40 +0100 kbuild (1:0.1.4svn1804-1) unstable; urgency=low * new upstream version * Bump up Standards-Version: 3.8.0 (no changes). -- Torsten Werner Tue, 07 Oct 2008 20:50:48 +0200 kbuild (1:0.1.3svn1610-1) unstable; urgency=low * new upstream version (Closes: #479046, #480012) * Remove patch cpu.diff that has been applied upstream. -- Torsten Werner Thu, 08 May 2008 20:20:07 +0200 kbuild (1:0.1.3svn1587-1) unstable; urgency=low * new upstream version * Add support for armv5tejl. -- Torsten Werner Thu, 17 Apr 2008 22:08:34 +0200 kbuild (1:0.1.2svn1393-2) unstable; urgency=high * Add patch to fix build on parisc. * Set urgency to high because we are fixing a FTBFS bug on 1 arch. -- Torsten Werner Thu, 10 Apr 2008 22:42:26 +0200 kbuild (1:0.1.2svn1393-1) unstable; urgency=low * new upstream release * Remove our patch because it has been applied upstream. -- Torsten Werner Sun, 09 Mar 2008 22:29:26 +0100 kbuild (1:0.1.2svn1377-5) unstable; urgency=low * Add support for s390x. -- Torsten Werner Sun, 30 Dec 2007 23:54:18 +0100 kbuild (1:0.1.2svn1377-4) unstable; urgency=low * Add support for mips. -- Torsten Werner Sun, 30 Dec 2007 22:53:09 +0100 kbuild (1:0.1.2svn1377-3) unstable; urgency=low * Add support for armv5tel. -- Torsten Werner Fri, 28 Dec 2007 23:39:11 +0100 kbuild (1:0.1.2svn1377-2) unstable; urgency=low * Add support for PA-RISC. -- Torsten Werner Fri, 28 Dec 2007 13:20:11 +0100 kbuild (1:0.1.2svn1377-1) unstable; urgency=low * Use version number (KBUILD_VERSION) from file Config.kmk for our package. * Always bootstrap kBuild because it is required. * Add Build-Depends: autoconf, automake, cvs. * Remove Build-Depends: doxygen, kbuild. -- Torsten Werner Sat, 22 Dec 2007 11:53:03 +0100 kbuild (1377-2) unstable; urgency=low * Add patch cpu.diff to support Debian's architectures. * Set LDFLAGS to -Wl,--as-needed to avoid linking of unneeded libraries. * Use the freshly built kmk for the installation step instead of the old one used for the build step. Rationale: that is a very basic test that the new kmk is really working. -- Torsten Werner Fri, 21 Dec 2007 18:06:38 +0100 kbuild (1377-1) unstable; urgency=low * new upstream version * Add some debugging output (gcc macros). * Update Homepage and Vcs headers in debian/control. * Change Standards-Version: 3.7.3. * Add manpage symlinks for kmk_redirect and kmk_test. -- Torsten Werner Fri, 21 Dec 2007 12:30:37 +0100 kbuild (1366-1) unstable; urgency=low * new upstream version - Does not ship kBuild.Doxyfile any more. * Remove all references to the obsoleted documentation files. (Closes: #454038) * Remove Depends: autoconf, automake1.9. -- Torsten Werner Mon, 03 Dec 2007 18:59:04 +0100 kbuild (1258-1) unstable; urgency=low * new upstream release * Remove the last patch because it has been applied upstream. -- Torsten Werner Sun, 28 Oct 2007 23:05:09 +0100 kbuild (1173-1) unstable; urgency=low * new upstream release * Fix the get-orig-source target in debian/rules. * Removed all patches that have been applied upstream. * Add more man page symlinks (kmk_cmp and kmk_md5sum). -- Torsten Werner Tue, 02 Oct 2007 21:59:51 +0200 kbuild (1096-1) unstable; urgency=low * new upstream version * Add kbuild to Build-Depends. * Fix clean target. (Closes: #442611) * Comment the patches. -- Torsten Werner Sun, 16 Sep 2007 19:06:22 +0200 kbuild (1080-2) unstable; urgency=low * Add patch arm.diff to support armv4l too. -- Torsten Werner Sat, 21 Jul 2007 12:26:46 +0200 kbuild (1080-1) unstable; urgency=low * New upstream version * Add a patch debug.diff that fixes debugging output. -- Torsten Werner Sat, 21 Jul 2007 08:27:12 +0200 kbuild (1060-1) unstable; urgency=low * New upstream version * Bootstrap every architecture again because some binaries are buggy. -- Torsten Werner Sat, 9 Jun 2007 07:42:44 +0200 kbuild (894-5) unstable; urgency=low * Remove directory 'out' in clean target. (Closes: #424426) -- Torsten Werner Sat, 19 May 2007 23:25:17 +0200 kbuild (894-4) unstable; urgency=low * Add hppa, ia64, mips, mipsel, powerpc, s390 to already bootstrapped architectures. * Add patch unused.diff to fix a build problem on alpha. -- Torsten Werner Mon, 14 May 2007 05:30:43 +0200 kbuild (894-3) unstable; urgency=low * Add yet another fix for the missing architectures. -- Torsten Werner Sat, 12 May 2007 18:32:30 +0200 kbuild (894-2) unstable; urgency=low * Complete the last (incomplete) patch. -- Torsten Werner Sat, 12 May 2007 15:20:34 +0200 kbuild (894-1) unstable; urgency=low * New upstream revision. * Use the revision number from debian/changelog for debian/orig-tar.sh. * Add Build-Depends: kbuild [amd64 i386]. * Add a patch to support all Debian architectures. -- Torsten Werner Sat, 12 May 2007 14:38:49 +0200 kbuild (893-1) unstable; urgency=low * Initial release (Closes: #422367) -- Torsten Werner Fri, 4 May 2007 20:35:40 +0200 kbuild-3686/dist/debian/kbuild.doc-base0000664000175000017500000000041715053010106017743 0ustar locutuslocutusDocument: kBuild Title: kmk Quick Reference Author: Knut St. Osmundsen Abstract: Brief description of all the features of the make program. Section: Devel/Tools Format: HTML Index: /usr/share/doc/kbuild/kmk-QuickReference-kmk.html Files: /usr/share/doc/kbuild*.htmlkbuild-3686/dist/debian/control0000664000175000017500000000263015053010106016474 0ustar locutuslocutusSource: kbuild Section: devel Priority: extra Maintainer: Torsten Werner Build-Depends: autoconf, automake, byacc, cdbs, cvs, debhelper (>= 5), flex, quilt Standards-Version: 3.8.0 Homepage: http://svn.netlabs.org/kbuild Vcs-Svn: https://bollin.googlecode.com/svn/kbuild/trunk Vcs-Browser: http://bollin.googlecode.com/svn/kbuild/trunk Package: kbuild Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: framework for writing simple makefiles for complex tasks The goals of the kBuild framework: - Similar behavior cross all supported platforms. - Flexibility, don't create unnecessary restrictions preventing ad-hoc solutions. - Makefile can very simple to write and maintain. . There are four concepts being tried out in the current kBuild incaration: - One configuration file for a subtree automatically included. - Target configuration templates as the primary mechanism for makefile simplification. - Tools and SDKs for helping out the templates with flexibility. - Non-recursive makefile method by using sub-makefiles. . kBuild does not provide any facilities for checking compiler/library/header configurations, that's not in its scope. If this is important for your project, check out the autoconf tool in the GNU build system. It is possible to use kBuild together with autoconf if you like, but you might just as well use the full GNU package. kbuild-3686/dist/debian/compat0000664000175000017500000000000215053010106016266 0ustar locutuslocutus5 kbuild-3686/dist/portage/0000775000175000017500000000000015053010106015307 5ustar locutuslocutuskbuild-3686/dist/portage/dev-util/0000775000175000017500000000000015053010106017040 5ustar locutuslocutuskbuild-3686/dist/portage/dev-util/kbuild/0000775000175000017500000000000015053010106020312 5ustar locutuslocutuskbuild-3686/dist/portage/dev-util/kbuild/kbuild-0.1.5.ebuild0000664000175000017500000000164215053010106023414 0ustar locutuslocutus# Copyright 1999-2008 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: /var/cvsroot/gentoo-x86/dev-util/kbuild/kbuild-0.1.4.ebuild,v 1.4 2008/10/28 18:11:02 jokey Exp $ EAPI=1 WANT_AUTOMAKE=1.9 inherit eutils autotools MY_P=kBuild-${PV}-src DESCRIPTION="A makefile framework for writing simple makefiles for complex tasks" HOMEPAGE="http://svn.netlabs.org/kbuild/wiki" SRC_URI="ftp://ftp.netlabs.org/pub/kbuild/${MY_P}.tar.gz" LICENSE="GPL-2 GPL-3 FDL-1.3" SLOT="0" KEYWORDS="amd64 x86" IUSE="" DEPEND="sys-devel/bison sys-devel/flex sys-devel/gettext" S=${WORKDIR}/${MY_P/-src} src_unpack() { unpack ${A} cd "${S}" } src_compile() { kBuild/env.sh --full \ make -f bootstrap.gmk NIX_INSTALL_DIR=/usr || die "bootstrap failed" } src_install() { kBuild/env.sh --full-with-bin kmk \ NIX_INSTALL_DIR=/usr \ PATH_INS="${D}" \ install || die "install failed" } kbuild-3686/dist/macports/0000775000175000017500000000000015053010106015476 5ustar locutuslocutuskbuild-3686/dist/macports/PortIndex0000664000175000017500000000124115053010106017333 0ustar locutuslocutuskbuild 336 variants universal description kBuild portdir devel/kbuild homepage http://svn.netlabs.org/kbuild epoch 0 platforms darwin name kbuild long_description {See http://svn.netlabs.org/kbuild (I'm lazy). Stable version, well, soon to be stable anyways.} maintainers bird-kBuild-spam@anduin.net categories devel version 0.1.3-beta revision 0 kbuild-head 310 variants universal description {kBuild subversion trunk} portdir devel/kbuild-head homepage http://svn.netlabs.org/kbuild epoch 0 platforms darwin name kbuild-head long_description {See http://svn.netlabs.org/kbuild (I'm lazy).} maintainers bird-kBuild-spam@anduin.net categories devel version 9999 revision 0 kbuild-3686/dist/macports/devel/0000775000175000017500000000000015053010106016575 5ustar locutuslocutuskbuild-3686/dist/macports/devel/kbuild/0000775000175000017500000000000015053010106020047 5ustar locutuslocutuskbuild-3686/dist/macports/devel/kbuild/Portfile0000664000175000017500000000204115053010106021553 0ustar locutuslocutus# $Id: Portfile 2413 2010-09-11 17:43:04Z bird $ # Very crude atm, everything is exec'ed. PortSystem 1.0 name kbuild version 0.1.5 categories devel maintainers bird-kBuild-spamx@anduin.net description kBuild long_description \ See http://svn.netlabs.org/kbuild (I'm lazy). homepage http://svn.netlabs.org/kbuild platforms darwin master_sites ftp://ftp.netlabs.org/pub/kbuild \ ftp://ftp.netlabs.org/incoming/kbuild distfiles kBuild-${version}-src.tar.gz checksums kBuild-${version}-src.tar.gz md5 df7e0905232e67728643f97d63cbf3f3 worksrcdir kBuild-${version} test.run no configure {} build { system "cd ${workpath}/${worksrcdir} && ./kBuild/env.sh --full gnumake -f bootstrap.gmk NIX_INSTALL_DIR=${prefix} " } test { system "cd ${workpath}/${worksrcdir} && ./kBuild/env.sh --full-with-bin kmk -C tests nothing " } destroot { system "cd ${workpath}/${worksrcdir} && ./kBuild/env.sh --full-with-bin kmk NIX_INSTALL_DIR=${prefix} PATH_INS=${destroot}/ " } kbuild-3686/dist/macports/devel/kbuild-head/0000775000175000017500000000000015053010106020746 5ustar locutuslocutuskbuild-3686/dist/macports/devel/kbuild-head/Portfile0000664000175000017500000000172015053010106022455 0ustar locutuslocutus# $Id: Portfile 2413 2010-09-11 17:43:04Z bird $ # Very crude atm, everything is exec'ed. PortSystem 1.0 name kbuild-head version 9999 categories devel maintainers bird-kBuild-spamx@anduin.net description kBuild subversion trunk long_description \ See http://svn.netlabs.org/kbuild (I'm lazy). homepage http://svn.netlabs.org/kbuild platforms darwin fetch.type svn svn.url http://svn.netlabs.org/repos/kbuild/trunk #svn.url svn://system360/svn-mirrors/kbuild/trunk worksrcdir trunk test.run no configure {} build { system "cd ${workpath}/${worksrcdir} && ./kBuild/env.sh --full gnumake -f bootstrap.gmk NIX_INSTALL_DIR=${prefix} " } test { system "cd ${workpath}/${worksrcdir} && ./kBuild/env.sh --full-with-bin kmk -C tests nothing " } destroot { system "cd ${workpath}/${worksrcdir} && ./kBuild/env.sh --full-with-bin kmk NIX_INSTALL_DIR=${prefix} PATH_INS=${destroot}/ " } kbuild-3686/Makefile.kmk0000664000175000017500000000521115053010106015123 0ustar locutuslocutus# $Id: Makefile.kmk 3637 2024-11-02 01:54:01Z bird $ ## @file # Top-Level Sub-Makefile for kBuild. # # # Copyright (c) 2005-2024 knut st. osmundsen # # This file is part of kBuild. # # kBuild 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 3 of the License, or # (at your option) any later version. # # kBuild 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 kBuild. If not, see # # SUB_DEPTH = . include $(KBUILD_PATH)/subheader.kmk include $(PATH_SUB_CURRENT)/src/Makefile.kmk ifdef NIX_INSTALL_DIR # # When doing a unix install, install all the kBuild scripts and docs. # TODO: Make this default and make it possible to disable it for in-tree development. # INSTALLS += kBuild-data kBuild-data_TEMPLATE = DATA kBuild-data_SOURCES := \ $(wildcard \ kBuild/*.kmk \ ) \ $(foreach src,\ $(wildcard \ kBuild/tools/*.kmk \ kBuild/sdks/*.kmk \ kBuild/units/*.kmk \ kBuild/msgstyles/*.kmk \ kBuild/templates/*.kmk),\ $(src)=>$(subst kBuild/,,$(src))) INSTALLS += kBuild-doc kBuild-doc_TEMPLATE = DOC kBuild-doc_SOURCES := $(wildcard \ kBuild/doc/*.txt \ kBuild/doc/*.html \ ) endif # # And install any binary only tools and dlls. # TODO: Ship env.sh and envos2.cmd / envwin.cmd where applicable. # INSTALLS += kBuild_bin kBuild_bin_INST = $(TEMPLATE_BIN_INST) kBuild_bin_SOURCES = kBuild_bin_SOURCES.os2 = \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc06.dll=>libc06.dll \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc061.dll=>libc061.dll \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc062.dll=>libc062.dll \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc063.dll=>libc063.dll \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc064.dll=>libc064.dll \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc065.dll=>libc065.dll if1of ($(KBUILD_TARGET), nt win) ifndef KBUILD_NEW_VCC kBuild_bin_SOURCES.$(KBUILD_TARGET) = \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/msvcr100.dll endif kBuild_bin_SOURCES.profile = \ D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/bin/kPrf2.dll \ D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/bin/kPrf2WinApiWrappers.dll endif include $(FILE_KBUILD_SUB_FOOTER) kbuild-3686/src/0000775000175000017500000000000015053010106013472 5ustar locutuslocutuskbuild-3686/src/Makefile.kmk0000664000175000017500000000320215053010104015706 0ustar locutuslocutus# $Id: Makefile.kmk 3650 2024-11-03 02:42:43Z bird $ ## @file # Sub-makefile for the source directory. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild 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 3 of the License, or # (at your option) any later version. # # kBuild 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 kBuild. If not, see # # SUB_DEPTH = .. include $(KBUILD_PATH)/subheader.kmk include $(PATH_SUB_CURRENT)/lib/Makefile.kmk if1of ($(KBUILD_TARGET), win) include $(PATH_SUB_CURRENT)/sed/Makefile.kmk else include $(PATH_SUB_CURRENT)/oldsed/Makefile.kmk endif include $(PATH_SUB_CURRENT)/kmk/Makefile.kmk include $(PATH_SUB_CURRENT)/kash/Makefile.kmk include $(PATH_SUB_CURRENT)/kDepPre/Makefile.kmk include $(PATH_SUB_CURRENT)/kObjCache/Makefile.kmk include $(PATH_SUB_CURRENT)/misc/Makefile.kmk ifeq ($(KBUILD_TARGET),win) include $(PATH_SUB_CURRENT)/kLibTweaker/Makefile.kmk include $(PATH_SUB_CURRENT)/kDeDup/Makefile.kmk if1of ($(KBUILD_TARGET_ARCH), x86 amd64) include $(PATH_SUB_CURRENT)/kWorker/Makefile.kmk endif endif if1of ($(KBUILD_TARGET), win) include $(PATH_SUB_CURRENT)/grep/Makefile.kmk endif include $(FILE_KBUILD_SUB_FOOTER) kbuild-3686/src/kLibTweaker/0000775000175000017500000000000015053010106015676 5ustar locutuslocutuskbuild-3686/src/kLibTweaker/Makefile.kmk0000664000175000017500000000214315053010106020117 0ustar locutuslocutus# $Id: Makefile.kmk 2791 2015-09-15 22:57:44Z bird $ ## @file # Sub-makefile for kLibTweaker. # # # Copyright (c) 2007-2015 knut st. osmundsen # # This file is part of kBuild. # # kBuild 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 3 of the License, or # (at your option) any later version. # # kBuild 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 kBuild. If not, see # # SUB_DEPTH = ../.. include $(PATH_KBUILD)/subheader.kmk PROGRAMS += kLibTweaker kLibTweaker_TEMPLATE = BIN kLibTweaker_DEFS.release = NASSERT kLibTweaker_SOURCES = kLibTweaker.c kLibTweaker_INCS = ../lib kLibTweaker_LIBS = \ $(LIB_KDEP) \ $(LIB_KUTIL) include $(KBUILD_PATH)/subfooter.kmk kbuild-3686/src/kLibTweaker/kLibTweaker.c0000664000175000017500000006005515053010106020254 0ustar locutuslocutus/* $Id: kLibTweaker.c 2791 2015-09-15 22:57:44Z bird $ */ /** @file * kLibTweaker - Import library tweaker for windows. */ /* * Copyright (c) 2007-2015 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #if 0 # define ELECTRIC_HEAP # include "../kmk/electric.h" # include "../kmk/electric.c" #endif #include #include #include #include #include #include #include #include "k/kLdrFmts/pe.h" /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ /** * Microsoft import library archive header. * * This has the same size as a COFF header, which is probably not a coincidence. */ typedef struct COFFIMPLIBHDR { KU16 uSig1; /* 0 */ KU16 uSig2; /* 0xffff */ KU16 uVersion; /* 0 */ KU16 uMachine; /* IMAGE_FILE_MACHINE_I386, ... */ KU32 uTimeDateStamp; KU32 cbData; KU16 uOrdinalOrHint; KU16 uFlags; } COFFIMPLIBHDR; /** * COFF symbol. * * This one has an odd size and will cause misaligned accesses on platforms * which cares about such. */ #pragma pack(1) typedef struct COFFSYMBOL { union { char e_name[8]; struct { KU32 e_zeros; /**< Zero to distinguish it from ascii name. */ KU32 e_offset; /**< String table offset. */ } e; } e; KU32 e_value; KI16 e_scnum; KU16 e_type; KU8 e_sclass; KU8 e_numaux; } COFFSYMBOL; #pragma pack() /** * Archive file header. */ typedef struct ARCHFILEHDR { char achName[16]; char achModtime[12]; char achOwnerId[6]; char achGroupId[6]; char achMode[8]; char achSize[10]; char achMagic[2]; } ARCHFILEHDR; /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ /** Whether verbose output is enabled. */ static unsigned g_cVerbosityLevel = 0; /** What to prefix the errors with. */ static char g_szErrorPrefix[128]; void FatalMsg(const char *pszFormat, ...) { va_list va; if (g_szErrorPrefix[0]) fprintf(stderr, "%s - fatal error: ", g_szErrorPrefix); else fprintf(stderr, "fatal error: "); va_start(va, pszFormat); vfprintf(stderr, pszFormat, va); va_end(va); } void FatalDie(const char *pszFormat, ...) { va_list va; if (g_szErrorPrefix[0]) fprintf(stderr, "%s - fatal error: ", g_szErrorPrefix); else fprintf(stderr, "fatal error: "); va_start(va, pszFormat); vfprintf(stderr, pszFormat, va); va_end(va); exit(1); } static int ErrorMsg(const char *pszFormat, ...) { va_list va; if (g_szErrorPrefix[0]) fprintf(stderr, "%s - error: ", g_szErrorPrefix); else fprintf(stderr, "error: "); va_start(va, pszFormat); vfprintf(stderr, pszFormat, va); va_end(va); return 1; } static void InfoMsg(unsigned uLevel, const char *pszFormat, ...) { if (uLevel <= g_cVerbosityLevel) { va_list va; if (g_szErrorPrefix[0]) fprintf(stderr, "%s - info: ", g_szErrorPrefix); else fprintf(stderr, "info: "); va_start(va, pszFormat); vfprintf(stderr, pszFormat, va); va_end(va); } } static void SetErrorPrefix(const char *pszPrefix, ...) { int cch; va_list va; va_start(va, pszPrefix); #if defined(_MSC_VER) || defined(__sun__) cch = vsprintf(g_szErrorPrefix, pszPrefix, va); if (cch >= sizeof(g_szErrorPrefix)) FatalDie("Buffer overflow setting error prefix!\n"); #else vsnprintf(g_szErrorPrefix, sizeof(g_szErrorPrefix), pszPrefix, va); #endif va_end(va); (void)cch; } #ifndef ELECTRIC_HEAP void *xmalloc(size_t cb) { void *pv = malloc(cb); if (!pv) FatalDie("out of memory (%d)\n", (int)cb); return pv; } void *xrealloc(void *pvOld, size_t cb) { void *pv = realloc(pvOld, cb); if (!pv) FatalDie("out of memory (%d)\n", (int)cb); return pv; } char *xstrdup(const char *pszIn) { char *psz; if (pszIn) { psz = strdup(pszIn); if (!psz) FatalDie("out of memory (%d)\n", (int)strlen(pszIn)); } else psz = NULL; return psz; } #endif void *xmallocz(size_t cb) { void *pv = xmalloc(cb); memset(pv, 0, cb); return pv; } /** * Adds the arguments found in the pszCmdLine string to argument vector. * * The parsing of the pszCmdLine string isn't very sophisticated, no * escaping or quotes. * * @param pcArgs Pointer to the argument counter. * @param ppapszArgs Pointer to the argument vector pointer. * @param pszCmdLine The command line to parse and append. * @param pszWedgeArg Argument to put infront of anything found in pszCmdLine. */ static void AppendArgs(int *pcArgs, char ***ppapszArgs, const char *pszCmdLine, const char *pszWedgeArg) { int i; int cExtraArgs; const char *psz; char **papszArgs; /* * Count the new arguments. */ cExtraArgs = 0; psz = pszCmdLine; while (*psz) { while (isspace(*psz)) psz++; if (!psz) break; cExtraArgs++; while (!isspace(*psz) && *psz) psz++; } if (!cExtraArgs) return; /* * Allocate a new vector that can hold the arguments. * (Reallocating might not work since the argv might not be allocated * from the heap but off the stack or somewhere... ) */ i = *pcArgs; *pcArgs = i + cExtraArgs + !!pszWedgeArg; papszArgs = xmalloc((*pcArgs + 1) * sizeof(char *)); *ppapszArgs = memcpy(papszArgs, *ppapszArgs, i * sizeof(char *)); if (pszWedgeArg) papszArgs[i++] = xstrdup(pszWedgeArg); psz = pszCmdLine; while (*psz) { size_t cch; const char *pszEnd; while (isspace(*psz)) psz++; if (!psz) break; pszEnd = psz; while (!isspace(*pszEnd) && *pszEnd) pszEnd++; cch = pszEnd - psz; papszArgs[i] = xmalloc(cch + 1); memcpy(papszArgs[i], psz, cch); papszArgs[i][cch] = '\0'; i++; psz = pszEnd; } papszArgs[i] = NULL; } static fpos_t kLibTweakerAsciiToSize(const char *pch, size_t cch) { fpos_t cb = 0; /* strip leading spaces. */ while (cch > 0 && (*pch == ' ' || *pch == '\t')) cch--, pch++; /* Convert decimal to binary. */ while (cch-- > 0) { char ch = *pch++; if (ch >= '0' && ch <= '9') { cb *= 10; cb += ch - '0'; } else break; } return cb; } static int kLibMyReadAt(FILE *pFile, void *pv, size_t cb, fpos_t off, int fEofOk) { if (fsetpos(pFile, &off) == 0) { size_t cbActual = fread(pv, 1, cb, pFile); if (cbActual == cb) return 0; if (!fEofOk || !feof(pFile)) ErrorMsg("fread returned %#lx, expected %#lx!\n", (unsigned long)cbActual, (unsigned long)cb); } else ErrorMsg("seek error!\n"); return 1; } static int kLibMyWriteAt(FILE *pFile, const void *pv, size_t cb, fpos_t off) { if (fsetpos(pFile, &off) == 0) { size_t cbActual = fwrite(pv, 1, cb, pFile); if (cbActual == cb) return 0; ErrorMsg("fwrite returned %#lx, expected %#lx!\n", (unsigned long)cbActual, (unsigned long)cb); } else ErrorMsg("seek error!\n"); return 1; } static int kLibFillNullThunkData(FILE *pFile, fpos_t cbFile, fpos_t offFileBytes) { size_t off; IMAGE_FILE_HEADER CoffHdr; IMAGE_SECTION_HEADER SecHdr; unsigned iSecHdr; fpos_t offCur; unsigned cbMachineWord; KU32 cbStrTab; COFFSYMBOL *paSymbols; int rcRet = 0; /* * Read the COFF file header and filter out unlikly files based on * section and symbol counts. */ if (cbFile <= sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_SECTION_HEADER) * 2 + 4) return 0; if (kLibMyReadAt(pFile, &CoffHdr, sizeof(CoffHdr), offFileBytes, 0) != 0) return 1; if ( CoffHdr.Machine != IMAGE_FILE_MACHINE_I386 && CoffHdr.Machine != IMAGE_FILE_MACHINE_AMD64) return 0; cbMachineWord = CoffHdr.Machine == IMAGE_FILE_MACHINE_I386 ? 4 : 8; if ( CoffHdr.NumberOfSections == 0 || CoffHdr.NumberOfSymbols == 0) return 0; off = sizeof(IMAGE_FILE_HEADER) + CoffHdr.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); if ((fpos_t)off >= cbFile) return 0; if ( CoffHdr.PointerToSymbolTable >= (KU64)cbFile || CoffHdr.PointerToSymbolTable < off) return 0; /* * Search for the .idata$5 section which the thunk data is usually found in. */ offCur = offFileBytes + sizeof(CoffHdr); for (iSecHdr = 0; iSecHdr < CoffHdr.NumberOfSections; iSecHdr++) { if (kLibMyReadAt(pFile, &SecHdr, sizeof(SecHdr), offCur, 0) != 0) return 1; InfoMsg(2, "#2: %.8s VirtualSize=%#lx\n", SecHdr.Name, SecHdr.SizeOfRawData); if ( !memcmp(SecHdr.Name, ".idata$5", 8) && SecHdr.SizeOfRawData == cbMachineWord) break; offCur += sizeof(SecHdr); } if (iSecHdr == CoffHdr.NumberOfSections) return 0; /* * Read in the symbo and string tables. */ off = CoffHdr.PointerToSymbolTable + CoffHdr.NumberOfSymbols * sizeof(COFFSYMBOL); if (kLibMyReadAt(pFile, &cbStrTab, sizeof(cbStrTab), offFileBytes + off, 0) != 0) return 1; InfoMsg(2, "#2: Found COFF file header, cbStrTab=%#x; off=%#lx NumberOfSymbols=%#x PointerToSymbolTable=%#x\n", cbStrTab, (long)off, CoffHdr.NumberOfSymbols, CoffHdr.PointerToSymbolTable); if ( cbStrTab <= 4U || cbStrTab >= 16*1024*1024U /* 16MB */ || (fpos_t)off + cbStrTab > cbFile) return 0; paSymbols = xmalloc(CoffHdr.NumberOfSymbols * sizeof(COFFSYMBOL) + cbStrTab + 1); if (kLibMyReadAt(pFile, paSymbols, CoffHdr.NumberOfSymbols * sizeof(COFFSYMBOL) + cbStrTab, offFileBytes + CoffHdr.PointerToSymbolTable, 0) == 0) { char *pchStrTab = (char *)&paSymbols[CoffHdr.NumberOfSymbols]; unsigned iSym; pchStrTab[cbStrTab] = '\0'; pchStrTab[0] = '\0'; pchStrTab[1] = '\0'; pchStrTab[2] = '\0'; pchStrTab[3] = '\0'; for (iSym = 0; iSym < CoffHdr.NumberOfSymbols; iSym++) { static char const s_szSuffix[] = "NULL_THUNK_DATA"; const char *pchName; size_t cchName; if (paSymbols[iSym].e.e.e_zeros != 0) { pchName = &paSymbols[iSym].e.e_name[0]; cchName = (char *)memchr(pchName, '\0', sizeof(paSymbols[iSym].e.e_name)) - pchName; if (cchName > sizeof(paSymbols[iSym].e.e_name)) cchName = sizeof(paSymbols[iSym].e.e_name); } else if ( paSymbols[iSym].e.e.e_offset == 0 || paSymbols[iSym].e.e.e_offset >= cbStrTab) continue; else { pchName = &pchStrTab[paSymbols[iSym].e.e.e_offset]; cchName = strlen(pchName); } if ( *pchName == 0x7f && cchName >= sizeof(s_szSuffix) && memcmp(&pchName[cchName - sizeof(s_szSuffix) + 1], s_szSuffix, sizeof(s_szSuffix) - 1) == 0) { if (pchName[cchName] == '\0') InfoMsg(1, "#2: Found '%s': value=%#lx\n", pchName, paSymbols[iSym].e_value); else InfoMsg(1, "#2: Found '%.8s': value=%#lx\n", pchName, paSymbols[iSym].e_value); if ( paSymbols[iSym].e_scnum > 0 && paSymbols[iSym].e_scnum <= CoffHdr.NumberOfSections) { if (paSymbols[iSym].e_scnum != iSecHdr + 1) InfoMsg(0, "#2: '%s' in section %u, expected %u\n", pchName, paSymbols[iSym].e_scnum, iSecHdr); else if (paSymbols[iSym].e_value != 0) InfoMsg(0, "#2: '%s' in value %#xu, expected 0x0\n", pchName, paSymbols[iSym].e_value); else if ( SecHdr.PointerToRawData < sizeof(CoffHdr) + CoffHdr.NumberOfSections * sizeof(IMAGE_SECTION_HEADER) || (fpos_t)SecHdr.PointerToRawData + cbMachineWord > cbFile) InfoMsg(0, "#2: Unexpected PointerToRawData value: %#x\n", SecHdr.PointerToRawData); else { union { KU8 ab[8]; KU32 u32; KU64 u64; } uBuf; uBuf.u64 = 0; off = offFileBytes + SecHdr.PointerToRawData; if (kLibMyReadAt(pFile, &uBuf, cbMachineWord, off, 0) == 0) { static const KU8 s_abGarbage[8] = { 0xaa, 0x99, 0x88, 0xbb, 0xbb, 0xaa, 0x88, 0x99 }; static const KU8 s_abZero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; if (memcmp(&uBuf, s_abZero,cbMachineWord) == 0) { rcRet = kLibMyWriteAt(pFile, s_abGarbage, cbMachineWord, off); if (!rcRet) InfoMsg(1, "#2: Updated '%s'\n", pchName); } else if (memcmp(&uBuf, s_abGarbage, cbMachineWord) == 0) { InfoMsg(1, "#2: Already modified '%s'\n", pchName); rcRet = 0; } else rcRet = ErrorMsg(0, "#2: Unexpected '%s' data: %02x %02x %02x %02x %02x %02x %02x %02x\n", pchName, uBuf.ab[0], uBuf.ab[1], uBuf.ab[2], uBuf.ab[3], uBuf.ab[4], uBuf.ab[5], uBuf.ab[6], uBuf.ab[7]); } break; } } } } } else rcRet = 1; free(paSymbols); return rcRet; } /** * Clears timestamps to avoid rebuilding stuff just because the internal * timestamps changed in an import library. */ static int kLibClearTimestamps(FILE *pFile, fpos_t offFileHdr, ARCHFILEHDR *pFileHdr, fpos_t cbFile, fpos_t offFileBytes) { union { IMAGE_FILE_HEADER CoffHdr; COFFIMPLIBHDR ImpLibHdr; } u; if (sizeof(u.CoffHdr) != sizeof(u.ImpLibHdr)) FatalDie("Oops!"); /* * Clear the timestamp in the library file header. */ memset(pFileHdr->achModtime, '0', sizeof(pFileHdr->achModtime)); if (kLibMyWriteAt(pFile, pFileHdr, sizeof(*pFileHdr), offFileHdr) != 0) return 1; /* * Clear the timestamp in the COFF header, if we find one. */ if (cbFile <= sizeof(IMAGE_FILE_HEADER)) return 0; if (kLibMyReadAt(pFile, &u.CoffHdr, sizeof(u.CoffHdr), offFileBytes, 0) != 0) return 1; if ( ( u.CoffHdr.Machine == IMAGE_FILE_MACHINE_I386 || u.CoffHdr.Machine == IMAGE_FILE_MACHINE_AMD64) && sizeof(IMAGE_FILE_HEADER) + u.CoffHdr.NumberOfSections * sizeof(IMAGE_SECTION_HEADER) <= (KU64)cbFile && u.CoffHdr.PointerToSymbolTable <= (KU64)cbFile) { InfoMsg(1, "Found COFF file header\n"); if (u.CoffHdr.TimeDateStamp != 0) { u.CoffHdr.TimeDateStamp = 0; return kLibMyWriteAt(pFile, &u.CoffHdr, sizeof(u.CoffHdr), offFileBytes); } } else if ( u.ImpLibHdr.uSig1 == 0 && u.ImpLibHdr.uSig2 == 0xffff && u.ImpLibHdr.uVersion == 0 && ( u.ImpLibHdr.uMachine == IMAGE_FILE_MACHINE_I386 || u.ImpLibHdr.uMachine == IMAGE_FILE_MACHINE_AMD64) && u.ImpLibHdr.cbData <= cbFile) { InfoMsg(1, "Found COFF import library header\n"); if (u.ImpLibHdr.uTimeDateStamp) { u.ImpLibHdr.uTimeDateStamp = 0; return kLibMyWriteAt(pFile, &u.ImpLibHdr, sizeof(u.ImpLibHdr), offFileBytes); } } else InfoMsg(1, "CoffHdr.Machine=%#x ImpLibHdr.Machine=%#x\n", u.CoffHdr.Machine, u.ImpLibHdr.uMachine); return 0; } static int kLibTweakerDoIt(const char *pszLib, int fClearTimestamps, int fFillNullThunkData) { int rcRet = 0; FILE *pFile = fopen(pszLib, "r+b"); if (pFile) { /* * Read the header. */ static char s_szMagic[] = "!\n"; union { char ab[1024]; IMAGE_FILE_HEADER CoffHdr; } uBuf; if ( fread(uBuf.ab, 1, sizeof(s_szMagic) - 1, pFile) == sizeof(s_szMagic) - 1 && memcmp(uBuf.ab, s_szMagic, sizeof(s_szMagic) - 1) == 0) { fpos_t offFileHdr = sizeof(s_szMagic) - 1; while (!feof(pFile)) { ARCHFILEHDR FileHdr; if (kLibMyReadAt(pFile, &FileHdr, sizeof(FileHdr), offFileHdr, 1) != 0) { if (feof(pFile)) break; rcRet = ErrorMsg("failed reading the file header (offset %ld)\n", (long)offFileHdr); break; } if ( FileHdr.achMagic[0] == 0x60 && FileHdr.achMagic[1] == 0x0a) { fpos_t const offFileBytes = offFileHdr + sizeof(FileHdr); /* * Convert the size from decimal to binary as we need it to skip to * the next file header. */ fpos_t const cb = kLibTweakerAsciiToSize(FileHdr.achSize, sizeof(FileHdr.achSize)); InfoMsg(1, "Found header at %#lx: cbFile=%#lx, bytes at %#lx\n", (unsigned long)offFileHdr, (unsigned long)cb, (unsigned long)offFileBytes); /* * Make the requested changes. */ if (fClearTimestamps) rcRet |= kLibClearTimestamps(pFile, offFileHdr, &FileHdr, cb, offFileBytes); if (fFillNullThunkData) rcRet |= kLibFillNullThunkData(pFile, cb, offFileBytes); /* * Skip to the next header. */ offFileHdr = offFileBytes + ((cb + 1) & ~(fpos_t)1); } else rcRet = ErrorMsg("invalid file header magic (offset %ld)\n", (long)offFileHdr); } } else rcRet = ErrorMsg("Didn't find '!\\n' magic in '%s' (or read error)\n", pszLib); if (fclose(pFile) != 0) rcRet = ErrorMsg("Error closing '%s'\n"); } else rcRet = ErrorMsg("Failed to open '%s' for read+write\n", pszLib); return rcRet; } /** * Prints a syntax error and returns the appropriate exit code * * @returns approriate exit code. * @param pszFormat The syntax error message. * @param ... Message args. */ static int SyntaxError(const char *pszFormat, ...) { va_list va; fprintf(stderr, "kObjCache: syntax error: "); va_start(va, pszFormat); vfprintf(stderr, pszFormat, va); va_end(va); return 1; } /** * Prints the usage. * @returns 0. */ static int usage(FILE *pOut) { fprintf(pOut, "syntax: kLibTweaker [-v|--verbose] [--clear-timestamps] \n" "\n"); return 0; } int main(int argc, char **argv) { char *psz; int i; int fClearTimestamps = 0; int fFillNullThunkData = 0; const char *pszLib = NULL; SetErrorPrefix("kLibTweaker"); /* * Arguments passed in the environmnet? */ psz = getenv("KLIBTWEAKER_OPTS"); if (psz) AppendArgs(&argc, &argv, psz, NULL); /** @todo Add the capability to produce import/stub libraries from ELF shared * objects that we can use while linking and break up linking dependencies * (i.e. not relink everything just because something in VBoxRT change that * didn't make any difference to the symbols it exports). */ /* * Parse the arguments. */ if (argc <= 1) return usage(stderr) + 1; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "--clear-timestamps")) fClearTimestamps = 1; else if (!strcmp(argv[i], "--fill-null_thunk_data")) fFillNullThunkData = 1; /* Standard stuff: */ else if (!strcmp(argv[i], "--help")) return usage(stderr); else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) g_cVerbosityLevel++; else if (!strcmp(argv[i], "-q") || !strcmp(argv[i], "--quiet")) g_cVerbosityLevel = 0; else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-?") || !strcmp(argv[i], "/h") || !strcmp(argv[i], "/?") || !strcmp(argv[i], "/help")) return usage(stdout); else if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) { printf("kLibTweaker - kBuild version %d.%d.%d ($Revision: 2791 $)\n" "Copyright (c) 2007-2015 knut st. osmundsen\n", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH); return 0; } else if (!strcmp(argv[i], "--")) { i++; if (i == argc) return SyntaxError("No library given!\n"); if (i + 1 != argc || pszLib) return SyntaxError("Only one library can be tweaked at a time!\n"); pszLib = argv[i]; break; } else if (argv[i][0] == '-') return SyntaxError("Doesn't grok '%s'!\n", argv[i]); else if (!pszLib) pszLib = argv[i]; else return SyntaxError("Only one library can be tweaked at a time!\n"); } if (!pszLib) return SyntaxError("No library given!\n"); return kLibTweakerDoIt(pszLib, fClearTimestamps, fFillNullThunkData); } kbuild-3686/src/oldsed/0000775000175000017500000000000015053010106014744 5ustar locutuslocutuskbuild-3686/src/oldsed/bootstrap.sh.in0000775000175000017500000000527115053010105017731 0ustar locutuslocutus#! /bin/sh # edit this to taste; note that you can also override via the environment: case "$CC" in "") CC=cc esac if test -f config.h; then :; else echo "Creating basic config.h..." cat >config.h <<'END_OF_CONFIG_H' /* A bootstrap version of config.h, for systems which can't auto-configure due to a lack of a working sed. If you are on a sufficiently odd machine you may need to hand-tweak this file. Regardless, once you get a working version of sed you really should re-build starting with a run of "configure", as the bootstrap version is almost certainly more crippled than it needs to be on your machine. */ #define PACKAGE "sed" #define VERSION "@VERSION@-boot" #define SED_FEATURE_VERSION "@SED_FEATURE_VERSION@" #define BOOTSTRAP 1 /* Define if your compiler/headers don't support const. */ #undef const /* Undefine if headers have conflicting definition. */ #define mbstate_t int /* Toggle if you encounter errors in lib/mkstemp.c. */ #define HAVE_UNISTD_H #define HAVE_FCNTL_H #undef HAVE_SYS_FILE_H #undef HAVE_IO_H /* Undefine if or has conflicting definition. */ #define size_t unsigned #define ssize_t int /* If your antique compiler doesn't grok ``void *'', then #define VOID char */ #undef VOID /* All other config.h.in options intentionally omitted. Report as a bug if you need extra "#define"s in here. */ END_OF_CONFIG_H fi # tell the user what we're doing from here on... set -x -e # the ``|| exit 1''s are for fail-stop; set -e doesn't work on some systems rm -f lib/*.o sed/*.o sed/sed cd lib || exit 1 rm -f regex.h cp regex_.h regex.h ${CC} -DHAVE_CONFIG_H -I.. -I. -c alloca.c ${CC} -DHAVE_CONFIG_H -I.. -I. -c getline.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c getopt.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c getopt1.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c memchr.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c memcmp.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c memmove.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c mkstemp.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c strverscmp.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c obstack.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c regex.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c strerror.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c utils.c || exit 1 cd ../sed || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c sed.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c fmt.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c compile.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c execute.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c mbcs.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c regexp.c || exit 1 ${CC} -o sed *.o ../lib/*.o || exit 1 kbuild-3686/src/oldsed/Makefile.kmk0000664000175000017500000000511615053010105017167 0ustar locutuslocutus# $Id: Makefile.kmk 3062 2017-09-30 11:26:21Z bird $ ## @file # Sub-Makefile for kmk_sed. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild 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 3 of the License, or # (at your option) any later version. # # kBuild 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 kBuild. If not, see # # SUB_DEPTH = ../.. include $(KBUILD_PATH)/subheader.kmk # # kmk_sed # PROGRAMS += kmk_sed kmk_sed_TEMPLATE = BIN kmk_sed_DEPS = \ $(kmk_sed_0_OUTDIR)/config.h \ $(kmk_sed_0_OUTDIR)/regex.h kmk_sed_CLEAN = $(kmk_sed_DEPS) kmk_sed_CFLAGS.solaris = -std=gnu99 kmk_sed_INCS = \ $(kmk_sed_0_OUTDIR) \ . \ lib \ intl kmk_sed_DEFS = \ HAVE_CONFIG_H ifdef KBUILD_SOLARIS_10 kmk_sed_CFLAGS += -std=gnu99 endif kmk_sed_SOURCES = \ sed/sed.c \ lib/regex.c \ sed/compile.c \ sed/execute.c \ sed/regexp.c \ sed/fmt.c \ sed/mbcs.c \ lib/getopt1.c \ lib/getopt.c \ lib/utils.c kmk_sed_SOURCES.darwin = \ lib/strverscmp.c \ lib/obstack.c \ lib/getline.c kmk_sed_SOURCES.dragonfly = \ lib/strverscmp.c \ lib/obstack.c \ lib/getline.c kmk_sed_SOURCES.freebsd = \ lib/strverscmp.c \ lib/obstack.c \ lib/getline.c kmk_sed_SOURCES.haiku = \ lib/strverscmp.c \ lib/obstack.c kmk_sed_SOURCES.netbsd = \ lib/strverscmp.c \ lib/obstack.c \ lib/getline.c kmk_sed_SOURCES.openbsd = \ lib/strverscmp.c \ lib/obstack.c \ lib/getline.c kmk_sed_SOURCES.solaris = \ lib/strverscmp.c \ lib/obstack.c \ lib/getline.c kmk_sed_SOURCES.win = \ lib/strverscmp.c \ lib/obstack.c \ lib/mkstemp.c \ lib/getline.c \ ../lib/startuphacks-win.c kmk_sed_LIBS.win = $(LIB_KUTIL) # for stdout optimizations. include $(FILE_KBUILD_SUB_FOOTER) # # Use checked in config.h instead of running ./configure for it. # kmk_sed_config.h.$(KBUILD_TARGET) := $(kmk_sed_DEFPATH)/config.h.$(KBUILD_TARGET) $(kmk_sed_0_OUTDIR)/config.h: $(kmk_sed_config.h.$(KBUILD_TARGET)) | $(call DIRDEP,$(kmk_sed_0_OUTDIR)) $(CP) -f $^ $@ # # Use the regex lib shipped with sed and not anything installed on the system. # $(kmk_sed_0_OUTDIR)/regex.h: $(kmk_sed_DEFPATH)/lib/regex_.h | $(call DIRDEP,$(kmk_sed_0_OUTDIR)) $(CP) -f $^ $@ kbuild-3686/src/oldsed/po/0000775000175000017500000000000015053010106015362 5ustar locutuslocutuskbuild-3686/src/oldsed/po/fr.gmo0000664000175000017500000002337715053010106016511 0ustar locutuslocutus•ÞQ¤m,àúá,Ü5 7?\w`Ôu 5l «b V {Y Ò~ , «º ;% ö  3 Md j Ï ã ú3$Kp‚®·#Öú0BT fHs¼Öõ!5J(_ˆ#¦Ê$ê#)BM2à ×ø*5*`‹« »#É#í&8,W„-²àö* @Ng€h›&/+L[A¨êcj‘Θ`ùay‚Ûˆ^¼çà¤+…±Ðîo |$«Ðð. 8Rp€%“)¹ ã   # 7 K _\ n# Ë ï!4!.!c!‚J! $!ë+"'"<8"d%"0"ÃJ"ô>#?#~#œ,#¼%#é<$7$L,$„$± $Ä'$Ò'$ú.%"%%Q7%w %¯%ÐE%í&3&I &X&f&~&—&¨&¿(&Ö$DQ"!@=ELB5?43 .N;2(:9%< /CP',KM #6+017F H*->J O8& I)GA If no -e, --expression, -f, or --file option is given, then the first non-option argument is taken as the sed script to interpret. All remaining arguments are names of input files; if no input files are specified, then the standard input is read. --help display this help and exit --version output version information and exit --posix disable all GNU extensions. -R, --regexp-perl use Perl 5's regular expressions syntax in the script. -e script, --expression=script add the script to the commands to be executed -f script-file, --file=script-file add the contents of script-file to the commands to be executed -i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if extension supplied) -l N, --line-length=N specify the desired line-wrap length for the `l' command -n, --quiet, --silent suppress automatic printing of pattern space -r, --regexp-extended use extended regular expressions in the script. -s, --separate consider files as separate rather than as a single continuous long stream. -u, --unbuffered load minimal amounts of data from the input files and flush the output buffers more often %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]... `e' command not supported`}' doesn't want any addressesbased on GNU sed version %s can't find label for jump to `%s'cannot remove %s: %scannot rename %s: %scannot specify modifiers on empty regexpcommand only uses one addresscomments don't accept any addressescouldn't edit %s: is a terminalcouldn't edit %s: not a regular filecouldn't open file %s: %scouldn't open temporary file %s: %scouldn't write %d item to %s: %scouldn't write %d items to %s: %sdelimiter character is not a single-byte charactererror in subprocessexpected \ after `a', `c' or `i'expected newer version of sedextra characters after commandinvalid reference \%d on `s' command's RHSinvalid usage of +N or ~N as first addressinvalid usage of line address 0missing commandmultiple `!'smultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandno previous regular expressionnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %sstrings for `y' command are different lengthssuper-sed version %s unexpected `,'unexpected `}'unknown command: `%c'unknown option to `s'unmatched `{'unterminated `s' commandunterminated `y' commandunterminated address regexProject-Id-Version: sed 4.1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2004-07-12 00:09+0200 Last-Translator: Gaël Quéri Language-Team: French MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8-bit Plural-Forms: nplurals=2; plural=(n > 1); Si aucune option -e, --expression, -f ou --file n'est donnée, le premier argument qui n'est pas une option sera pris comme étant le script sed à interpréter. Tous les arguments restants sont les noms des fichiers d'entrée; si aucun fichier d'entrée n'est spécifiée, l'entrée standard est lue. --help afficher cette aide et sortir --version afficher les informations de version du logiciel et sortir --posix désactiver toutes les extensions GNU. -R, --regexp-perl utiliser la syntaxe des expressions régulières de Perl 5 dans le script. -e script, --expression=script ajouter le script aux commandes à être exécutées -f fichier-script, --file=fichier-script ajouter le contenu de fichier-script aux commandes à être exécutées -i[SUFFIXE], --in-place[=SUFFIXE] éditer les fichiers à leur place (fait une sauvegarde si l'extension est fournie) -l N, --line-length=N spécifier la longueur de coupure de ligne désirée pour la commande `l' -n, --quiet, --silent supprimer l'écriture automatique de l'espace des motifs -r, --regexp-extended utiliser la syntaxe des expressions régulières étendues dans le script. -s, --separate considérer les fichiers comme séparés plutôt que comme un simple flux long et continu. -u, --unbuffered charger des quantités minimales de données depuis les fichiers d'entrée et libérer les tampons de sortie plus souvent %s Ce logiciel est libre; voir les sources pour les conditions de reproduction. AUCUNE garantie n'est donnée; y compris pour des RAISONS COMMERCIALES ou pour RÉPONDRE A UN BESOIN PARTICULIER, à l'étendue permise par la loi. %s: -e expression n°%lu, caractère %lu: %s %s: impossible de lire %s: %s %s: fichier %s ligne %lu: %s : n'a besoin d'aucune adresseRapporter toutes anomalies à: %s. N'oubliez pas d'inclure le mot ``%s'' quelque-part dans la zone ``Subject:'' GNU sed version %s Référence arrière invalideNom de classe de caractères invalideCaractère de collation invalideContenu de \{\} invalideL'expression régulière précédente est invalideFin d'intervalle invalideExpression régulière invalideMémoire épuiséePas de concordancePas d'expression régulière précédenteFin prématurée d'une expression régulièreExpression régulière trop grandeSuccèsAntislash de protection( ou \( non refermé) ou \) non refermé[ ou [^ non refermé\{ non referméUtilisation: %s [OPTION]... {script-seulement-si-pas-d'autre-script} [fichier-d'entrée]... la commande `e' n'est pas supportée`}' n'a besoin d'aucune adressefondé sur GNU sed version %s impossible de trouver l'étiquette pour sauter à `%s'impossible de supprimer %s: %simpossible de renommer %s: %simpossible de spécifier des modifieurs sur une expression rationnelle videla commande n'utilise qu'une adresseles commentaires n'acceptent aucune adresseimpossible d'éditer %s: est un terminalimpossible d'éditer %s: ce n'est pas un fichier régulierimpossible d'ouvrir le fichier %s: %simpossible d'ouvrir le fichier temporaire %s: %simpossible d'écrire %d item à %s: %simpossible d'écrire %d items à %s: %sle caractère délimiteur n'est pas un caractère à un seul octeterreur dans le sous-processus\ attendu après `a', `c' ou `i'une version plus récente de sed est attenduecaractères inutiles après la commanderéférence \%d invalide dans le côté droit de la commande `s'utilisation invalide de +N ou ~N comme première adresseutilisation invalide de l'adresse de ligne 0commande manquante`!' multiplesplusieurs options `g' à la commande `s'plusieurs options `p' à la commande `s'plusieurs options numériques à la commande `s'pas d'expression régulière précédentel'option numérique de la comande `s' ne peut être nullel'option `e' n'est pas supportéeerreur de lecture sur %s: %sles chaînes destinées à la commande `y' ont des longueurs différentessuper-sed version %s `,' inattendue`}' inattenducommande inconnue: `%c'option inconnue pour `s'`{' non referméecommande `s' inachevéecommande `y' inachevéeexpression régulière d'adresse inachevéekbuild-3686/src/oldsed/po/el.gmo0000664000175000017500000000442115053010106016467 0ustar locutuslocutus•Þ¤,ˆº‰%Dj›d¸<Vu#‰#­&Ñ,ø%>HSõœ(’"»Þüƒ(Æ!å& &G*n;™Õõ     %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. No previous regular expression`e' command not supported`}' doesn't want any addresseserror in subprocessmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %sProject-Id-Version: GNU sed 3.02.80 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2002-03-08 12:57+0000 Last-Translator: Simos Xenitellis Language-Team: Greek MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-7 Content-Transfer-Encoding: 8bit %s Áõôü ôï ðñüãñáììá åßíáé åëåýèåñï ëïãéóìéêü· äåßôå ôïí ðçãáßï êþäéêá ãéá ôïõò êáíïíéóìïýò áíôéãñáöÞò. Äåí õðÜñ÷åé ÊÁÌÉÁ ÅÃÃÕÇÓÇ· ïýôå áêüìá ãéá ËÅÉÔÏÕÑÃÉÊÏÔÇÔÁ Þ ÊÁÔÁËËÇËÏÔÇÔÁ ÃÉÁ ÅÍÁ ÓÕÃÊÅÊÑÉÌÅÍÏ ÓÊÏÐÏ, ìÝ÷ñé ôï óçìåßï ðïõ åðéôñÝðåé ï íüìïò. %s: -e Ýêöñáóç #%lu, ÷áñáêôÞñáò %lu: %s %s: áäõíáìßá óôçí áíÜãíùóç %s: %s %s: áñ÷åßï %s ãñáììÞ %lu: %s : äåí ÷ñåéÜæåôáé äéåõèýíóåéòÁíáöïñÝò óöáëìÜôùí ìÝóù çëåêôñïíéêïý ôá÷õäñïìåßïõ óôï: %s . ÐñïóÝîôå íá óõìðåñéëÜâåôå ôç ëÝîç ``%s'' êÜðïõ óôï ðåäßï ``Subject:''. Äåí âñÝèçêå ðñïçãïýìåíç êáíïíéêÞ Ýêöñáóçäåí õðïóôçñßæåôáé ç åíôïëÞ `e'ôï `}' äåí ÷ñåéÜæåôáé äéåõèýíóåéòóöÜëìá óôç õðïäéáäéêáóßáðïëëáðëÝò åðéëïãÝò `g' óôçí åíôïëÞ `s'ðïëëáðëÝò åðéëïãÝò `p' óôçí åíôïëÞ `s'ðïëëáðëüò åðéëïãÝò áñéèìïý óôçí åíôïëÞ `s'ç åðéëïãÞ áñéèìïý óôçí åíôïëÞ `s' äåí ìðïñåß íá åßíáé ìçäÝíäåí õðïóôçñßæåôáé ç åðéëïãÞ `e'óöÜëìá áíÜãíùóçò óôï %s: %skbuild-3686/src/oldsed/po/ru.gmo0000664000175000017500000002306515053010106016522 0ustar locutuslocutus•ÞQ¤m,àúá,Ü5 7?\w`Ôu 5l «b V {Y Ò~ , «º ;% ö  3 Md j Ï ã ú3$Kp‚®·#Öú0BT fHs¼Öõ!5J(_ˆ#¦Ê$ê#)BM2à ×ø*5*`‹« »#É#í&8,W„-²àö* @Ng€v›,3C;we³[qu}çdeWÊc"„†™ ¥&· Þÿ,nH·Ê#ç )0H y!š¼Í%Ý/$3X `™²ËYÞ 8, V ƒ* ¢ Í ç=!$!E4!j)!Ÿ0!É!ú("Q"B4"”"É""Þ ##"*#?=#j*#¨#Ó#ç*#þ*$)/$T%$„:$ª$å%)%%@%U%o%‰%£%Á%Õ%ï+& $DQ"!@=ELB5?43 .N;2(:9%< /CP',KM #6+017F H*->J O8& I)GA If no -e, --expression, -f, or --file option is given, then the first non-option argument is taken as the sed script to interpret. All remaining arguments are names of input files; if no input files are specified, then the standard input is read. --help display this help and exit --version output version information and exit --posix disable all GNU extensions. -R, --regexp-perl use Perl 5's regular expressions syntax in the script. -e script, --expression=script add the script to the commands to be executed -f script-file, --file=script-file add the contents of script-file to the commands to be executed -i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if extension supplied) -l N, --line-length=N specify the desired line-wrap length for the `l' command -n, --quiet, --silent suppress automatic printing of pattern space -r, --regexp-extended use extended regular expressions in the script. -s, --separate consider files as separate rather than as a single continuous long stream. -u, --unbuffered load minimal amounts of data from the input files and flush the output buffers more often %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]... `e' command not supported`}' doesn't want any addressesbased on GNU sed version %s can't find label for jump to `%s'cannot remove %s: %scannot rename %s: %scannot specify modifiers on empty regexpcommand only uses one addresscomments don't accept any addressescouldn't edit %s: is a terminalcouldn't edit %s: not a regular filecouldn't open file %s: %scouldn't open temporary file %s: %scouldn't write %d item to %s: %scouldn't write %d items to %s: %sdelimiter character is not a single-byte charactererror in subprocessexpected \ after `a', `c' or `i'expected newer version of sedextra characters after commandinvalid reference \%d on `s' command's RHSinvalid usage of +N or ~N as first addressinvalid usage of line address 0missing commandmultiple `!'smultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandno previous regular expressionnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %sstrings for `y' command are different lengthssuper-sed version %s unexpected `,'unexpected `}'unknown command: `%c'unknown option to `s'unmatched `{'unterminated `s' commandunterminated `y' commandunterminated address regexProject-Id-Version: sed-4.1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2004-07-07 17:54+0300 Last-Translator: Pavel Maryanov Language-Team: Russian MIME-Version: 1.0 Content-Type: text/plain; charset=KOI8-R Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n>1; X-Generator: KBabel 1.3 åÓÌÉ ÏÐÃÉÑ -e, --expression, -f, ÉÌÉ --file ÎÅ ÕËÁÚÁÎÁ, ÔÏÇÄÁ ÐÅÒ×ÙÊ ÎÅÏÐÃÉÏÎÁÌØÎÙÊ ÁÒÇÕÍÅÎÔ ÂÅÒÅÔÓÑ ËÁË ÓËÒÉÐÔ sed ÄÌÑ ÉÎÔÅÒÐÒÅÔÁÃÉÉ. ÷ÓÅ ÏÓÔÁ×ÛÉÅÓÑ ÁÒÇÕÍÅÎÔÙ Ñ×ÌÑÀÔÓÑ ÉÍÅÎÁÍÉ ×ÈÏÄÎÙÈ ÆÁÊÌÏ×; ÅÓÌÉ ×ÈÏÄÎÙÅ ÆÁÊÌÙ ÎÅ ÕËÁÚÁÎÙ, ÔÏÇÄÁ ÞÉÔÁÅÔÓÑ ÓÔÁÎÔÁÒÔÎÙÊ ××ÏÄ. --help ×Ù×ÏÄ ÜÔÏÊ ÓÐÒÁ×ËÉ É ×ÙÈÏÄ --version ×Ù×ÏÄ ÉÎÆÏÒÍÁÃÉÉ Ï ×ÅÒÓÉÉ É ×ÙÈÏÄ --posix ÏÔËÌÀÞÅÎÉÅ ×ÓÅÈ ÒÁÓÛÉÒÅÎÉÊ GNU. -R, --regexp-perl ÉÓÐÏÌØÚÏ×ÁÎÉÅ × ÓËÒÉÐÔÅ ÓÉÎÔÁËÓÉÓÁ ÒÅÇÕÌÑÒÎÙÈ ×ÙÒÁÖÅÎÉÊ Perl 5. -e script, --expression=script ÄÏÂÁ×ÌÅÎÉÅ ÓËÒÉÐÔÁ × ÉÓÐÏÌÎÑÅÍÙÅ ËÏÍÁÎÄÙ -f script-file, --file=script-file ÄÏÂÁ×ÌÅÎÉÅ ÓÏÄÅÒÖÉÍÏÇÏ ÆÁÊÌÁ-ÓËÒÉÐÔÁ × ÉÓÐÏÌÎÑÅÍÙÅ ËÏÍÁÎÄÙ -i[óõææéëó], --in-place[=óõææéëó] ÒÅÄÁËÔÉÒÏ×ÁÎÉÅ ÆÁÊÌÏ× ÎÁ ÍÅÓÔÅ (ÓÏÚÄÁÅÔ ËÏÐÉÀ, ÅÓÌÉ ÕËÁÚÁÎÏ ÒÁÓÛÉÒÅÎÉÅ) -l N, --line-length=N ÕËÁÚÁÎÉÅ ÖÅÌÁÅÍÏÊ ÄÌÉÎÙ ÐÅÒÅÎÏÓÉÍÏÊ ÓÔÒÏËÉ ÄÌÑ ËÏÍÁÎÄÙ `l' -n, --quiet, --silent ÐÏÄÁ×ÌÅÎÉÅ Á×ÔÏÍÁÔÉÞÅÓËÏÇÏ ×Ù×ÏÄÁ ÐÒÏÍÅÖÕÔËÏ× -r, --regexp-extended ÉÓÐÏÌØÚÏ×ÁÎÉÅ × ÓËÒÉÐÔÅ ÒÁÓÛÉÒÅÎÎÙÈ ÒÅÇÕÌÑÒÎÙÈ ×ÙÒÁÖÅÎÉÊ. -s, --separate ÄÏÐÕÝÅÎÉÅ, ÞÔÏ ÆÁÊÌÙ ÒÁÚÄÅÌÅÎÙ, Á ÎÅ × ×ÉÄÅ ÏÄÎÏÇÏ ÄÌÉÎÎÏÇÏ ÎÅÐÒÅÒÙ×ÎÏÇÏ ÐÏÔÏËÁ. -u, --unbuffered ÚÁÇÒÕÚËÁ ÍÉÎÉÍÁÌØÎÏÇÏ ÏÂßÅÍÁ ÄÁÎÎÙÈ ÉÚ ×ÈÏÄÎÙÈ ÆÁÊÌÏ× É ÂÏÌÅÅ ÞÁÓÔÙÊ ÓÂÒÏÓ ÎÁ ÄÉÓË ×ÙÈÏÄÎÙÈ ÂÕÆÅÒÏ× %s üÔÏ Ó×ÏÂÏÄÎÏÅ ÐÒÏÇÒÁÍÍÎÏÅ ÏÂÅÓÐÅÞÅÎÉÅ; ÕÓÌÏ×ÉÑ ÅÇÏ ËÏÐÉÒÏ×ÁÎÉÑ ÓÍÏÔÒÉÔÅ × ÉÓÈÏÄÎÙÈ ÔÅËÓÔÁÈ. îÅ ÐÒÅÄÏÓÔÁ×ÌÑÅÔÓÑ îéëáëïê ÇÁÒÁÎÔÉÉ; ÄÁÖÅ ÇÁÒÁÎÔÉÉ ðòéçïäîïóôé äìñ ðòïäáöé ÉÌÉ ðòéíåîéíïóôé äìñ ëïîëòåôîïê ãåìé, × ÔÏÊ ÍÅÒÅ, × ËÏÔÏÒÏÊ ÜÔÏ ÍÏÖÅÔ ÂÙÔØ ÄÏÐÕÝÅÎÏ ÚÁËÏÎÏÄÁÔÅÌØÓÔ×ÏÍ. %s: -e ×ÙÒÁÖÅÎÉÅ #%lu, ÓÉÍ×ÏÌ %lu: %s %s: ÎÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ %s: %s %s: ÆÁÊÌ %s ÓÔÒÏËÁ %lu: %s `:' ÎÅ ÄÏÐÕÓËÁÅÔ ÕËÁÚÁÎÉÑ ËÁËÉÈ-ÌÉÂÏ ÁÄÒÅÓÏ×ïÔÞÅÔÙ Ï ÏÛÉÂËÁÈ ÏÔÐÒÁ×ÌÑÊÔÅ ÐÏ ÁÄÒÅÓÕ: %s . õÂÅÄÉÔÅÓØ, ÞÔÏ ×ËÌÀÞÉÌÉ ÇÄÅ-ÌÉÂÏ × ÐÏÌÅ ``ôÅÍÁ:'' ÓÌÏ×Ï ``%s''. GNU sed ×ÅÒÓÉÑ %s îÅÄÏÐÕÓÔÉÍÁÑ ÏÂÒÁÔÎÁÑ ÓÓÙÌËÁîÅÄÏÐÕÓÔÉÍÏÅ ÉÍÑ ÄÌÑ ËÌÁÓÓÁ ÓÉÍ×ÏÌÁîÅÄÏÐÕÓÔÉÍÙÊ ÓÉÍ×ÏÌ ÓÒÁ×ÎÅÎÉÑîÅÄÏÐÕÓÔÉÍÏÅ ÓÏÄÅÒÖÉÍÏÅ × \{\}îÅÄÏÐÕÓÔÉÍÏÅ ÐÒÅÄÛÅÓÔ×ÕÀÝÅÅ ÒÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅîÅÄÏÐÕÓÔÉÍÏÅ ÏËÏÎÞÁÎÉÅ ÄÉÁÐÁÚÏÎÁîÅÄÏÐÕÓÔÉÍÏÅ ÒÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅðÁÍÑÔØ ÉÓÞÅÒÐÁÎÁîÅÔ ÓÏÏÔ×ÅÓÔ×ÉÑîÅÔ ÐÒÅÄÙÄÕÝÅÇÏ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑðÒÅÖÄÅ×ÒÅÍÅÎÎÏÅ ÏËÏÎÞÁÎÉÅ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑòÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅ ÓÌÉÛËÏÍ ÂÏÌØÛÏÅõÓÐÅÛÎÏúÁ×ÅÒÛÁÀÝÁÑ ÏÂÒÁÔÎÁÑ ËÏÓÁÑ ÞÅÒÔÁîÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ ( or \(îÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ ) ÉÌÉ \)îÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ [ ÉÌÉ [^îÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ \{éÓÐÏÌØÚÏ×ÁÎÉÅ: %s [ïðãéñ]... {ÔÏÌØËÏ-ÓËÒÉÐÔ-ÅÓÌÉ-ÎÅÔ-ÄÒÕÇÏÇÏ-ÓËÒÉÐÔÁ} [×ÈÏÄÎÏÊ-ÆÁÊÌ]... ËÏÍÁÎÄÁ `e' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ`}' ÎÅ ÄÏÐÕÓËÁÅÔ ÕËÁÚÁÎÉÑ ËÁËÉÈ-ÌÉÂÏ ÁÄÒÅÓÏ×ÏÓÎÏ×ÁÎ ÎÁ GNU sed ×ÅÒÓÉÉ %s ÎÅ×ÏÚÍÏÖÎÏ ÎÁÊÔÉ ÍÅÔËÕ ÄÌÑ ÐÅÒÅÈÏÄÁ Ë `%s'ÎÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ %s: %sÎÅ×ÏÚÍÏÖÎÏ ÐÅÒÅÉÍÅÎÏ×ÁÔØ %s: %sÎÅ×ÏÚÍÏÖÎÏ ÕËÁÚÁÔØ ÍÏÄÉÆÉËÁÔÏÒÙ × ÐÕÓÔÏÍ ÒÅÇÕÌÑÒÎÏÍ ×ÙÒÁÖÅÎÉÉËÏÍÁÎÄÁ ÉÓÐÏÌØÚÕÅÔ ÔÏÌØËÏ ÏÄÉÎ ÁÄÒÅÓËÏÍÍÅÎÔÁÒÉÉ ÎÅ ÄÏÐÕÓËÁÀÔ ÕËÁÚÁÎÉÑ ËÁËÉÈ-ÌÉÂÏ ÁÄÒÅÓÏ×ÎÅ×ÏÚÍÏÖÎÏ ÒÅÄÁËÔÉÒÏ×ÁÔØ %s: ÜÔÏ ÔÅÒÍÉÎÁÌÎÅ×ÏÚÍÏÖÎÏ ÒÅÄÁËÔÉÒÏ×ÁÔØ %s: ÜÔÏ ÎÅ ÏÂÙÞÎÙÊ ÆÁÊÌÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ %s: %sÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ×ÒÅÍÅÎÎÙÊ ÆÁÊÌ %s: %sÎÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ %d ÜÌÅÍÅÎÔ × %s: %sÎÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ %d ÜÌÅÍÅÎÔÏ× × %s: %sÓÉÍ×ÏÌ-ÒÁÚÄÅÌÉÔÅÌØ ÎÅ Ñ×ÌÑÅÔÓÑ ÏÄÎÏÂÁÊÔÏ×ÙÍ ÓÉÍ×ÏÌÏÍÏÛÉÂËÁ × ÐÏÄÐÒÏÃÅÓÓÅÏÖÉÄÁÌÁÓØ \ ÐÏÓÌÅ `a', `c' ÉÌÉ `i'ÏÖÉÄÁÌÁÓØ ÂÏÌÅÅ ÎÏ×ÁÑ ×ÅÒÓÉÑ sedÌÉÛÎÉÅ ÓÉÍ×ÏÌÙ ÐÏÓÌÅ ËÏÍÁÎÄÙÎÅÄÏÐÕÓÔÉÍÁÑ ÓÓÙÌËÁ \%d ÎÁ RHS ËÏÍÁÎÄÙ `s'ÉÓÐÏÌØÚÏ×ÁÎÉÅ +N ÉÌÉ ~N × ËÁÞÅÓÔ×Å ÐÅÒ×ÏÇÏ ÁÄÒÅÓÁ ÎÅÄÏÐÕÓÔÉÍÏÎÅÄÏÐÕÓÔÉÍÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÓÔÒÏËÉ ÁÄÒÅÓÁ 0ÏÔÓÕÔÓÔ×ÕÅÔ ËÏÍÁÎÄÁÎÅÓËÏÌØËÏ ÓÉÍ×ÏÌÏ× `!'ÎÅÓËÏÌØËÏ ÍÏÄÉÆÉËÁÔÏÒÏ× `g' Ó ËÏÍÁÎÄÏÊ `s'ÎÅÓËÏÌØËÏ ÍÏÄÉÆÉËÁÔÏÒÏ× `p' Ó ËÏÍÁÎÄÏÊ `s'ÎÅÓËÏÌØËÏ ÞÉÓÌÏ×ÙÈ ÍÏÄÉÆÉËÁÔÏÒÏ× Ó ËÏÍÁÎÄÏÊ `s'ÎÅÔ ÐÒÅÄÙÄÕÝÅÇÏ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑÞÉÓÌÏ×ÏÊ ÍÏÄÉÆÉËÁÔÏÒ ÄÌÑ ËÏÍÁÎÄÙ `s' ÎÅ ÍÏÖÅÔ ÂÙÔØ ÎÕÌÅ×ÙÍÏÐÃÉÑ `e' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑÏÛÉÂËÁ ÞÔÅÎÉÑ %s: %sÓÔÒÏËÉ ÄÌÑ ËÏÍÁÎÄÙ `y' ÉÍÅÀÔ ÒÁÚÎÕÀ ÄÌÉÎÕsuper-sed ×ÅÒÓÉÑ %s ÎÅÐÒÅÄ×ÉÄÅÎÎÙÊ ÓÉÍ×ÏÌ `,'ÎÅÐÒÅÄ×ÉÄÅÎÎÙÊ ÓÉÍ×ÏÌ `}'ÎÅÉÚ×ÅÓÔÎÁÑ ËÏÍÁÎÄÁ: `%c'ÎÅÉÚ×ÅÓÔÎÙÊ ÍÏÄÉÆÉËÁÔÏÒ Ë `s'ÎÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ `{'ÎÅÚÁ×ÅÒÛÅÎÎÁÑ ËÏÍÁÎÄÁ `s'ÎÅÚÁ×ÅÒÛÅÎÎÁÑ ËÏÍÁÎÄÁ `y'ÎÅÚÁ×ÅÒÛÅÎÎÏÅ ÁÄÒÅÓÎÏÅ ÒÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅkbuild-3686/src/oldsed/po/sv.gmo0000664000175000017500000002251415053010106016522 0ustar locutuslocutus•ÞQ¤m,àúá,Ü5 7?\w`Ôu 5l «b V {Y Ò~ , «º ;% ö  3 Md j Ï ã ú3$Kp‚®·#Öú0BT fHs¼Öõ!5J(_ˆ#¦Ê$ê#)BM2à ×ø*5*`‹« »#É#í&8,W„-²àö* @Ng€i›ð2ö6);`^œeû†aèYyZÓV.€…†x$+E]†{,E_%xžµ Ð Ü è$ .JSsŠ¡¸IÇ  * J+ j – ®3 Ë# ÿ$!#&!H*!o!š'!¸O!à)"0"Z&"m "”"µ0"Ò3#"#7#Z #j$#t$#™&#¾ #å2$$9$P+$b$Ž $¤ $°$¼$Ñ$ç$÷%&%%$DQ"!@=ELB5?43 .N;2(:9%< /CP',KM #6+017F H*->J O8& I)GA If no -e, --expression, -f, or --file option is given, then the first non-option argument is taken as the sed script to interpret. All remaining arguments are names of input files; if no input files are specified, then the standard input is read. --help display this help and exit --version output version information and exit --posix disable all GNU extensions. -R, --regexp-perl use Perl 5's regular expressions syntax in the script. -e script, --expression=script add the script to the commands to be executed -f script-file, --file=script-file add the contents of script-file to the commands to be executed -i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if extension supplied) -l N, --line-length=N specify the desired line-wrap length for the `l' command -n, --quiet, --silent suppress automatic printing of pattern space -r, --regexp-extended use extended regular expressions in the script. -s, --separate consider files as separate rather than as a single continuous long stream. -u, --unbuffered load minimal amounts of data from the input files and flush the output buffers more often %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]... `e' command not supported`}' doesn't want any addressesbased on GNU sed version %s can't find label for jump to `%s'cannot remove %s: %scannot rename %s: %scannot specify modifiers on empty regexpcommand only uses one addresscomments don't accept any addressescouldn't edit %s: is a terminalcouldn't edit %s: not a regular filecouldn't open file %s: %scouldn't open temporary file %s: %scouldn't write %d item to %s: %scouldn't write %d items to %s: %sdelimiter character is not a single-byte charactererror in subprocessexpected \ after `a', `c' or `i'expected newer version of sedextra characters after commandinvalid reference \%d on `s' command's RHSinvalid usage of +N or ~N as first addressinvalid usage of line address 0missing commandmultiple `!'smultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandno previous regular expressionnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %sstrings for `y' command are different lengthssuper-sed version %s unexpected `,'unexpected `}'unknown command: `%c'unknown option to `s'unmatched `{'unterminated `s' commandunterminated `y' commandunterminated address regexProject-Id-Version: sed 4.1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2004-07-11 11:45+0200 Last-Translator: Christian Rose Language-Team: Swedish MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); Om ingen av flaggorna -e, --expression, -f, eller --file ges, blir det första argumentet som inte är en flagga det sed-skript som tolkas. Alla återstående argument är namn på indatafiler. Om inga indatafiler är angivna läses standard in. --help visa denna hjälptext och avsluta --version visa versionsinformation och avsluta --posix inaktivera alla GNU-utökningar. -R, --regexp-perl använd Perl 5:s syntax för reguljära uttryck i skriptet. -e skript, --expression=skript lägg till skript till de kommandon som ska utföras -f skriptfil, --file=skriptfil lägg till innehållet i skriptfil till de kommandon som ska utföras -i[ÄNDELSE], --in-place[=ÄNDELSE] redigera filer på plats (skapar säkerhetskopia om ändelse tillhandahålls) -l N, --line-length=N ange önskad radbrytningslängd för "l"-kommandot -n, --quiet, --silent förhindrar automatisk utskrift av mönsterutrymme -r, --regexp-extended använd utökade reguljära uttryck i skriptet. -s, --separate betrakta filer som separata istället för som en kontinuerlig lång dataström. -u, --unbuffered läs in minimala mängder data från indatafilerna och töm utdatabufferterna oftare %s (Följande text är en informell översättning som enbart tillhandahålls i informativt syfte. För alla juridiska tolkningar gäller den engelska originaltexten.) Det här är fri programvara; se källkoden angående villkor för kopiering. Det finns INGEN garanti; inte ens för SÄLJBARHET eller LÄMPLIGHET FÖR NÅGOT SPECIELLT ÄNDAMÅL, i den omfattning som medges av gällande lag. %s: -e uttryck #%lu, tecken %lu: %s %s: kan inte läsa %s: %s %s: fil %s rad %lu: %s : vill inte ha några adresserRapportera fel till: %s . Ange ordet "%s" på något ställe i "Ärende:"-fältet. Skicka anmärkningar på översättningen till . GNU sed version %s Ogiltig bakåtreferensOgiltigt teckenklassnamnOgiltigt sorteringsteckenOgiltigt innehåll i \{\}Ogiltigt föregående reguljärt uttryckOgiltigt intervallslutOgiltigt reguljärt uttryckMinnet slutIngen träffInget tidigare reguljärt uttryckFör tidigt slut på reguljärt uttryckReguljärt uttryck för stortLyckadesEftersläpande omvänt snedstreckObalanserad ( eller \(Obalanserad ) eller \)Obalanserad [ eller [^Obalanserad \{Användning: %s [FLAGGA]... {skript-endast-om-inga-andra} [indatafil]... kommandot "e" stöds inte"}" vill inte ha några adresserbaserad på GNU sed version %s kan inte hitta etiketten för hopp till "%s"kan inte ta bort %s: %skan inte byta namn på %s: %skan inte ange modifierare på tomt reguljärt uttryckkommandot använder endast en adresskommentarer accepterar inga adresserkunde inte redigera %s: är en terminalkunde inte redigera %s: inte en vanlig filkunde inte öppna filen %s: %skunde inte öppna temporära filen %s: %skunde inte skriva %d objekt till %s: %skunde inte skriva %d objekt till %s: %savgränsningstecknet är inte en ensam bytefel i underprocess\ förväntades efter "a", "c" eller "i"nyare version av sed förväntadesextra tecken efter kommandotogiltig referens \%d på "s"-kommandots högersidaogiltig användning av +N eller ~N som första adressfelaktig användning av radadress 0kommando saknasflera "!"flera "g"-flaggor till "s"-kommandotflera "p"-flaggor till "s"-kommandotflera sifferflaggor till "s"-kommandotinget tidigare reguljärt uttrycksifferflagga till kommandot "s" får inte vara nollflaggan "e" stöds inteläsfel vid %s: %ssträngarna för kommandot "y" är olika långasuper-sed version %s oväntat ","oväntad "}"okänt kommando: "%c"flaggan okänd för "s"obalanserad "{"oavslutat "s"-kommandooavslutat "y"-kommandooavslutat reguljärt uttryck för adresskbuild-3686/src/oldsed/po/hr.po0000664000175000017500000002310315053010106016332 0ustar locutuslocutus# Translation of sed to Croatian # Copyright (C) 2002 Free Software Foundation, Inc. # Denis Lackovi , 2002. # msgid "" msgstr "" "Project-Id-Version: sed 3.02a\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2002-06-14 15:17-01\n" "Last-Translator: Denis Lackovic \n" "Language-Team: Croatian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n==1?0:1);\n" "X-Generator: TransDict server\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "ViÅ¡estruki `!'" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "NeoÄekivani `,'" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "Ne mogu koristiti +N ili ~N kao prvu adresu" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "Neuparena `{'" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "NeoÄekivana `}'" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "ViÅ¡ak znakova nakon komande" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' ne želi nikakve adrese" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": ne želi nikakve adrese" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Komentari ne primaju adrese" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Nedostaje naredba" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Naredba koristi samo jednu adresu" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "NezavrÅ¡eni regularni izraz adrese" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "NezavrÅ¡ena `s' naredba" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "NezavrÅ¡ena `y' naredba" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Nepoznata opcija za `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "viÅ¡estruke `p' opcije za `s' naredbu" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "viÅ¡estruke `g' opcije za `s' naredbu" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "viÅ¡ak opcija za za `s' naredbu" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "broj opcija za naredbu `s' ne smije biti nula" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "znakovni nizovi za naredbu y su razliÄitih duljina" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Neispravna uporaba adresnog modifikatora" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Nepoznata naredba:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: datoteka %s redak %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e izraz #%lu, znak %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Ne mogu naći labelu na koju bi trebalo skoÄiti `%s'" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: ne mogu Äitati %s: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Ne mogu otvoriti datoteku %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Ne mogu otvoriti datoteku %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Ne mogu otvoriti datoteku %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Nedostaje prethodni regularni izraz" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "E-mail bug prijave (na engleskom) poÅ¡aljite na: %s .\n" "UkljuÄite rijeÄ ``%s'' u polju ``Subject:''.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Ovo je slobodni softver; pogledajte kod kako biste doznali uvjete " "kopiranja.\n" " NEMA garancije;\n" "Äak ni tvrdnje o ISPLATIVOSTI ili POGODNOSTI ZA NEKU SVRHU.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: ne mogu Äitati %s: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Ne mogu otvoriti datoteku %s" #: lib/utils.c:220 #, fuzzy, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "Ne mogu upisati %d item%s u %s: %s" msgstr[1] "Ne mogu upisati %d item%s u %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "GreÅ¡ka u Äitanju na %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: ne mogu Äitati %s: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "" #: lib/regcomp.c:135 msgid "No match" msgstr "" #: lib/regcomp.c:138 #, fuzzy msgid "Invalid regular expression" msgstr "Nedostaje prethodni regularni izraz" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "" #: lib/regcomp.c:153 #, fuzzy msgid "Unmatched [ or [^" msgstr "Neuparena `{'" #: lib/regcomp.c:156 #, fuzzy msgid "Unmatched ( or \\(" msgstr "Neuparena `{'" #: lib/regcomp.c:159 #, fuzzy msgid "Unmatched \\{" msgstr "Neuparena `{'" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "" #: lib/regcomp.c:171 #, fuzzy msgid "Invalid preceding regular expression" msgstr "Nedostaje prethodni regularni izraz" #: lib/regcomp.c:174 #, fuzzy msgid "Premature end of regular expression" msgstr "Nedostaje prethodni regularni izraz" #: lib/regcomp.c:177 #, fuzzy msgid "Regular expression too big" msgstr "Nedostaje prethodni regularni izraz" #: lib/regcomp.c:180 #, fuzzy msgid "Unmatched ) or \\)" msgstr "Neuparena `{'" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Nedostaje prethodni regularni izraz" kbuild-3686/src/oldsed/po/cs.gmo0000664000175000017500000000372115053010106016476 0ustar locutuslocutus•Þ „ì0º1%ì)Cd`Å#ä#&,,S€D•çÚ Âãú¤3 Ø0ù0*2[)ޏ    %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. `}' doesn't want any addressesmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zeroread error on %s: %sProject-Id-Version: sed 3.02.80 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2001-08-05 19:52+02:00 Last-Translator: Vladimir Michl Language-Team: Czech MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-2 Content-Transfer-Encoding: 8bit %s Toto je volné programové vybavení; podmínky pro kopírování a roz¹iøování naleznete ve zdrojových textech. Toto programové vybavení je zcela BEZ ZÁRUKY, a to i bez záruky PRODEJNOSTI nebo VHODNOSTI PRO NÌJAKÝ KONKRÉTNÍ ÚÈEL. %s: -e výraz #%lu, znak %lu: %s %s: %s nelze èíst: %s %s: soubor %s, øádek %lu: %s : nechce jakoukoliv adresuChyby v programu oznamujte na adrese: %s (anglicky). Kamkoliv do polo¾ky ``Subject:'' vlo¾te ``%s''. Pøipomínky k pøekladu zasílejte na adresu (èesky). `}' nevy¾aduje jakoukoliv adresuvícenásobné pou¾ití pøepínaèe `g' s pøíkazem `s'vícenásobné pou¾ití pøepínaèe `p' s pøíkazem `s'pøíkaz `s' mù¾e mít maximálnì jednu èíselnou volbuèíselná volba pøíkazu `s' nemù¾e být nulachyba pøi ètení z %s: %skbuild-3686/src/oldsed/po/ro.po0000664000175000017500000002472715053010106016356 0ustar locutuslocutus# Mesajele în limba românã pentru sed. # Copyright (C) 2003 Free Software Foundation, Inc. # Acest fiºier este distribuit sub aceeaºi licenþã ca ºi pachetul sed. # Laurentiu Buzdugan , 2003. # # msgid "" msgstr "" "Project-Id-Version: sed 4.0.8\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2003-11-22 12:00-0500\n" "Last-Translator: Laurentiu Buzdugan \n" "Language-Team: Romanian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-2\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "`!'-uri multiple" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "`,' neaºteptat" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "Nu se poate folosi +N ºi ~N ca prima adresã" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "`{' fãrã pereche" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "`}' neaºteptat" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Extra caractere dupã comandã" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "Este aºteptat \\ dupã `a', `c' sau `i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' nu vrea nici o adresã" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": nu vrea nici o adresã" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Comentariile nu acceptã nici o adresã" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Comandã absentã" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Comanda foloseºte numai o adresã" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Adresã regex neterminatã" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Comandã `s' neterminatã" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Comandã `y' neterminatã" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Opþiune necunoscutã pentru `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "multiple opþiuni `p' pentru comanda `s'" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "multiple opþiuni `g' pentru comanda `s'" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "numãr multiplu de opþiuni pentru comanda `s'" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "numãrul de opþiuni pentru comanda `s' nu poate fi zero" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "ºirurile pentru comanda y au lungimi diferite" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "am aºteptat o versiune mai recentã de sed" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Comanda foloseºte numai o adresã" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Comandã necunoscutã:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: fiºierul %s linia %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e expresia #%lu, caracterul %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Nu pot gãsi eticheta pentru saltul la `%s'" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: nu pot citi %s: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Nu am putut deschide fiºierul %s: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Nu am putut deschide fiºierul %s: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Nu am putut deschide fiºierul temporar %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "eroare în subproces" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "opþiunea `e' nu e suportatã" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "comanda `e' nu e suportatã" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Nici o expresie regularã anterioarã" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "Nu se pot specifica modificatori pentru regexp vidã" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Referinþã invalidã \\%d pentru RHS-ul comanzii `s'" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " foloseºte sintaxa expresiilor regulare din Perl 5 în " "script.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " foloseºte sintaxa expresiilor regulare din Perl 5 în " "script.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Raportaþi bug-uri prin e-mail la: %s .\n" "Fiþi siguri cã includeþi ``%s'' undeva în câmpul ``Subject:''.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "versiunea super-sed %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "bazat pe GNU sed versiunea 3.02.80\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed versiunea %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Acesta este software liber; vedeþi codul sursã pentru condiþiile de " "copiere.\n" "Nu existã NICI o garanþie; nici mãcar pentru VANDABILITATE sau POTRIVIRE \n" "PENTRU UN ANUME SCOP, conform legilor în vigoare.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: nu pot citi %s: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Nu am putut deschide fiºierul %s: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "Nu am putut scrie %d articol în %s: %s" msgstr[1] "Nu am putut scrie %d articole în %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "eroare citire pentru %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: nu pot citi %s: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "Succes" #: lib/regcomp.c:135 msgid "No match" msgstr "Nici o potrivire" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Expresie regularã incorectã" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Colaþiune de caractere incorectã" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Nume de clasã de caractere incorect" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Backslash în coadã" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Referinþã înapoi incorectã" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "[ sau [^ fãrã pereche" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "( sau \\( fãrã pereche" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "\\{ fãrã pereche" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Conþinut incorect pentru \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Sfârºit de interval incorect" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Memorie epuizatã" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Expresie regularã precedentã incorectã" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Sfârºit prematur al expresiei regulare" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Expresie regularã prea mare" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr ") sau \\) fãrã pereche" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Nici o expresie regularã anterioarã" kbuild-3686/src/oldsed/po/ro.gmo0000664000175000017500000000772215053010106016516 0ustar locutuslocutus•Þ'T5Œ`\aº¾%yŸ¶ÐdíRf}š¶$Îó 1:#Y}˜ ³Å× éöB/r†#¤#È&ì,@Yn„a Ì v) C m … ¤f ¼ # 9# T x ™& · Þ û  (# 9& ] „   § º Ð æ ü 'NA)¤'Î'ö,6K‚žº!"  ' # % &$ -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessexpected newer version of sedmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: sed 4.0.8 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2003-11-22 12:00-0500 Last-Translator: Laurentiu Buzdugan Language-Team: Romanian MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-2 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); -R, --regexp-perl foloseºte sintaxa expresiilor regulare din Perl 5 în script. %s Acesta este software liber; vedeþi codul sursã pentru condiþiile de copiere. Nu existã NICI o garanþie; nici mãcar pentru VANDABILITATE sau POTRIVIRE PENTRU UN ANUME SCOP, conform legilor în vigoare. %s: -e expresia #%lu, caracterul %lu: %s %s: nu pot citi %s: %s %s: fiºierul %s linia %lu: %s : nu vrea nici o adresãRaportaþi bug-uri prin e-mail la: %s . Fiþi siguri cã includeþi ``%s'' undeva în câmpul ``Subject:''. GNU sed versiunea %s Referinþã înapoi incorectãNume de clasã de caractere incorectColaþiune de caractere incorectãConþinut incorect pentru \{\}Expresie regularã precedentã incorectãSfârºit de interval incorectExpresie regularã incorectãMemorie epuizatãNici o potrivireNici o expresie regularã anterioarãSfârºit prematur al expresiei regulareExpresie regularã prea mareSuccesBackslash în coadã( sau \( fãrã pereche) sau \) fãrã pereche[ sau [^ fãrã pereche\{ fãrã perechecomanda `e' nu e suportatã`}' nu vrea nici o adresãNu am putut scrie %d articol în %s: %sNu am putut scrie %d articole în %s: %seroare în subprocesam aºteptat o versiune mai recentã de sedmultiple opþiuni `g' pentru comanda `s'multiple opþiuni `p' pentru comanda `s'numãr multiplu de opþiuni pentru comanda `s'numãrul de opþiuni pentru comanda `s' nu poate fi zeroopþiunea `e' nu e suportatãeroare citire pentru %s: %sversiunea super-sed %s kbuild-3686/src/oldsed/po/sl.gmo0000664000175000017500000001014615053010106016506 0ustar locutuslocutus•Þ'T5Œ`\aº¾%yŸ¶ÐdíRf}š¶$Îó 1:#Y}˜ ³Å× éöB/r†#¤#È&ì,@YnÑ„^ VÚ µ  ± Ï ðg  m „ ž ¼ Ð# è!  . I ^ j& Š ± Ê Ò ï/Oi|¦šA'U!}!Ÿ'Á2é2M!"  ' # % &$ -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessexpected newer version of sedmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: sed 4.0.6 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2003-04-02 17:20+0200 Last-Translator: Primo¾ Peterlin Language-Team: Slovenian MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-2 Content-Transfer-Encoding: 8-bit Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0); -R, --regexp-perl dovoli uporabo regularnih izrazov, ki jih podpira Perl 5 %s To je prost program; pogoji, pod katerimi ga lahko uporabljate, razmno¾ujete in raz¹irjate so navedeni v izvorni kodi. Za program ni NOBENEGA JAMSTVA, niti jamstev USTREZNOSTI ZA PRODAJO ali PRIMERNOSTI ZA UPORABO. %s: -e izraz #%lu, znak %lu: %s %s: %s ni mo¾no prebrati: %s %s: datoteka %s vrstica %lu: %s : ne zahteva naslovaSporoèila o napakah po¹ljite na %s . Poskrbite, da bo nekje v polju ,,Subject`` nastopal izraz ,,%s``. GNU sed, razlièica %s Neveljavni povratni sklicNeveljavno ime razreda znakovZnaka izven abecedeNeveljavna vsebina \{\}Neveljaven prej¹nji regularni izrazNeveljavna zgornja meja intervalaNeveljavni regularni izrazZmanjkalo pomnilnikaNi ujemanjaPrej¹nji regularni izraz manjkaPredèasni zakljuèek regularnega izrazaRegularni izraz prevelikUspe¹noZakljuèna obrnjena po¹evnicaOklepaj ( ali \( brez zaklepajaOklepaj ) ali \) brez zaklepajaOklepaj [ ali [^ brez zaklepajaOklepaj \{ brez zaklepajaUkaz ,e` ni podprtZaklepaj } ne zahteva naslovani mogoèe zapisati %d elementov na %s: %sni mogoèe zapisati %d elementa na %s: %sni mogoèe zapisati %d elementov na %s: %sni mogoèe zapisati %d elementov na %s: %sNapaka v podprocesuprièakovana novej¹a izdaja programa sedveèterne izbire "g" pri ukazu "s"veèterne izbire "p" pri ukazu "s"veèterne ¹tevilène izbire pri ukazu "s"¹tevilèna izbira pri ukazu "s" mora biti nenièelnaIzbira ,e` ni podprtanapaka pri branju z %s: %ssuper-sed, razlièica %s kbuild-3686/src/oldsed/po/it.gmo0000664000175000017500000002277115053010106016513 0ustar locutuslocutus•ÞR¬m<ðúñ,ì57O\‡`äu El »b (V ‹Y â~ < »º K%  , C ]d z ß ó 'C$[€’­¾Ç#æ %-@Rd vHƒÌæ!#EZ(o˜#¶Ú$ú#9B]2 Ó ç&*E*p›» Ë#Ù#ý&!HW,v£¼-Ñÿ$3I _m†Ÿjº"%-H?v?¶Xö\Or¬šeºY `z€Û[\Ÿ+~ªÊäfücx+#»7ß*Bb‚“*²(Ý")42g›®P  . H4 h  ºD Ø !"!>)!a0!‹!!¼,!ÞU" &"a"ˆ"£'"À'"è=#.#N$#}#¢ #³##À##ä)$$2*$J6$u$¬$Ç6$ã% %1 %>%K%e%€%“%­1%Ç$ER"!@=FMB5?43 .O;2(:9%< /CQ',LN #6+017G DI*->K P8& J)HA If no -e, --expression, -f, or --file option is given, then the first non-option argument is taken as the sed script to interpret. All remaining arguments are names of input files; if no input files are specified, then the standard input is read. --help display this help and exit --version output version information and exit --posix disable all GNU extensions. -R, --regexp-perl use Perl 5's regular expressions syntax in the script. -e script, --expression=script add the script to the commands to be executed -f script-file, --file=script-file add the contents of script-file to the commands to be executed -i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if extension supplied) -l N, --line-length=N specify the desired line-wrap length for the `l' command -n, --quiet, --silent suppress automatic printing of pattern space -r, --regexp-extended use extended regular expressions in the script. -s, --separate consider files as separate rather than as a single continuous long stream. -u, --unbuffered load minimal amounts of data from the input files and flush the output buffers more often %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]... `e' command not supported`}' doesn't want any addressesbased on GNU sed version %s can't find label for jump to `%s'cannot remove %s: %scannot rename %s: %scannot specify modifiers on empty regexpcommand only uses one addresscomments don't accept any addressescouldn't edit %s: is a terminalcouldn't edit %s: not a regular filecouldn't open file %s: %scouldn't open temporary file %s: %scouldn't write %d item to %s: %scouldn't write %d items to %s: %sdelimiter character is not a single-byte charactererror in subprocessexpected \ after `a', `c' or `i'expected newer version of sedextra characters after commandinvalid reference \%d on `s' command's RHSinvalid usage of +N or ~N as first addressinvalid usage of line address 0missing commandmultiple `!'smultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandno input filesno previous regular expressionnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %sstrings for `y' command are different lengthssuper-sed version %s unexpected `,'unexpected `}'unknown command: `%c'unknown option to `s'unmatched `{'unterminated `s' commandunterminated `y' commandunterminated address regexProject-Id-Version: sed 4.0a Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2002-11-26 12:44+0100 Last-Translator: Paolo Bonzini Language-Team: Italian MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8-bit Plural-Forms: nplurals=2; plural=n != 1; Se non è usata nessuna delle opzioni -e, --expression, -f o --file allora il primo argomento che non è una opzione sarà usato come lo script sed da interpretare. Tutti gli argomenti rimanenti sono nomi di file di input; se non sono specificati file di input sarà letto lo standard input. --help mostra questo aiuto ed esce --version stampa le informazioni sulla versione ed esce --posix disabilita tutte le estensioni GNU. -R, --regexp-perl usa la sintassi Perl 5 per le espressioni regolari -e script, --expression=script aggiunge lo script ai comandi da eseguire -f script-file, --file=file-script aggiunge il contenuto di file-script ai comandi da eseguire -i[SUFFIX], --in-place[=SUFFIX] scrive il risultato sul file originale (facendo una copia se è fornita un'estensione) -l N, --line-length=N specifica la lunghezza delle linee generate dal comando `l' -n, --quiet, --silent sopprime la stampa automatica del pattern space -r, --regexp-extended usa la sintassi di `egrep' per le espressioni regolari -s, --separate considera i file di input come separati invece che come un unico file lungo. -u, --unbuffered carica e visualizza i dati una a pezzetti piu' piccoli %s Questo è software libero; si veda il sorgente per le condizioni di copiatura. NON c'è garanzia; neppure di COMMERCIABILITA' o IDONEITA' AD UN PARTICOLARE SCOPO, nei limiti permessi dalla legge. %s: espressione -e #%lu, carattere %lu: %s %s: impossibile leggere %s: %s %s: file %s riga %lu: %s : non accetta indirizziSegnalare eventuali bug a: %s . Assicurarsi di includere la parola ``%s'' nell'oggetto del messaggio. GNU sed versione %s Riferimento non validoNome non valido per una classe di caratteriCarattere di ordinamento non validonumero di ripetizioni specificato tra graffe non validoEspressione regolare precedente non validaFine dell'intervallo non validaEspressione regolare non validaMemoria esauritaNessuna corrispondenza trovataOccorre un'espressione regolare precedenteFine prematura dell'espressione regolareEspressione regolare troppo grandeSuccessoBarra rovesciata alla fine dell'espressione regolare`(' o `\(' non bilanciata`)' o `\)' non bilanciata`[' non bilanciata`\{' non bilanciataUtilizzo: %s [OPZIONE]... {script-se-nessun-altro-specificato} [input-file]... comando `e' non supportato`}' non accetta indirizzibasato su GNU sed versione %s impossibile trovare un'etichetta per il salto a `%s'impossibile rimuovere %s: %simpossibile rinominare %s: %snon è possibile specificare dei modificatori per l'espressione vuotail comando usa solo un indirizzoi commenti non accettano indirizziimpossibile modificare %s: è un terminaleimpossibile modificare %s: non è un file normaleimpossibile aprire il file %s: %simpossibile aprire il file temporaneo %s: %sImpossibile scrivere %d elemento su %s: %sImpossibile scrivere %d elementi su %s: %sil carattere delimitatore è multi-byteerrore in un sottoprocessoatteso \ dopo `a', `c' o `i'attesa una versione piu' recente di sedci sono altri caratteri dopo il comandoriferimento non valido \%d nel secondo membro del comando `s'impossibile usare +N o ~N come primo indirizzoutilizzo non valido dell'indirizzo 0manca il comando`!' multipliopzioni `g' multiple al comando `s'opzioni `p' multiple al comando `s'opzioni numeriche multiple al comando `s'nessun file in ingressooccorre un'espressione regolare precedentel'opzione numerica del comando `s' non può essere zeroopzione `e' non supportataerrore di lettura su %s: %sle stringhe per il comandi `y' hanno lunghezze diversesuper-sed versione %s `,' inattesa`}' inattesacomando sconosciuto: `%c'opzione di `s' sconosciuta`{' non bilanciatacomando `s' non terminatocomando `y' non terminatoespressione regolare non terminata nell'indirizzokbuild-3686/src/oldsed/po/it.po0000664000175000017500000003203215053010106016336 0ustar locutuslocutus# traduzione di sed # Copyright (C) 1999 Free Software Foundation, Inc. # Paolo Bonzini , 2001 # msgid "" msgstr "" "Project-Id-Version: sed 4.0a\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2002-11-26 12:44+0100\n" "Last-Translator: Paolo Bonzini \n" "Language-Team: Italian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" # sed/compile.c:166 #: sed/compile.c:162 msgid "multiple `!'s" msgstr "`!' multipli" # sed/compile.c:167 #: sed/compile.c:163 msgid "unexpected `,'" msgstr "`,' inattesa" # sed/compile.c:169 #: sed/compile.c:164 msgid "invalid usage of +N or ~N as first address" msgstr "impossibile usare +N o ~N come primo indirizzo" # sed/compile.c:170 #: sed/compile.c:165 msgid "unmatched `{'" msgstr "`{' non bilanciata" # sed/compile.c:171 #: sed/compile.c:166 msgid "unexpected `}'" msgstr "`}' inattesa" # sed/compile.c:172 #: sed/compile.c:167 msgid "extra characters after command" msgstr "ci sono altri caratteri dopo il comando" # sed/compile.c:173 #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "atteso \\ dopo `a', `c' o `i'" # sed/compile.c:174 #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' non accetta indirizzi" # sed/compile.c:175 #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": non accetta indirizzi" # sed/compile.c:176 #: sed/compile.c:171 msgid "comments don't accept any addresses" msgstr "i commenti non accettano indirizzi" # sed/compile.c:177 #: sed/compile.c:172 msgid "missing command" msgstr "manca il comando" # sed/compile.c:178 #: sed/compile.c:173 msgid "command only uses one address" msgstr "il comando usa solo un indirizzo" # sed/compile.c:179 #: sed/compile.c:174 msgid "unterminated address regex" msgstr "espressione regolare non terminata nell'indirizzo" # sed/compile.c:180 #: sed/compile.c:175 msgid "unterminated `s' command" msgstr "comando `s' non terminato" # sed/compile.c:181 #: sed/compile.c:176 msgid "unterminated `y' command" msgstr "comando `y' non terminato" # sed/compile.c:182 #: sed/compile.c:177 msgid "unknown option to `s'" msgstr "opzione di `s' sconosciuta" # sed/compile.c:183 #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "opzioni `p' multiple al comando `s'" # sed/compile.c:184 #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "opzioni `g' multiple al comando `s'" # sed/compile.c:186 #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "opzioni numeriche multiple al comando `s'" # sed/compile.c:188 #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "l'opzione numerica del comando `s' non può essere zero" # sed/compile.c:190 #: sed/compile.c:182 msgid "strings for `y' command are different lengths" msgstr "le stringhe per il comandi `y' hanno lunghezze diverse" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "il carattere delimitatore è multi-byte" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "attesa una versione piu' recente di sed" # sed/compile.c:178 #: sed/compile.c:185 msgid "invalid usage of line address 0" msgstr "utilizzo non valido dell'indirizzo 0" # sed/compile.c:1319 #: sed/compile.c:186 #, c-format msgid "unknown command: `%c'" msgstr "comando sconosciuto: `%c'" # sed/compile.c:1340 #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: file %s riga %lu: %s\n" # sed/compile.c:1343 #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: espressione -e #%lu, carattere %lu: %s\n" # sed/compile.c:1543 #: sed/compile.c:1644 #, c-format msgid "can't find label for jump to `%s'" msgstr "impossibile trovare un'etichetta per il salto a `%s'" # sed/execute.c:516 #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: impossibile leggere %s: %s\n" # sed/execute.c:675 #: sed/execute.c:673 #, c-format msgid "couldn't edit %s: is a terminal" msgstr "impossibile modificare %s: è un terminale" #: sed/execute.c:677 #, c-format msgid "couldn't edit %s: not a regular file" msgstr "impossibile modificare %s: non è un file normale" # lib/utils.c:131 #: sed/execute.c:684 lib/utils.c:196 #, c-format msgid "couldn't open temporary file %s: %s" msgstr "impossibile aprire il file temporaneo %s: %s" # sed/execute.c:1003 sed/execute.c:1183 #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "errore in un sottoprocesso" # sed/execute.c:1005 #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "opzione `e' non supportata" # sed/execute.c:1185 #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "comando `e' non supportato" #: sed/execute.c:1714 msgid "no input files" msgstr "nessun file in ingresso" # lib/regcomp.c:658 sed/regex.c:47 #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "occorre un'espressione regolare precedente" # sed/regex.c:48 #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "non è possibile specificare dei modificatori per l'espressione vuota" # sed/regex.c:146 #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "riferimento non valido \\%d nel secondo membro del comando `s'" # sed/sed.c:98 #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " usa la sintassi Perl 5 per le espressioni regolari\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" "Utilizzo: %s [OPZIONE]... {script-se-nessun-altro-specificato} [input-" "file]...\n" "\n" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" " -n, --quiet, --silent\n" " sopprime la stampa automatica del pattern space\n" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" " -e script, --expression=script\n" " aggiunge lo script ai comandi da eseguire\n" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" " -f script-file, --file=file-script\n" " aggiunge il contenuto di file-script ai comandi da " "eseguire\n" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " scrive il risultato sul file originale (facendo una copia\n" " se è fornita un'estensione)\n" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" " -l N, --line-length=N\n" " specifica la lunghezza delle linee generate dal comando " "`l'\n" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" " --posix\n" " disabilita tutte le estensioni GNU.\n" # sed/sed.c:98 #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -r, --regexp-extended\n" " usa la sintassi di `egrep' per le espressioni regolari\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" " -s, --separate\n" " considera i file di input come separati invece che come un\n" " unico file lungo.\n" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" " -u, --unbuffered\n" " carica e visualizza i dati una a pezzetti piu' piccoli\n" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr " --help mostra questo aiuto ed esce\n" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr " --version stampa le informazioni sulla versione ed esce\n" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" "\n" "Se non è usata nessuna delle opzioni -e, --expression, -f o --file allora " "il\n" "primo argomento che non è una opzione sarà usato come lo script sed da\n" "interpretare. Tutti gli argomenti rimanenti sono nomi di file di input; se " "non\n" "sono specificati file di input sarà letto lo standard input.\n" "\n" # sed/sed.c:132 #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Segnalare eventuali bug a: %s .\n" "Assicurarsi di includere la parola ``%s'' nell'oggetto del messaggio.\n" # sed/sed.c:255 #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed versione %s\n" # sed/sed.c:256 #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "basato su GNU sed versione %s\n" "\n" # sed/sed.c:258 #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed versione %s\n" # sed/sed.c:260 #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Questo è software libero; si veda il sorgente per le condizioni di " "copiatura.\n" "NON c'è garanzia; neppure di COMMERCIABILITA' o IDONEITA' AD UN PARTICOLARE\n" "SCOPO, nei limiti permessi dalla legge.\n" # sed/execute.c:516 #: lib/utils.c:98 lib/utils.c:336 #, c-format msgid "cannot remove %s: %s" msgstr "impossibile rimuovere %s: %s" # lib/utils.c:131 #: lib/utils.c:143 #, c-format msgid "couldn't open file %s: %s" msgstr "impossibile aprire il file %s: %s" # lib/utils.c:161 #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "Impossibile scrivere %d elemento su %s: %s" msgstr[1] "Impossibile scrivere %d elementi su %s: %s" # lib/utils.c:176 #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "errore di lettura su %s: %s" # sed/execute.c:516 #: lib/utils.c:341 #, c-format msgid "cannot rename %s: %s" msgstr "impossibile rinominare %s: %s" # lib/regcomp.c:179 #: lib/regcomp.c:132 msgid "Success" msgstr "Successo" # lib/regcomp.c:182 #: lib/regcomp.c:135 msgid "No match" msgstr "Nessuna corrispondenza trovata" # lib/regcomp.c:185 #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Espressione regolare non valida" # lib/regcomp.c:188 #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Carattere di ordinamento non valido" # lib/regcomp.c:191 #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Nome non valido per una classe di caratteri" # lib/regcomp.c:194 #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Barra rovesciata alla fine dell'espressione regolare" # lib/regcomp.c:197 #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Riferimento non valido" # lib/regcomp.c:200 #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "`[' non bilanciata" # lib/regcomp.c:203 #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "`(' o `\\(' non bilanciata" # lib/regcomp.c:206 #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "`\\{' non bilanciata" # lib/regcomp.c:209 #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "numero di ripetizioni specificato tra graffe non valido" # lib/regcomp.c:212 #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Fine dell'intervallo non valida" # lib/regcomp.c:215 #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Memoria esaurita" # lib/regcomp.c:218 #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Espressione regolare precedente non valida" # lib/regcomp.c:221 #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Fine prematura dell'espressione regolare" # lib/regcomp.c:224 #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Espressione regolare troppo grande" # lib/regcomp.c:227 #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "`)' o `\\)' non bilanciata" # lib/regcomp.c:658 sed/regex.c:47 #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Occorre un'espressione regolare precedente" kbuild-3686/src/oldsed/po/sv.po0000664000175000017500000002755115053010106016364 0ustar locutuslocutus# Swedish messages for sed. # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. # Christian Rose , 1999, 2000, 2001, 2002, 2003, 2004. # msgid "" msgstr "" "Project-Id-Version: sed 4.1.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2004-07-11 11:45+0200\n" "Last-Translator: Christian Rose \n" "Language-Team: Swedish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: sed/compile.c:162 msgid "multiple `!'s" msgstr "flera \"!\"" #: sed/compile.c:163 msgid "unexpected `,'" msgstr "oväntat \",\"" #: sed/compile.c:164 msgid "invalid usage of +N or ~N as first address" msgstr "ogiltig användning av +N eller ~N som första adress" #: sed/compile.c:165 msgid "unmatched `{'" msgstr "obalanserad \"{\"" #: sed/compile.c:166 msgid "unexpected `}'" msgstr "oväntad \"}\"" #: sed/compile.c:167 msgid "extra characters after command" msgstr "extra tecken efter kommandot" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "\\ förväntades efter \"a\", \"c\" eller \"i\"" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "\"}\" vill inte ha några adresser" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": vill inte ha några adresser" #: sed/compile.c:171 msgid "comments don't accept any addresses" msgstr "kommentarer accepterar inga adresser" #: sed/compile.c:172 msgid "missing command" msgstr "kommando saknas" #: sed/compile.c:173 msgid "command only uses one address" msgstr "kommandot använder endast en adress" #: sed/compile.c:174 msgid "unterminated address regex" msgstr "oavslutat reguljärt uttryck för adress" #: sed/compile.c:175 msgid "unterminated `s' command" msgstr "oavslutat \"s\"-kommando" #: sed/compile.c:176 msgid "unterminated `y' command" msgstr "oavslutat \"y\"-kommando" #: sed/compile.c:177 msgid "unknown option to `s'" msgstr "flaggan okänd för \"s\"" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "flera \"p\"-flaggor till \"s\"-kommandot" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "flera \"g\"-flaggor till \"s\"-kommandot" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "flera sifferflaggor till \"s\"-kommandot" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "sifferflagga till kommandot \"s\" får inte vara noll" #: sed/compile.c:182 msgid "strings for `y' command are different lengths" msgstr "strängarna för kommandot \"y\" är olika långa" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "avgränsningstecknet är inte en ensam byte" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "nyare version av sed förväntades" #: sed/compile.c:185 msgid "invalid usage of line address 0" msgstr "felaktig användning av radadress 0" #: sed/compile.c:186 #, c-format msgid "unknown command: `%c'" msgstr "okänt kommando: \"%c\"" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: fil %s rad %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e uttryck #%lu, tecken %lu: %s\n" #: sed/compile.c:1644 #, c-format msgid "can't find label for jump to `%s'" msgstr "kan inte hitta etiketten för hopp till \"%s\"" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: kan inte läsa %s: %s\n" #: sed/execute.c:673 #, c-format msgid "couldn't edit %s: is a terminal" msgstr "kunde inte redigera %s: är en terminal" #: sed/execute.c:677 #, c-format msgid "couldn't edit %s: not a regular file" msgstr "kunde inte redigera %s: inte en vanlig fil" #: sed/execute.c:684 lib/utils.c:196 #, c-format msgid "couldn't open temporary file %s: %s" msgstr "kunde inte öppna temporära filen %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "fel i underprocess" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "flaggan \"e\" stöds inte" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "kommandot \"e\" stöds inte" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "inget tidigare reguljärt uttryck" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "kan inte ange modifierare på tomt reguljärt uttryck" # Kommentar från Jan Djärv: # Jag antar RHS står för "right hand side". Man kan då säga # "... kommandots högersida" # #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "ogiltig referens \\%d på \"s\"-kommandots högersida" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " använd Perl 5:s syntax för reguljära uttryck i skriptet.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" "Användning: %s [FLAGGA]... {skript-endast-om-inga-andra} [indatafil]...\n" "\n" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" " -n, --quiet, --silent\n" " förhindrar automatisk utskrift av mönsterutrymme\n" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" " -e skript, --expression=skript\n" " lägg till skript till de kommandon som ska utföras\n" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" " -f skriptfil, --file=skriptfil\n" " lägg till innehållet i skriptfil till de kommandon som ska\n" " utföras\n" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" " -i[ÄNDELSE], --in-place[=ÄNDELSE]\n" " redigera filer på plats (skapar säkerhetskopia om ändelse\n" " tillhandahålls)\n" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" " -l N, --line-length=N\n" " ange önskad radbrytningslängd för \"l\"-kommandot\n" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" " --posix\n" " inaktivera alla GNU-utökningar.\n" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -r, --regexp-extended\n" " använd utökade reguljära uttryck i skriptet.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" " -s, --separate\n" " betrakta filer som separata istället för som en\n" " kontinuerlig lång dataström.\n" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" " -u, --unbuffered\n" " läs in minimala mängder data från indatafilerna och töm\n" " utdatabufferterna oftare\n" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr " --help visa denna hjälptext och avsluta\n" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr " --version visa versionsinformation och avsluta\n" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" "\n" "Om ingen av flaggorna -e, --expression, -f, eller --file ges, blir det\n" "första argumentet som inte är en flagga det sed-skript som tolkas. Alla\n" "återstående argument är namn på indatafiler. Om inga indatafiler är angivna\n" "läses standard in.\n" "\n" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Rapportera fel till: %s .\n" "Ange ordet \"%s\" på något ställe i \"Ärende:\"-fältet.\n" "Skicka anmärkningar på översättningen till .\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed version %s\n" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "baserad på GNU sed version %s\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed version %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "(Följande text är en informell översättning som enbart tillhandahålls\n" " i informativt syfte. För alla juridiska tolkningar gäller den engelska\n" " originaltexten.)\n" "Det här är fri programvara; se källkoden angående villkor för kopiering.\n" "Det finns INGEN garanti; inte ens för SÄLJBARHET eller LÄMPLIGHET FÖR NÅGOT\n" "SPECIELLT ÄNDAMÅL, i den omfattning som medges av gällande lag.\n" #: lib/utils.c:98 lib/utils.c:336 #, c-format msgid "cannot remove %s: %s" msgstr "kan inte ta bort %s: %s" #: lib/utils.c:143 #, c-format msgid "couldn't open file %s: %s" msgstr "kunde inte öppna filen %s: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "kunde inte skriva %d objekt till %s: %s" msgstr[1] "kunde inte skriva %d objekt till %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "läsfel vid %s: %s" #: lib/utils.c:341 #, c-format msgid "cannot rename %s: %s" msgstr "kan inte byta namn på %s: %s" #: lib/regcomp.c:132 msgid "Success" msgstr "Lyckades" #: lib/regcomp.c:135 msgid "No match" msgstr "Ingen träff" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Ogiltigt reguljärt uttryck" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Ogiltigt sorteringstecken" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Ogiltigt teckenklassnamn" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Eftersläpande omvänt snedstreck" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Ogiltig bakåtreferens" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "Obalanserad [ eller [^" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "Obalanserad ( eller \\(" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "Obalanserad \\{" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Ogiltigt innehåll i \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Ogiltigt intervallslut" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Minnet slut" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Ogiltigt föregående reguljärt uttryck" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "För tidigt slut på reguljärt uttryck" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Reguljärt uttryck för stort" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "Obalanserad ) eller \\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Inget tidigare reguljärt uttryck" kbuild-3686/src/oldsed/po/es.gmo0000664000175000017500000001001715053010106016474 0ustar locutuslocutus•Þ'T5Œ`\aº¾%yŸ¶ÐdíRf}š¶$Îó 1:#Y}˜ ³Å× éöB/r†#¤#È&ì,@Ynr„{ ÷Ï s( C l ‰ §| Å B V$ v! › ½% Ø þ  1 A# U' y" ¡ Ä Ê æ ø "*MUmÃ+Ú((/.X7‡!¿áù!"  ' # % &$ -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessexpected newer version of sedmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: sed 4.0.8 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2003-10-24 12:38-0500 Last-Translator: Cristian Othón Martínez Vera Language-Team: Spanish MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8-bit Plural-Forms: nplurals=2; plural=(n != 1); -R, --regexp-perl utilizar la sintaxis de expresiones regulares de Perl 5 en el guión. %s Esto es software libre; vea el código fuente para las condiciones de copia. No hay NINGUNA garantía; ni siquiera de COMERCIABILIDAD o IDONEIDAD PARA UN FIN DETERMINADO, en la extensión permitida por ley. %s: -e expresión #%lu, carácter %lu: %s %s: no se puede leer %s: %s %s: fichero %s línea %lu: %s : no acepta ninguna direcciónEnvíe reportes de bichos por e-mail a: %s . Asegúrese de incluir la palabra ``%s'' en algún lugar en el campo ``Subject:''. GNU sed versión %s Referencia hacia atrás inválidaCarácter de nombre de clase inválidoCarácter de ordenamiento inválidoContenido inválido de \{\}Expresión regular precedente inválidaFinal de rango inválidoExpresion regular inválidaMemoria agotadaNo hay coincidenciaNo hay una expresión regular previaFinal prematuro de la expresión regularExpresión regular demasiado grandeÉxitoDiagonal invertida al final( ó \( sin pareja) ó \) sin pareja[ ó [^ sin pareja\{ sin parejano hay soporte para el comando `e'`}' no acepta ninguna direcciónno se puede escribir %d elemento a %s: %sno se pueden escribir %d elementos a %s: %serror en el subprocesose esperaba una versión más reciente de sedmúltiples opciones `g' para la orden `s'múltiples opciones `p' para la orden `s'múltiples opciones numéricas para la orden `s'una opción numérica para la orden `s' no puede ser cerono hay soporte para la opción `e'error al leer de %s: %ssuper-sed versión %s kbuild-3686/src/oldsed/po/sr.gmo0000664000175000017500000001146315053010106016517 0ustar locutuslocutus•Þ'T5Œ`\aº¾%yŸ¶ÐdíRf}š¶$Îó 1:#Y}˜ ³Å× éöB/r†#¤#È&ì,@Ynº„† ? Æ) Ë' õ' / E u 8 15 j2  + ÓG ÿ*G2r#¥É=ã7!5Y /šÊé'0=5n­¤$R5w9­9çD!Tf.»+ê!"  ' # % &$ -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessexpected newer version of sedmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: sed 4.0.9 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2004-01-13 22:51-0500 Last-Translator: Aleksandar Jelenak Language-Team: Serbian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : (n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); -R, --regexp-perl кориÑти у ÑпиÑу ÑинтакÑу Перла 5 за регуларне изразе. %s Ово је Ñлободан Ñофтвер; видети изворни кôд за уÑлове умножавања. БЕЗ икакве гаранције; чак ни о ТРЖИШÐОСТИ или ИСПУЊÐÐ’ÐЊУ ОДРЕЂЕÐЕ ПОТРЕБЕ. %s: -e израз #%lu, знак %lu: %s %s: не може читати %s: %s %s: датотека %s ред %lu: %s : не захтева икакве адреÑеЕпошта за пријаву грешака: %s . ПоÑтарајте Ñе да укључите реч „%s“ негде у „Subject:“ пољу. ГÐУ sed верзија %s ÐеиÑправна повратна референцаÐеиÑправно име клаÑе знаковаÐеиÑправни знак прикупљањаÐеиÑправни Ñадржај у \{\}ÐеиÑправан претходећи регуларни изразÐеиÑправни крај опÑегаÐеиÑправни регуларни изразМеморија иÑцрпљенаБез поклапањаБез претходног регуларног изразаПреран крај регуларног изразаРегуларни израз Ñувише великУÑпехПратећа обрнута коÑа цртаÐеÑпарено ( или \(ÐеÑпарено ) или \)ÐеÑпарено [ или ^[ÐеÑпарено \{наредба „e“ није подржана„}“ не захтева икакве адреÑенеуÑпешан Ð·Ð°Ð¿Ð¸Ñ %d Ñтавке на %s: %sнеуÑпешан Ð·Ð°Ð¿Ð¸Ñ %d Ñтавке на %s: %sнеуÑпешан Ð·Ð°Ð¿Ð¸Ñ %d Ñтавки на %s: %sгрешка у потпроцеÑуочекивана новија верзија sed-авише „g“ опција за „s“ наредбувише „p“ опција за „s“ наредбувише бројчаних опција за „s“ наредбубројчана опција наредбе „s“ не може бити нулаопција „e“ није подржанагрешка учитавања на %s: %ssuper-sed верзија %s kbuild-3686/src/oldsed/po/zh_CN.po0000664000175000017500000002132515053010106016726 0ustar locutuslocutus# SOME DESCRIPTIVE TITLE. # Copyright (C) 2002 Free Software Foundation, Inc. # Wang Li , 2002. # msgid "" msgstr "" "Project-Id-Version: sed 3.02.80\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2002-08-18 11:11+0800\n" "Last-Translator: Wang Li \n" "Language-Team: Chinese (simplified) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=gb2312\n" "Content-Transfer-Encoding: 8bit\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "¶à¸ö¡°!¡±" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "ÒâÍâµÄ¡°,¡±" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "ÎÞ·¨½« +N »ò ~N ×÷ΪµÚÒ»¸öµØÖ·" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "δƥÅäµÄ¡°{¡±" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "δƥÅäµÄ¡°}¡±" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "ÃüÁîºóº¬ÓжàÓàµÄ×Ö·û" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "¡°}¡±²»ÐèÒªÈκεØÖ·" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": ²»ÐèÒªÈκεØÖ·" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "×¢ÊͲ»½ÓÊÜÈκεØÖ·" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "ÒÅ©ÃüÁî" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "ÃüÁîֻʹÓÃÒ»¸öµØÖ·" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "δÖÕÖ¹µÄµØÖ·³£¹æ±í´ïʽ" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "δÖÕÖ¹µÄ¡°s¡±ÃüÁî" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "δÖÕÖ¹µÄ¡°y¡±ÃüÁî" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "¡°s¡±µÄδ֪ѡÏî" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "¶à¸ö¡°s¡±ÃüÁîµÄÑ¡Ïî¡°p¡±" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "¶à¸ö¡°s¡±ÃüÁîµÄÑ¡Ïî¡°g¡±" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "¶à¸ö¡°s¡±ÃüÁîµÄÊýֵѡÏî" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "¡°s¡±ÃüÁîµÄÊýֵѡÏî²»ÄÜΪÁã" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "y ÃüÁîµÄ×Ö·û´®³¤¶È²»Í¬" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "·Ç·¨Ê¹ÓõØÖ·ÐÞÊηû" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "δ֪µÄÃüÁ" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s£ºÎļþ %s Ðкţº%lu£º%s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s£º-e ±í´ïʽ #%lu£¬×Ö·û %lu£º%s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "ÎÞ·¨ÎªÄ¿µÄΪ¡°%s¡±µÄÌø×ªÕÒµ½±êÇ©" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s£ºÎÞ·¨¶ÁÈ¡ %s£º%s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "ÎÞ·¨´ò¿ªÎļþ %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "ÎÞ·¨´ò¿ªÎļþ %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "ÎÞ·¨´ò¿ªÎļþ %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "½«´íÎ󱨸æÍ¨¹ýµç×ÓÓʼþ·¢Ë͵½£º%s .\n" "ÇëÎñ±Ø½«µ¥´Ê¡°%s¡±·ÅÔÚ¡°Subject:¡±ÓòµÄij´¦¡£\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s£ºÎÞ·¨¶ÁÈ¡ %s£º%s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "ÎÞ·¨´ò¿ªÎļþ %s" #: lib/utils.c:220 #, fuzzy, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "ÎÞ·¨½« %d ¸öÏîĿдÈë %s£º%s" msgstr[1] "ÎÞ·¨½« %d ¸öÏîĿдÈë %s£º%s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "¶ÁÈ¡ %s ³ö´í£º%s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s£ºÎÞ·¨¶ÁÈ¡ %s£º%s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "" #: lib/regcomp.c:135 msgid "No match" msgstr "" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "" #: lib/regcomp.c:153 #, fuzzy msgid "Unmatched [ or [^" msgstr "δƥÅäµÄ¡°{¡±" #: lib/regcomp.c:156 #, fuzzy msgid "Unmatched ( or \\(" msgstr "δƥÅäµÄ¡°{¡±" #: lib/regcomp.c:159 #, fuzzy msgid "Unmatched \\{" msgstr "δƥÅäµÄ¡°{¡±" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "" #: lib/regcomp.c:180 #, fuzzy msgid "Unmatched ) or \\)" msgstr "δƥÅäµÄ¡°{¡±" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "" kbuild-3686/src/oldsed/po/de.po0000664000175000017500000002525115053010106016317 0ustar locutuslocutus# sed german translation # Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. # Walter Koch , 2001, 2002, 2003 # msgid "" msgstr "" "Project-Id-Version: sed 4.0.6\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2003-03-21 22:03:41+0100\n" "Last-Translator: Walter Koch \n" "Language-Team: German \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "Mehrfache `!'" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "Unerwartetes `,'" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "+N oder ~N können nicht als erste Adresse benutzt werden" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "Nicht paarweises `{'" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "Unerwartetes `}'" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Zusätzliche Zeichen nach dem Befehl" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "Nach `a', `c' oder `i' wird \\ erwartet" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' erwartet keine Adressen" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr "`:' erwartet keine Adressen" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Kommentare erlauben keine Adressen" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Fehlender Befehl" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Befehl verwendet nur eine Adresse" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Nicht beendeter regulärer Adressausdruck" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Nicht beendeter `s'-Befehl" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Nicht beendeter `y'-Befehl" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Unbekannte Option betreffs `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "Mehrere 'p'-Optionen am `s'-Befehl" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "Mehrere 'g'-Optionen am `s'-Befehl" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "Mehrere numerische Optionen am `s'-Befehl" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "Numerisch Option am `s'-Befehl darf nicht Null sein" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "Unterschiedliche Länge der Zeichenketten am `y'-Befehl" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "Neuere Version von sed erwartet" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Befehl verwendet nur eine Adresse" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Unbekannter Befehl:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: Datei %s Zeile %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e Ausdruck #%lu, Zeichen %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Kann das Ziel für den Sprung nach `%s' nicht finden" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: kann %s nicht lesen: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Datei %s kann nicht geöffnet werden: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Datei %s kann nicht geöffnet werden: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Datei %s kann nicht geöffnet werden: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "Fehler im Subprozess" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "Option `e' wird nicht unterstützt" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "`e'-Kommando wird nicht unterstützt" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Kein vorheriger regulärer Ausdruck" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "Auf leere reguläre Ausdrücke können keine `modifier' angewandt werden" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Ungültiger Verweis \\%d in den Haltepuffer des `s'-Befehls" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " Verwende die Perl 5 - Syntax für reg.Ausdrücke im Script.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " Verwende die Perl 5 - Syntax für reg.Ausdrücke im Script.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Fehlerberichte (in Englisch!) per E-Mail an: %s .\n" "Verwenden Sie dabei den Begriff ``%s'' irgendwo in der ``Betreff:''-Zeile.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "Super-sed version %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "basiert auf GNU sed Version 3.02.80\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed Version %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "(Der folgende Text ist eine nicht überprüfte Übersetzung, die zur\n" " Information dient; in rechtlichen Fragen ist immer das englische\n" " Original ausschlaggebend)\n" "\n" "Dieses Program ist freie Software; In den Quelldateien können Sie die\n" "Bedingungen für die Weitergabe nachlesen.\n" "Es gibt KEINE GARANTIE; nicht einmal die implizite Garantie der\n" "MARKTFÄHIGKEIT oder der ERFÜLLUNG EINES BESTIMMTEN ZWECKES.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: kann %s nicht lesen: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Datei %s kann nicht geöffnet werden: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "Kann %d Feld nicht auf %s schreiben: %s" msgstr[1] "Kann %d Felder nicht auf %s schreiben: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "Lesefehler in %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: kann %s nicht lesen: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "Erfolgreich" #: lib/regcomp.c:135 msgid "No match" msgstr "Keine Übereinstimmung" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Ungültiger regulärer Ausdruck" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Ungültiger Vergleichszeichen" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Ungültige Zeichenklassenname" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Abschliessender Backslash" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Ungültiger Rückwärtsverweis" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "Nicht paarweises [ bzw. [^" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "Nicht paarweises ( bzw. \\(" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "Nicht paarweises \\{" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Ungültiger Inhalt in \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Ungültiges Bereichende" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Speicher erschöpft" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Vorheriger regulärer Ausdruck ist ungültig" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Regulärer Ausdruck endet zu früh" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Regulärer Ausdruck ist zu groß" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "Nicht paarweises ) bzw. \\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Kein vorheriger regulärer Ausdruck" kbuild-3686/src/oldsed/po/pl.gmo0000664000175000017500000002334515053010106016510 0ustar locutuslocutus•ÞQ¤m,àúá,Ü5 7?\w`Ôu 5l «b V {Y Ò~ , «º ;% ö  3 Md j Ï ã ú3$Kp‚®·#Öú0BT fHs¼Öõ!5J(_ˆ#¦Ê$ê#)BM2à ×ø*5*`‹« »#É#í&8,W„-²àö* @Ng€¼›YX8²8ëC$eheΕ4¦ÊcqdÕ]:‚˜ŽÌª$wœ»ÖeñW j‹«É/æ!3Ug'x) "Êíô  ' C _S u É ê !,!(!U!mC!Œ$!Ð(!õ+"1"J"|,"œy"É5#C#y&#Œ&#³#Ú;#÷5$3#$i$$Ÿ'$´'$Ü,%'%13%Y%%ª.%À%ï&&&2 &K&l&ƒ&Ÿ)&»$DQ"!@=ELB5?43 .N;2(:9%< /CP',KM #6+017F H*->J O8& I)GA If no -e, --expression, -f, or --file option is given, then the first non-option argument is taken as the sed script to interpret. All remaining arguments are names of input files; if no input files are specified, then the standard input is read. --help display this help and exit --version output version information and exit --posix disable all GNU extensions. -R, --regexp-perl use Perl 5's regular expressions syntax in the script. -e script, --expression=script add the script to the commands to be executed -f script-file, --file=script-file add the contents of script-file to the commands to be executed -i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if extension supplied) -l N, --line-length=N specify the desired line-wrap length for the `l' command -n, --quiet, --silent suppress automatic printing of pattern space -r, --regexp-extended use extended regular expressions in the script. -s, --separate consider files as separate rather than as a single continuous long stream. -u, --unbuffered load minimal amounts of data from the input files and flush the output buffers more often %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]... `e' command not supported`}' doesn't want any addressesbased on GNU sed version %s can't find label for jump to `%s'cannot remove %s: %scannot rename %s: %scannot specify modifiers on empty regexpcommand only uses one addresscomments don't accept any addressescouldn't edit %s: is a terminalcouldn't edit %s: not a regular filecouldn't open file %s: %scouldn't open temporary file %s: %scouldn't write %d item to %s: %scouldn't write %d items to %s: %sdelimiter character is not a single-byte charactererror in subprocessexpected \ after `a', `c' or `i'expected newer version of sedextra characters after commandinvalid reference \%d on `s' command's RHSinvalid usage of +N or ~N as first addressinvalid usage of line address 0missing commandmultiple `!'smultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandno previous regular expressionnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %sstrings for `y' command are different lengthssuper-sed version %s unexpected `,'unexpected `}'unknown command: `%c'unknown option to `s'unmatched `{'unterminated `s' commandunterminated `y' commandunterminated address regexProject-Id-Version: sed 4.1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2004-07-08 19:58+0200 Last-Translator: Wojciech Polak Language-Team: Polish MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-2 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); Je¿eli nie zostan± podane opcje -e, --expression, -f, lub --file, to wtedy pierwszy argument, który nie jest opcj± linii poleceñ sed, zostanie wziêty jako skrypt sed do przetworzenia. Wszystkie pozosta³e argumenty s± nazwami plików wej¶ciowych; je¿eli nie zostan± podane ¿adne pliki wej¶ciowe, to wtedy odczytane zostanie standardowe wej¶cie. --help wy¶wietla tê oto pomoc i koñczy pracê. --version wy¶wietla numer wersji i koñczy pracê. --posix wy³±cza wszystkie rozszerzenia GNU. -R, --regexp-perl u¿ywa w skrypcie wyra¿enia regularne zgodne ze sk³adni± Perl 5. -e skrypt, --expression=skrypt dodaje skrypt do poleceñ, które maj± byæ wykonane. -f plik-skryptowy, --file=plik-skryptowy dodaje zawarto¶æ pliku skryptowego do poleceñ, które maj± byæ wykonane. -i[rozszerzenie], --in-place[=rozszerzenie] edytuje pliki "w miejscu" (tworzy kopie zapasowe je¿eli zosta³o podane rozszerzenie). -l N, --line-length=N ustala po¿±dan± d³ugo¶æ ³amanych linii dla polecenia `l'. -n, --quiet, --silent powstrzymuje automatyczne drukowanie przetwarzanych linii. -r, --regexp-extended u¿ywa w skrypcie rozszerzonych wyra¿eñ regularnych. -s, --separate traktuje pliki jako oddzielne, a nie jako pojedynczy, d³ugi i ci±g³y strumieñ. -u, --unbuffered ³aduje minimaln± ilo¶æ danych z plików wej¶ciowych i czê¶ciej oczyszcza bufor wyj¶ciowy. %s Niniejszy program jest wolnym oprogramowaniem; warunki kopiowania s± opisane w ¼ród³ach. Autorzy nie daj± ¯ADNYCH gwarancji, w tym równie¿ gwarancji PRZYDATNO¦CI DO SPRZEDA¯Y LUB DO KONKRETNYCH CELÓW. %s: -e wyra¿enie #%lu, znak %lu: %s %s: nie mo¿na odczytaæ %s: %s %s: plik %s linia %lu: %s : nie chce ¿adnych adresówEwentualne b³êdy prosimy zg³aszaæ na adres: %s W tym celu proszê dodaæ s³owo ``%s'' do tematu listu. GNU sed wersja %s Nieprawid³owe odwo³anie wsteczneNieprawid³owa nazwa klasy znakuNieprawid³owy znak porównaniaNieprawid³owa zawarto¶æ \{\}Nieprawid³owe poprzedzaj±ce wyra¿enie regularneNieprawid³owy koniec zakresuNieprawid³owe wyra¿enie regularnePamiêæ wyczerpanaBrak dopasowaniaBrak poprzedniego wyra¿enia regularnegoPrzedwczesny koniec wyra¿enia regularnegoWyra¿enie regularne jest zbyt du¿eSukcesKoñcowy znak backslashNiedopasowany znak ( lub \(Niedopasowany znak ) lub \)Niedopasowany znak [ lub [^Niedopasowany znak \{U¿ycie: %s [OPCJE] {skrypt-tylko-wtedy-gdy-¿aden-inny-skrypt} [plik-wej¶ciowy]... polecenie `e' nie jest wspierane`}' nie chce ¿adnych adresówna podstawie wersji GNU sed %s nie mo¿na znale¼æ etykiety dla skoku do `%s'nie mo¿na usun±æ %s: %snie mo¿na zmieniæ nazwy %s: %snie mo¿na wyszczególniæ modyfikatorów w pustym wyra¿eniu regularnympolecenie u¿ywa tylko jednego adresukomentarze nie akceptuj± ¿adnych adresównie mo¿na edytowaæ %s: plik jest terminalemnie mo¿na edytowaæ %s: to nie jest regularny pliknie mo¿na otworzyæ pliku %s: %snie mo¿na otworzyæ tymczasowego pliku %s: %snie mo¿na zapisaæ %d elementu do %s: %snie mo¿na zapisaæ %d elementów do %s: %snie mo¿na zapisaæ %d elementów do %s: %sznak ogranicznika nie jest pojedynczym znakiem-bajtemb³±d w podprocesieoczekiwano znaku \ po `a', `c' lub `i'oczekiwano nowszej wersji programu seddodatkowe znaki po poleceniunieprawid³owe odwo³anie \%d po prawej stronie polecenia `s'nieprawid³owe u¿ycie +N lub ~N jako pierwszego adresunieprawid³owe u¿ycie adresu linii 0brakuje poleceniawielokrotny znak `!'wielokrotne opcje `g' dla polecenia `s'wielokrotne opcje `p' dla polecenia `s'wielokrotne opcje liczbowe dla polecenia `s'brak poprzedniego wyra¿enia regularnegoopcja liczbowa dla polecenia `s' nie mo¿e byæ zeremopcja `e' nie jest wspieranab³±d odczytu w %s: %s³añcuchy dla polecenia `y' s± ró¿nych d³ugo¶cisuper-sed wersja %s nieoczekiwany znak `,'nieoczekiwany znak `}'nieznane polecenie: `%c'nieznana opcja dla polecenia `s'niedopasowany znak `{'niezakoñczone polecenie `s'niezakoñczone polecenie `y'niezakoñczony adres wyra¿enia regularnegokbuild-3686/src/oldsed/po/quot.sed0000664000175000017500000000023115053010106017043 0ustar locutuslocutuss/"\([^"]*\)"/“\1â€/g s/`\([^`']*\)'/‘\1’/g s/ '\([^`']*\)' / ‘\1’ /g s/ '\([^`']*\)'$/ ‘\1’/g s/^'\([^`']*\)' /‘\1’ /g s/“â€/""/g kbuild-3686/src/oldsed/po/nl.gmo0000664000175000017500000002221715053010106016503 0ustar locutuslocutus•ÞPœkÈúÉ,Ä5ñ7'\_`¼u l “b Y c~ ½ <º Ì% ‡ ­ Ä Þd û ` t ‹ ¨ Ä$ Ü.?H#g‹¦®ÁÓå ÷HMg†!¤ÆÛ(ð#7[${ #ºBÞ2!T h‰§*Æ*ñ< L#Z#~&¢É,è.-Cq‡–¥» Ñßøi,–2«:Þ>nXdÇ{,‰¨i2cœhiÑù%Ëñ *®>í4J*d¤Â× é( 3SZr…˜ «Q¹# / E+f’®>È% ! -% O) u Ÿ( ¾N ç(!6!_!r&!’!¹=!Ò."""?"b "w%"…%"«&"Ñ "ø.# #H#i<#|#¹#Î#Þ#î$$ $/$I+$cB(4  M 68OI,=1:AF'2</ !5+)$7%&->3DL E09P*C?NK.;G"J#@H If no -e, --expression, -f, or --file option is given, then the first non-option argument is taken as the sed script to interpret. All remaining arguments are names of input files; if no input files are specified, then the standard input is read. --help display this help and exit --version output version information and exit --posix disable all GNU extensions. -R, --regexp-perl use Perl 5's regular expressions syntax in the script. -e script, --expression=script add the script to the commands to be executed -f script-file, --file=script-file add the contents of script-file to the commands to be executed -i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if extension supplied) -l N, --line-length=N specify the desired line-wrap length for the `l' command -r, --regexp-extended use extended regular expressions in the script. -s, --separate consider files as separate rather than as a single continuous long stream. -u, --unbuffered load minimal amounts of data from the input files and flush the output buffers more often %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]... `e' command not supported`}' doesn't want any addressesbased on GNU sed version %s can't find label for jump to `%s'cannot remove %s: %scannot rename %s: %scannot specify modifiers on empty regexpcommand only uses one addresscomments don't accept any addressescouldn't edit %s: is a terminalcouldn't edit %s: not a regular filecouldn't open file %s: %scouldn't open temporary file %s: %scouldn't write %d item to %s: %scouldn't write %d items to %s: %sdelimiter character is not a single-byte charactererror in subprocessexpected \ after `a', `c' or `i'expected newer version of sedextra characters after commandinvalid reference \%d on `s' command's RHSinvalid usage of +N or ~N as first addressinvalid usage of line address 0missing commandmultiple `!'smultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandno previous regular expressionnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %sstrings for `y' command are different lengthssuper-sed version %s unexpected `,'unexpected `}'unknown command: `%c'unknown option to `s'unmatched `{'unterminated `s' commandunterminated `y' commandunterminated address regexProject-Id-Version: sed 4.1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2005-04-12 20:09+0200 Last-Translator: Taco Witte Language-Team: Dutch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n != 1; Als geen -e, --expression, -f of --file optie gegeven is, wordt het eerste niet-optie argument genomen als het te interpreteren sed-script. Alle overblijvende argumenten zijn namen van invoerbestanden; als geen invoerbestanden opgegeven zijn, wordt standaardinvoer gelezen. --help deze hulp weergeven en afsluiten --version versie-informatie weergeven en afsluiten --posix alle GNU-uitbreidingen uit zetten. -R, --regexp-perl de syntaxis van Perl 5 voor reguliere expressie gebruiken in het script. -e script, --expression=SCRIPT het SCRIPT toevoegen aan uit te voeren opdrachten -f script-file, --file=SCRIPTBESTAND de inhoud van SCRIPTBESTAND toevoegen aan uit te voeren opdrachten -i[ACHTERVOEGSEL], --in-place[=ACHTERVOEGSEL] bestanden ter plekke bewerken (maakt reservekopie als extensie gegeven) -l AANTAL, --line-length=AANTAL gewenste regelafbreeklengte opgeven voor `l'-opdracht -r, --regexp-extended uitgebreide reguliere expressies gebruiken in het script. -s, --separate bestanden als losstaand beschouwen i.p.v. als enkele continue stroom. -u, --unbuffered minimale hoeveelheid gegevens laden uit invoerbestanden en uitvoerbuffers vaker leegmaken %s Dit is vrije software; zie de bron voor kopieervoorwaarden. Er is GEEN garantie; zelfs niet voor VERHANDELBAARHEID of GESCHIKTHEID VOOR EEN BEPAALD DOEL, tot het uiterste dat door de wet wordt toegestaan. %s: -e expressie #%lu, teken %lu: %s %s: kan %s niet lezen: %s %s: bestand %s regel %lu: %s : wil geen adressenStuur foutrapporten naar: %s . Zorg ervoor dat het woord ``%s'' ergens in het ``Onderwerp:''-veld staat. Rapporteer fouten in de vertalingen bij . GNU sed versie %s Ongeldige terugverwijzingOngeldige tekenklassenaamOngeldig sorteertekenOngeldige inhoud van \{\}Ongeldige voorafgaande reguliere expressieOngeldig bereikeindeOngeldige reguliere expressieOnvoldoende geheugenGeen overeenkomstGeen eerdere reguliere expressieVoortijdig einde van reguliere expressieReguliere expressie is te grootGeluktBackslash aan het eindeOngepaarde ( of \(Ongepaarde ) of \)Ongepaarde [ of [^Ongepaarde \{Gebruik: %s [OPTIE]... {script-alleen-als-geen-ander-script} [invoerbestand]... `e'-opdracht wordt niet ondersteund`}' wil geen adressengebaseerd op GNU sed versie %s kan label voor sprong naar `%s' niet vindenkan %s niet verwijderen: %skon %s niet hernoemen: %skan geen veranderaars opgeven bij een lege reguliere expressieopdracht gebruikt slechts één adresopmerkingen accepteren geen adreskon %s niet bewerken: is een terminalkon %s niet bewerken: geen gewoon bestandkon bestand %s niet openen: %skon tijdelijk bestand %s niet openen: %skon niet %d item naar %s schrijven: %skon niet %d items naar %s schrijven: %sscheidingsteken is geen enkel-byte-tekenfout in deelprocesverwachtte \ na `a', `c' of `i'verwachtte een nieuwere versie van sedextra tekens na opdrachtongeldige verwijzing \%d op rechterhandzijde van `s'-opdrachtongeldig gebruik van +N of ~N als eerste adresongeldig gebruik van regel-adres 0ontbrekende opdrachtmeerdere `!'smeerdere `g'-opties voor `s'-opdrachtmeerdere `p'-opties voor `s'-opdrachtmeerdere getalopties voor `s'-opdrachtgeen eerdere reguliere expressiegetaloptie voor `s'-opdracht mag niet nul zijnoptie `e' wordt niet ondersteundleesfout op %s: %stekenreeksen voor `y'-opdracht zijn van verschillende lengtesuper-sed versie %s onverwachte `,'onverwachte `}'onbekende opdracht: `%c'onbekende optie voor `s'ongepaarde `{'onafgemaakte `s'-opdrachtonafgemaakte `y'-opdrachtonafgemaakte reguliere expressie voor adreskbuild-3686/src/oldsed/po/ru.po0000664000175000017500000002764515053010106016366 0ustar locutuslocutus# Translation of sed-4.1.1.po to Russian # Copyright (C) 1998, 2004 Free Software Foundation, Inc. # Const Kaplinsky , 1998. # Pavel Maryanov , 2004. # msgid "" msgstr "" "Project-Id-Version: sed-4.1.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2004-07-07 17:54+0300\n" "Last-Translator: Pavel Maryanov \n" "Language-Team: Russian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=KOI8-R\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n>1;\n" "X-Generator: KBabel 1.3\n" #: sed/compile.c:162 msgid "multiple `!'s" msgstr "ÎÅÓËÏÌØËÏ ÓÉÍ×ÏÌÏ× `!'" #: sed/compile.c:163 msgid "unexpected `,'" msgstr "ÎÅÐÒÅÄ×ÉÄÅÎÎÙÊ ÓÉÍ×ÏÌ `,'" #: sed/compile.c:164 msgid "invalid usage of +N or ~N as first address" msgstr "ÉÓÐÏÌØÚÏ×ÁÎÉÅ +N ÉÌÉ ~N × ËÁÞÅÓÔ×Å ÐÅÒ×ÏÇÏ ÁÄÒÅÓÁ ÎÅÄÏÐÕÓÔÉÍÏ" #: sed/compile.c:165 msgid "unmatched `{'" msgstr "ÎÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ `{'" #: sed/compile.c:166 msgid "unexpected `}'" msgstr "ÎÅÐÒÅÄ×ÉÄÅÎÎÙÊ ÓÉÍ×ÏÌ `}'" #: sed/compile.c:167 msgid "extra characters after command" msgstr "ÌÉÛÎÉÅ ÓÉÍ×ÏÌÙ ÐÏÓÌÅ ËÏÍÁÎÄÙ" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "ÏÖÉÄÁÌÁÓØ \\ ÐÏÓÌÅ `a', `c' ÉÌÉ `i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' ÎÅ ÄÏÐÕÓËÁÅÔ ÕËÁÚÁÎÉÑ ËÁËÉÈ-ÌÉÂÏ ÁÄÒÅÓÏ×" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr "`:' ÎÅ ÄÏÐÕÓËÁÅÔ ÕËÁÚÁÎÉÑ ËÁËÉÈ-ÌÉÂÏ ÁÄÒÅÓÏ×" #: sed/compile.c:171 msgid "comments don't accept any addresses" msgstr "ËÏÍÍÅÎÔÁÒÉÉ ÎÅ ÄÏÐÕÓËÁÀÔ ÕËÁÚÁÎÉÑ ËÁËÉÈ-ÌÉÂÏ ÁÄÒÅÓÏ×" #: sed/compile.c:172 msgid "missing command" msgstr "ÏÔÓÕÔÓÔ×ÕÅÔ ËÏÍÁÎÄÁ" #: sed/compile.c:173 msgid "command only uses one address" msgstr "ËÏÍÁÎÄÁ ÉÓÐÏÌØÚÕÅÔ ÔÏÌØËÏ ÏÄÉÎ ÁÄÒÅÓ" #: sed/compile.c:174 msgid "unterminated address regex" msgstr "ÎÅÚÁ×ÅÒÛÅÎÎÏÅ ÁÄÒÅÓÎÏÅ ÒÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅ" #: sed/compile.c:175 msgid "unterminated `s' command" msgstr "ÎÅÚÁ×ÅÒÛÅÎÎÁÑ ËÏÍÁÎÄÁ `s'" #: sed/compile.c:176 msgid "unterminated `y' command" msgstr "ÎÅÚÁ×ÅÒÛÅÎÎÁÑ ËÏÍÁÎÄÁ `y'" #: sed/compile.c:177 msgid "unknown option to `s'" msgstr "ÎÅÉÚ×ÅÓÔÎÙÊ ÍÏÄÉÆÉËÁÔÏÒ Ë `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "ÎÅÓËÏÌØËÏ ÍÏÄÉÆÉËÁÔÏÒÏ× `p' Ó ËÏÍÁÎÄÏÊ `s'" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "ÎÅÓËÏÌØËÏ ÍÏÄÉÆÉËÁÔÏÒÏ× `g' Ó ËÏÍÁÎÄÏÊ `s'" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "ÎÅÓËÏÌØËÏ ÞÉÓÌÏ×ÙÈ ÍÏÄÉÆÉËÁÔÏÒÏ× Ó ËÏÍÁÎÄÏÊ `s'" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "ÞÉÓÌÏ×ÏÊ ÍÏÄÉÆÉËÁÔÏÒ ÄÌÑ ËÏÍÁÎÄÙ `s' ÎÅ ÍÏÖÅÔ ÂÙÔØ ÎÕÌÅ×ÙÍ" #: sed/compile.c:182 msgid "strings for `y' command are different lengths" msgstr "ÓÔÒÏËÉ ÄÌÑ ËÏÍÁÎÄÙ `y' ÉÍÅÀÔ ÒÁÚÎÕÀ ÄÌÉÎÕ" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "ÓÉÍ×ÏÌ-ÒÁÚÄÅÌÉÔÅÌØ ÎÅ Ñ×ÌÑÅÔÓÑ ÏÄÎÏÂÁÊÔÏ×ÙÍ ÓÉÍ×ÏÌÏÍ" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "ÏÖÉÄÁÌÁÓØ ÂÏÌÅÅ ÎÏ×ÁÑ ×ÅÒÓÉÑ sed" #: sed/compile.c:185 msgid "invalid usage of line address 0" msgstr "ÎÅÄÏÐÕÓÔÉÍÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÓÔÒÏËÉ ÁÄÒÅÓÁ 0" #: sed/compile.c:186 #, c-format msgid "unknown command: `%c'" msgstr "ÎÅÉÚ×ÅÓÔÎÁÑ ËÏÍÁÎÄÁ: `%c'" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: ÆÁÊÌ %s ÓÔÒÏËÁ %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e ×ÙÒÁÖÅÎÉÅ #%lu, ÓÉÍ×ÏÌ %lu: %s\n" #: sed/compile.c:1644 #, c-format msgid "can't find label for jump to `%s'" msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÎÁÊÔÉ ÍÅÔËÕ ÄÌÑ ÐÅÒÅÈÏÄÁ Ë `%s'" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: ÎÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ %s: %s\n" #: sed/execute.c:673 #, c-format msgid "couldn't edit %s: is a terminal" msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÒÅÄÁËÔÉÒÏ×ÁÔØ %s: ÜÔÏ ÔÅÒÍÉÎÁÌ" #: sed/execute.c:677 #, c-format msgid "couldn't edit %s: not a regular file" msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÒÅÄÁËÔÉÒÏ×ÁÔØ %s: ÜÔÏ ÎÅ ÏÂÙÞÎÙÊ ÆÁÊÌ" #: sed/execute.c:684 lib/utils.c:196 #, c-format msgid "couldn't open temporary file %s: %s" msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ×ÒÅÍÅÎÎÙÊ ÆÁÊÌ %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "ÏÛÉÂËÁ × ÐÏÄÐÒÏÃÅÓÓÅ" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "ÏÐÃÉÑ `e' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "ËÏÍÁÎÄÁ `e' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "ÎÅÔ ÐÒÅÄÙÄÕÝÅÇÏ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑ" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÕËÁÚÁÔØ ÍÏÄÉÆÉËÁÔÏÒÙ × ÐÕÓÔÏÍ ÒÅÇÕÌÑÒÎÏÍ ×ÙÒÁÖÅÎÉÉ" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "ÎÅÄÏÐÕÓÔÉÍÁÑ ÓÓÙÌËÁ \\%d ÎÁ RHS ËÏÍÁÎÄÙ `s'" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " ÉÓÐÏÌØÚÏ×ÁÎÉÅ × ÓËÒÉÐÔÅ ÓÉÎÔÁËÓÉÓÁ ÒÅÇÕÌÑÒÎÙÈ ×ÙÒÁÖÅÎÉÊ " "Perl 5.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" "éÓÐÏÌØÚÏ×ÁÎÉÅ: %s [ïðãéñ]... {ÔÏÌØËÏ-ÓËÒÉÐÔ-ÅÓÌÉ-ÎÅÔ-ÄÒÕÇÏÇÏ-ÓËÒÉÐÔÁ} " "[×ÈÏÄÎÏÊ-ÆÁÊÌ]...\n" "\n" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" " -n, --quiet, --silent\n" " ÐÏÄÁ×ÌÅÎÉÅ Á×ÔÏÍÁÔÉÞÅÓËÏÇÏ ×Ù×ÏÄÁ ÐÒÏÍÅÖÕÔËÏ×\n" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" " -e script, --expression=script\n" " ÄÏÂÁ×ÌÅÎÉÅ ÓËÒÉÐÔÁ × ÉÓÐÏÌÎÑÅÍÙÅ ËÏÍÁÎÄÙ\n" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" " -f script-file, --file=script-file\n" " ÄÏÂÁ×ÌÅÎÉÅ ÓÏÄÅÒÖÉÍÏÇÏ ÆÁÊÌÁ-ÓËÒÉÐÔÁ × ÉÓÐÏÌÎÑÅÍÙÅ ËÏÍÁÎÄÙ\n" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" " -i[óõææéëó], --in-place[=óõææéëó]\n" " ÒÅÄÁËÔÉÒÏ×ÁÎÉÅ ÆÁÊÌÏ× ÎÁ ÍÅÓÔÅ (ÓÏÚÄÁÅÔ ËÏÐÉÀ, ÅÓÌÉ ÕËÁÚÁÎÏ " "ÒÁÓÛÉÒÅÎÉÅ)\n" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" " -l N, --line-length=N\n" " ÕËÁÚÁÎÉÅ ÖÅÌÁÅÍÏÊ ÄÌÉÎÙ ÐÅÒÅÎÏÓÉÍÏÊ ÓÔÒÏËÉ ÄÌÑ ËÏÍÁÎÄÙ `l'\n" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" " --posix\n" " ÏÔËÌÀÞÅÎÉÅ ×ÓÅÈ ÒÁÓÛÉÒÅÎÉÊ GNU.\n" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -r, --regexp-extended\n" " ÉÓÐÏÌØÚÏ×ÁÎÉÅ × ÓËÒÉÐÔÅ ÒÁÓÛÉÒÅÎÎÙÈ ÒÅÇÕÌÑÒÎÙÈ ×ÙÒÁÖÅÎÉÊ.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" " -s, --separate\n" " ÄÏÐÕÝÅÎÉÅ, ÞÔÏ ÆÁÊÌÙ ÒÁÚÄÅÌÅÎÙ, Á ÎÅ × ×ÉÄÅ ÏÄÎÏÇÏ\n" " ÄÌÉÎÎÏÇÏ ÎÅÐÒÅÒÙ×ÎÏÇÏ ÐÏÔÏËÁ.\n" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" " -u, --unbuffered\n" " ÚÁÇÒÕÚËÁ ÍÉÎÉÍÁÌØÎÏÇÏ ÏÂßÅÍÁ ÄÁÎÎÙÈ ÉÚ ×ÈÏÄÎÙÈ ÆÁÊÌÏ×\n" " É ÂÏÌÅÅ ÞÁÓÔÙÊ ÓÂÒÏÓ ÎÁ ÄÉÓË ×ÙÈÏÄÎÙÈ ÂÕÆÅÒÏ×\n" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr " --help ×Ù×ÏÄ ÜÔÏÊ ÓÐÒÁ×ËÉ É ×ÙÈÏÄ\n" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr " --version ×Ù×ÏÄ ÉÎÆÏÒÍÁÃÉÉ Ï ×ÅÒÓÉÉ É ×ÙÈÏÄ\n" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" "\n" "åÓÌÉ ÏÐÃÉÑ -e, --expression, -f, ÉÌÉ --file ÎÅ ÕËÁÚÁÎÁ, ÔÏÇÄÁ ÐÅÒ×ÙÊ\n" "ÎÅÏÐÃÉÏÎÁÌØÎÙÊ ÁÒÇÕÍÅÎÔ ÂÅÒÅÔÓÑ ËÁË ÓËÒÉÐÔ sed ÄÌÑ ÉÎÔÅÒÐÒÅÔÁÃÉÉ. ÷ÓÅ\n" "ÏÓÔÁ×ÛÉÅÓÑ ÁÒÇÕÍÅÎÔÙ Ñ×ÌÑÀÔÓÑ ÉÍÅÎÁÍÉ ×ÈÏÄÎÙÈ ÆÁÊÌÏ×; ÅÓÌÉ ×ÈÏÄÎÙÅ\n" "ÆÁÊÌÙ ÎÅ ÕËÁÚÁÎÙ, ÔÏÇÄÁ ÞÉÔÁÅÔÓÑ ÓÔÁÎÔÁÒÔÎÙÊ ××ÏÄ.\n" "\n" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "ïÔÞÅÔÙ Ï ÏÛÉÂËÁÈ ÏÔÐÒÁ×ÌÑÊÔÅ ÐÏ ÁÄÒÅÓÕ: %s .\n" "õÂÅÄÉÔÅÓØ, ÞÔÏ ×ËÌÀÞÉÌÉ ÇÄÅ-ÌÉÂÏ × ÐÏÌÅ ``ôÅÍÁ:'' ÓÌÏ×Ï ``%s''.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed ×ÅÒÓÉÑ %s\n" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "ÏÓÎÏ×ÁÎ ÎÁ GNU sed ×ÅÒÓÉÉ %s\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed ×ÅÒÓÉÑ %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "üÔÏ Ó×ÏÂÏÄÎÏÅ ÐÒÏÇÒÁÍÍÎÏÅ ÏÂÅÓÐÅÞÅÎÉÅ; ÕÓÌÏ×ÉÑ ÅÇÏ ËÏÐÉÒÏ×ÁÎÉÑ ÓÍÏÔÒÉÔÅ ×\n" "ÉÓÈÏÄÎÙÈ ÔÅËÓÔÁÈ. îÅ ÐÒÅÄÏÓÔÁ×ÌÑÅÔÓÑ îéëáëïê ÇÁÒÁÎÔÉÉ; ÄÁÖÅ ÇÁÒÁÎÔÉÉ\n" "ðòéçïäîïóôé äìñ ðòïäáöé ÉÌÉ ðòéíåîéíïóôé äìñ ëïîëòåôîïê ãåìé, × ÔÏÊ ÍÅÒÅ,\n" "× ËÏÔÏÒÏÊ ÜÔÏ ÍÏÖÅÔ ÂÙÔØ ÄÏÐÕÝÅÎÏ ÚÁËÏÎÏÄÁÔÅÌØÓÔ×ÏÍ.\n" #: lib/utils.c:98 lib/utils.c:336 #, c-format msgid "cannot remove %s: %s" msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ %s: %s" #: lib/utils.c:143 #, c-format msgid "couldn't open file %s: %s" msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ %s: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "ÎÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ %d ÜÌÅÍÅÎÔ × %s: %s" msgstr[1] "ÎÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ %d ÜÌÅÍÅÎÔÏ× × %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "ÏÛÉÂËÁ ÞÔÅÎÉÑ %s: %s" #: lib/utils.c:341 #, c-format msgid "cannot rename %s: %s" msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÐÅÒÅÉÍÅÎÏ×ÁÔØ %s: %s" #: lib/regcomp.c:132 msgid "Success" msgstr "õÓÐÅÛÎÏ" #: lib/regcomp.c:135 msgid "No match" msgstr "îÅÔ ÓÏÏÔ×ÅÓÔ×ÉÑ" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "îÅÄÏÐÕÓÔÉÍÏÅ ÒÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅ" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "îÅÄÏÐÕÓÔÉÍÙÊ ÓÉÍ×ÏÌ ÓÒÁ×ÎÅÎÉÑ" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "îÅÄÏÐÕÓÔÉÍÏÅ ÉÍÑ ÄÌÑ ËÌÁÓÓÁ ÓÉÍ×ÏÌÁ" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "úÁ×ÅÒÛÁÀÝÁÑ ÏÂÒÁÔÎÁÑ ËÏÓÁÑ ÞÅÒÔÁ" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "îÅÄÏÐÕÓÔÉÍÁÑ ÏÂÒÁÔÎÁÑ ÓÓÙÌËÁ" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "îÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ [ ÉÌÉ [^" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "îÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ ( or \\(" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "îÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ \\{" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "îÅÄÏÐÕÓÔÉÍÏÅ ÓÏÄÅÒÖÉÍÏÅ × \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "îÅÄÏÐÕÓÔÉÍÏÅ ÏËÏÎÞÁÎÉÅ ÄÉÁÐÁÚÏÎÁ" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "ðÁÍÑÔØ ÉÓÞÅÒÐÁÎÁ" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "îÅÄÏÐÕÓÔÉÍÏÅ ÐÒÅÄÛÅÓÔ×ÕÀÝÅÅ ÒÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅ" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "ðÒÅÖÄÅ×ÒÅÍÅÎÎÏÅ ÏËÏÎÞÁÎÉÅ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑ" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "òÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅ ÓÌÉÛËÏÍ ÂÏÌØÛÏÅ" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "îÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ ) ÉÌÉ \\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "îÅÔ ÐÒÅÄÙÄÕÝÅÇÏ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑ" kbuild-3686/src/oldsed/po/ga.gmo0000664000175000017500000002257115053010106016464 0ustar locutuslocutus•ÞQ¤m,àúá,Ü5 7?\w`Ôu 5l «b V {Y Ò~ , «º ;% ö  3 Md j Ï ã ú3$Kp‚®·#Öú0BT fHs¼Öõ!5J(_ˆ#¦Ê$ê#)BM2à ×ø*5*`‹« »#É#í&8,W„-²àö* @Ng€˜›ó4:(=c>¡Và[7t“š\£VZWZ²Œ èš ƒ¤ÂÞfþey®Î.ê4Sb$u*šÅßä ù   F(o‰ ©(Êó 0 .) _) ‰2 ³3 æ)!3!D£!x(""E0"^*"%"º)"à/# ##:#^#o%#%#§+#Í$#ù:$$Y$r2$Š$½$Ó$ã$ó%%&%/%F%]$DQ"!@=ELB5?43 .N;2(:9%< /CP',KM #6+017F H*->J O8& I)GA If no -e, --expression, -f, or --file option is given, then the first non-option argument is taken as the sed script to interpret. All remaining arguments are names of input files; if no input files are specified, then the standard input is read. --help display this help and exit --version output version information and exit --posix disable all GNU extensions. -R, --regexp-perl use Perl 5's regular expressions syntax in the script. -e script, --expression=script add the script to the commands to be executed -f script-file, --file=script-file add the contents of script-file to the commands to be executed -i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if extension supplied) -l N, --line-length=N specify the desired line-wrap length for the `l' command -n, --quiet, --silent suppress automatic printing of pattern space -r, --regexp-extended use extended regular expressions in the script. -s, --separate consider files as separate rather than as a single continuous long stream. -u, --unbuffered load minimal amounts of data from the input files and flush the output buffers more often %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]... `e' command not supported`}' doesn't want any addressesbased on GNU sed version %s can't find label for jump to `%s'cannot remove %s: %scannot rename %s: %scannot specify modifiers on empty regexpcommand only uses one addresscomments don't accept any addressescouldn't edit %s: is a terminalcouldn't edit %s: not a regular filecouldn't open file %s: %scouldn't open temporary file %s: %scouldn't write %d item to %s: %scouldn't write %d items to %s: %sdelimiter character is not a single-byte charactererror in subprocessexpected \ after `a', `c' or `i'expected newer version of sedextra characters after commandinvalid reference \%d on `s' command's RHSinvalid usage of +N or ~N as first addressinvalid usage of line address 0missing commandmultiple `!'smultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandno previous regular expressionnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %sstrings for `y' command are different lengthssuper-sed version %s unexpected `,'unexpected `}'unknown command: `%c'unknown option to `s'unmatched `{'unterminated `s' commandunterminated `y' commandunterminated address regexProject-Id-Version: sed 4.1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2004-07-07 11:04-0500 Last-Translator: Kevin Patrick Scannell Language-Team: Irish MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=4; plural=n==1 ? 0 : (n>1 && n<7) ? 1 : (n>6 && n <11) ? 2 : 3; Mura bhfuil rogha -e, --expression, -f, nó --file ann, glacfar an chéad argóint nach raibh ina rogha mar an script `sed' a léirmhíniú. Tá gach argóint eile an t-ainm de comhad ionchuir; mura bhfuil comhad ann léigh ón ionchur caighdeánach. --help taispeáin an chabhair seo agus éirigh as --version taispeáin eolas faoin leagan agus éirigh as --posix díchumasaigh gach feabhsúchán GNU. -R, --regexp-perl bain úsáid as sloinn ionadaíochta atá ag Perl 5. -e script, --expression=script cuir an script leis na horduithe le rith -f comhad-script, --file=comhad-script cuir na línte i `comhad-script' leis na horduithe le rith -i[IARMHÍR], --in-place[=IARMHÍR] cuir eagar ar comhaid san áit a bhfuil siad (agus déan cúltaca má tá IARMHÍR tugtha -l N, --line-length=N ceap an fad timfhillte le haghaidh an ordaithe `l' -n, --quiet, --silent stop priontáil uathoibríoch den spás patrúin -r, --regexp-extended úsáid sloinn ionadaíochta feabhsaithe sa script. -s, --separate féach ar comhaid ina leith seachas mar sruth leanúnach. -u, --unbuffered lódáil cantaí beaga ó na comhaid ionchur agus sruthlaigh na maoláin aschur níos minice %s Is saorbhogearra an ríomhchlár seo; féach ar an bhunchód le haghaidh coinníollacha cóipeála. Níl baránta AR BITH ann; go fiú níl baránta ann d'INDÍOLTACHT nó FEILIÚNACHT DO FHEIDHM AR LEITH, an oiread atá ceadaithe de réir dlí. %s: -e slonn #%lu, char %lu: %s %s: ní féidir %s a léamh: %s %s: comhad %s líne %lu: %s Níl fáilte roimh seoltaí le `:'Seol tuairiscí fabhtanna chuig: %s . Cuir an focal ``%s'' áit éigin sa líne ``Subject:'' le do thoil. GNU sed, leagan %s Cúltagairt neamhbhailíAicme charachtair neamhbhailíCarachtar cóimheasa neamhbhailíÁbhar neamhbhailí idir \{\}Is neamhbhailí an slonn ionadaíochta roimh seoDeireadh raoin neamhbhailíSlonn ionadaíochta neamhbhailíCuimhne íditheNíl a leithéid annNíl aon slonn ionadaíochta roimh seoDeireadh le slonn ionadaíochta gan choinneSlonn ionadaíochta rómhórBua!Cúlslais ag deireadh( nó \( corr) nó \) corr[ nó [^ corr\{ corrÚsáid: %s [ROGHA]... {script-mura-bhfuil-script-eile} [inchomhad]... níl an t-ordú `e' ar fáilNíl fáilte roimh seoltaí le `}'bunaithe ar GNU sed, leagan %s níl aon fháil ar an lipéad `%s' don léimní féidir %s a scriosadh: %sní féidir %s a athainmniú: %sní féidir bunathraitheoirí a shonrú le slonn bánní úsáidtear an t-ordú ach seoladh amháinníl fáilte roimh seoltaí le nótaí tráchtaníorbh fhéidir %s a chur in eagar; is teirminéal éníorbh fhéidir %s a chur in eagar: ní gnáthcomhad éníorbh fhéidir an comhad %s a oscailt: %sníorbh fhéidir an comhad sealadach %s a oscailt: %sníorbh fhéidir %d rud a scríobh i %s: %sníorbh fhéidir %d rud a scríobh i %s: %sníorbh fhéidir %d rud a scríobh i %s: %sníorbh fhéidir %d rud a scríobh i %s: %stá an teorantóir ina charachtar ilbheartearráid i bhfo-phróiseasbhíothas ag súil le \ i ndiaidh `a', `c', nó `i'bhíothas ag súil le leagan `sed' níos úirecarachtair breise i ndiaidh an t-ordútagairt neamhbhailí \%d ar dheis ordú `s'ní féidir +N nó ~N a úsáid mar an chéad seoladhní féidir an seoladh líne 0 a úsáidordú ar iarraidh`!'-anna iomadúlaan iomarca roghanna `g' i ndiaidh `s'an iomarca roghanna `p' i ndiaidh `s'an iomarca roghanna uimhriúla i ndiaidh `s'níl aon slonn ionadaíochta roimh seoní cheadaítear nialas mar rogha uimhriúil leis an ordú `s'níl an rogha `e' ar fáilearráid ag léamh %s: %sní aon fad amháin ar na teaghráin leis an ordú `y'super-sed, leagan %s `,' gan choinne`}' gan choinneordú anaithnid: `%c'rogha anaithnid i ndiaidh `s'`{' corrordú `s' gan chríochnúordú `y' gan chríochnúseoladh regex gan chríochnúkbuild-3686/src/oldsed/po/he.gmo0000664000175000017500000000355515053010106016472 0ustar locutuslocutus•Þ „ì0º1%ì)Cd`Å#ä#&,,S€;•äÑ4¶ë) 5tH½Òð+-Y    %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. `}' doesn't want any addressesmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zeroread error on %s: %sProject-Id-Version: sed 3.02.80 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2001-08-04 20:37+0300 Last-Translator: Eli Zaretskii Language-Team: Hebrew MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-8 Content-Transfer-Encoding: 8-bit %s äååìî äðéà úéðëúä .øå÷îä éöá÷ úà äàø ,èåøéô øúéì ;úéùôç äðëú äðéä åæ úéðëú äãéîá úàæå ,àéäù úéìëú åæéàì äîàúä åà úåøéçñ íùì àì åìéôà ;úåéøçà áúëá .úàæ øùôàî ÷åçäù %s úéðëúá (%lu 'ñî -e éåèéá ìù %lu 'ñî åú) %s äàéâù %s úéðëúá %s úàéø÷á (%s) äàéâù %s úéðëúá (%s õáå÷ ìù %lu äøåù) %s äàéâù úåáåúë ìá÷î åðéà : .%s úáåúëì (bugs) äì÷ú éçååéã çåìùì àð .(``Subject'') ``ïåãðä'' úøåùá ``%s'' äìéî ìåìëì åãéô÷ä àðà úåáåúë ìá÷î åðéà `}'`s' äãå÷ôì íéáåøî `g' éðééôàî`s' äãå÷ôì íéáåøî `p' éðééôàî`s' äãå÷ôì íéáåøî øôñî éðééôàîñôà úåéäì ìåëé åðéà `s' äãå÷ôì éøôñî ïééôàî%s úàéø÷á (%s) äì÷úkbuild-3686/src/oldsed/po/sk.po0000664000175000017500000002551115053010106016343 0ustar locutuslocutus# Slovak translations for GNU sed package. # Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. # Marcel Telka , 2002, 2003. # Miroslav Vasko , 1999. # msgid "" msgstr "" "Project-Id-Version: GNU sed 4.0.8\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2003-10-25 17:22+0200\n" "Last-Translator: Marcel Telka \n" "Language-Team: Slovak \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural= (n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "Viacnásobný `!'" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "NeoÄakávaná `,'" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "+N alebo ~N sa nedá použiÅ¥ ako prvá adresa" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "Nezodpovedajúca `{'" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "NeoÄakávaná `}'" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "NadbytoÄné znaky po príkaze" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "OÄakávané \\ po `a', `c' alebo `i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' nevyžaduje akúkoľvek adresu" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": nechce akúkoľvek adresu" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "V komentári nie je prípustná akákoľvek adresa" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Chýbajúci príkaz" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Príkaz používa iba jednu adresu" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "NeukonÄený regulárny výraz adresy" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "NeukonÄený príkaz `s'" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "NeukonÄený príkaz `y'" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Neznáma voľba pre `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "viacnásobné použitie voľby `p' s príkazom `s'" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "viacnásobné použitie voľby `g' s príkazom `s'" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "príkaz `s' môže maÅ¥ maximálne jednu Äíselnú voľbu" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "Äíselná voľba príkazu `s' nemôže byÅ¥ nula" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "reÅ¥azce pre príkaz `y' majú rôzne dĺžky" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "oÄakávaná novÅ¡ia verzia programu sed" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Príkaz používa iba jednu adresu" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Neznámy príkaz:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: súbor %s, riadok %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e výraz #%lu, znak %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Návestie pre skok na `%s' nie je možné nájsÅ¥?" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: %s nie je možné ÄítaÅ¥: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Nebolo možné otvoriÅ¥ súbor %s: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Nebolo možné otvoriÅ¥ súbor %s: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Nebolo možné otvoriÅ¥ doÄasný súbor %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "chyba v podprocese" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "voľba `e' nie je podporovaná" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "príkaz `e' nie je podporovaný" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Bez predchádzajúceho regulárneho výrazu" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "Nie je možné zadaÅ¥ modifikátory pre prázdny regulárny výraz" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Neplatný odkaz \\%d na `s' príkazu RHS" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " použiÅ¥ syntax regulárnych výrazov z Perlu 5 v skripte.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " použiÅ¥ syntax regulárnych výrazov z Perlu 5 v skripte.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Správy o chybách zasielajte na adresu %s (iba anglicky).\n" "Prosím vložte slovo ``%s'' niekde do položky ``Predmet:''\n" "Komentáre k slovenskému prekladu zasielajte na adresu .\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed verzia %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "založené na GNU sed verzia 3.02.80\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed verzia %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Toto je voľné programové vybavenie; podmienky pre kopírovanie a " "rozÅ¡irovanie\n" "nájdete v zdrojových textoch. Toto programové vybavenie je BEZ záruky,\n" "a to aj bez záruky PREDAJNOSTI alebo VHODNOSTI PRE NEJAKà KONKRÉTNY ÚČEL.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: %s nie je možné ÄítaÅ¥: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Nebolo možné otvoriÅ¥ súbor %s: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "nebolo možné zapísaÅ¥ %d položiek do %s: %s" msgstr[1] "nebolo možné zapísaÅ¥ %d položku do %s: %s" msgstr[2] "nebolo možné zapísaÅ¥ %d položky do %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "chyba pri Äítaní z %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: %s nie je možné ÄítaÅ¥: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "Úspech" #: lib/regcomp.c:135 msgid "No match" msgstr "Nezodpovedá" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Neplatný regulárny výraz" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Neplatný znak pre porovnávanie" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Neplatný názov triedy znakov" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "UkonÄovacie opaÄné lomítko" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Neplatný spätný odkaz" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "Nezodpovedajúca [ alebo [^" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "Nezodpovedajúca ( alebo \\(" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "Nezodpovedajúca \\{" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Neplatný obsah \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Neplatný koniec rozsahu" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "VyÄerpaná pamäť" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Neplatný predchádzajúci regulárny výraz" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "NeoÄakávaný koniec regulárneho výrazu" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Regulárny výraz je príliÅ¡ veľký" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "Nezodpovedajúca ) alebo \\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Bez predchádzajúceho regulárneho výrazu" kbuild-3686/src/oldsed/po/pl.po0000664000175000017500000003016715053010106016344 0ustar locutuslocutus# Polish translations for GNU sed package. # Copyright (C) 2003, 2004 Free Software Foundation, Inc. # Wojciech Polak , 2003, 2004. # corrections: Jakub Bogusz , 2003. # msgid "" msgstr "" "Project-Id-Version: sed 4.1.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2004-07-08 19:58+0200\n" "Last-Translator: Wojciech Polak \n" "Language-Team: Polish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-2\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" #: sed/compile.c:162 msgid "multiple `!'s" msgstr "wielokrotny znak `!'" #: sed/compile.c:163 msgid "unexpected `,'" msgstr "nieoczekiwany znak `,'" #: sed/compile.c:164 msgid "invalid usage of +N or ~N as first address" msgstr "nieprawid³owe u¿ycie +N lub ~N jako pierwszego adresu" #: sed/compile.c:165 msgid "unmatched `{'" msgstr "niedopasowany znak `{'" #: sed/compile.c:166 msgid "unexpected `}'" msgstr "nieoczekiwany znak `}'" #: sed/compile.c:167 msgid "extra characters after command" msgstr "dodatkowe znaki po poleceniu" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "oczekiwano znaku \\ po `a', `c' lub `i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' nie chce ¿adnych adresów" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": nie chce ¿adnych adresów" #: sed/compile.c:171 msgid "comments don't accept any addresses" msgstr "komentarze nie akceptuj± ¿adnych adresów" #: sed/compile.c:172 msgid "missing command" msgstr "brakuje polecenia" #: sed/compile.c:173 msgid "command only uses one address" msgstr "polecenie u¿ywa tylko jednego adresu" #: sed/compile.c:174 msgid "unterminated address regex" msgstr "niezakoñczony adres wyra¿enia regularnego" #: sed/compile.c:175 msgid "unterminated `s' command" msgstr "niezakoñczone polecenie `s'" #: sed/compile.c:176 msgid "unterminated `y' command" msgstr "niezakoñczone polecenie `y'" #: sed/compile.c:177 msgid "unknown option to `s'" msgstr "nieznana opcja dla polecenia `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "wielokrotne opcje `p' dla polecenia `s'" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "wielokrotne opcje `g' dla polecenia `s'" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "wielokrotne opcje liczbowe dla polecenia `s'" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "opcja liczbowa dla polecenia `s' nie mo¿e byæ zerem" #: sed/compile.c:182 msgid "strings for `y' command are different lengths" msgstr "³añcuchy dla polecenia `y' s± ró¿nych d³ugo¶ci" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "znak ogranicznika nie jest pojedynczym znakiem-bajtem" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "oczekiwano nowszej wersji programu sed" #: sed/compile.c:185 msgid "invalid usage of line address 0" msgstr "nieprawid³owe u¿ycie adresu linii 0" #: sed/compile.c:186 #, c-format msgid "unknown command: `%c'" msgstr "nieznane polecenie: `%c'" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: plik %s linia %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e wyra¿enie #%lu, znak %lu: %s\n" #: sed/compile.c:1644 #, c-format msgid "can't find label for jump to `%s'" msgstr "nie mo¿na znale¼æ etykiety dla skoku do `%s'" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: nie mo¿na odczytaæ %s: %s\n" #: sed/execute.c:673 #, c-format msgid "couldn't edit %s: is a terminal" msgstr "nie mo¿na edytowaæ %s: plik jest terminalem" #: sed/execute.c:677 #, c-format msgid "couldn't edit %s: not a regular file" msgstr "nie mo¿na edytowaæ %s: to nie jest regularny plik" #: sed/execute.c:684 lib/utils.c:196 #, c-format msgid "couldn't open temporary file %s: %s" msgstr "nie mo¿na otworzyæ tymczasowego pliku %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "b³±d w podprocesie" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "opcja `e' nie jest wspierana" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "polecenie `e' nie jest wspierane" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "brak poprzedniego wyra¿enia regularnego" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "nie mo¿na wyszczególniæ modyfikatorów w pustym wyra¿eniu regularnym" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "nieprawid³owe odwo³anie \\%d po prawej stronie polecenia `s'" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " u¿ywa w skrypcie wyra¿enia regularne zgodne ze sk³adni± " "Perl 5.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" "U¿ycie: %s [OPCJE] {skrypt-tylko-wtedy-gdy-¿aden-inny-skrypt} [plik-" "wej¶ciowy]...\n" "\n" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" " -n, --quiet, --silent\n" " powstrzymuje automatyczne drukowanie przetwarzanych linii.\n" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" " -e skrypt, --expression=skrypt\n" " dodaje skrypt do poleceñ, które maj± byæ wykonane.\n" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" " -f plik-skryptowy, --file=plik-skryptowy\n" " dodaje zawarto¶æ pliku skryptowego do poleceñ,\n" " które maj± byæ wykonane.\n" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" " -i[rozszerzenie], --in-place[=rozszerzenie]\n" " edytuje pliki \"w miejscu\" (tworzy kopie zapasowe\n" " je¿eli zosta³o podane rozszerzenie).\n" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" " -l N, --line-length=N\n" " ustala po¿±dan± d³ugo¶æ ³amanych linii dla polecenia `l'.\n" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" " --posix\n" " wy³±cza wszystkie rozszerzenia GNU.\n" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -r, --regexp-extended\n" " u¿ywa w skrypcie rozszerzonych wyra¿eñ regularnych.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" " -s, --separate\n" " traktuje pliki jako oddzielne, a nie jako pojedynczy,\n" " d³ugi i ci±g³y strumieñ.\n" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" " -u, --unbuffered\n" " ³aduje minimaln± ilo¶æ danych z plików wej¶ciowych\n" " i czê¶ciej oczyszcza bufor wyj¶ciowy.\n" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr " --help wy¶wietla tê oto pomoc i koñczy pracê.\n" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr " --version wy¶wietla numer wersji i koñczy pracê.\n" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" "\n" "Je¿eli nie zostan± podane opcje -e, --expression, -f, lub --file,\n" "to wtedy pierwszy argument, który nie jest opcj± linii poleceñ sed,\n" "zostanie wziêty jako skrypt sed do przetworzenia. Wszystkie pozosta³e\n" "argumenty s± nazwami plików wej¶ciowych; je¿eli nie zostan± podane\n" "¿adne pliki wej¶ciowe, to wtedy odczytane zostanie standardowe wej¶cie.\n" "\n" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Ewentualne b³êdy prosimy zg³aszaæ na adres: %s\n" "W tym celu proszê dodaæ s³owo ``%s'' do tematu listu.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed wersja %s\n" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "na podstawie wersji GNU sed %s\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed wersja %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Niniejszy program jest wolnym oprogramowaniem; warunki kopiowania s± " "opisane\n" "w ¼ród³ach. Autorzy nie daj± ¯ADNYCH gwarancji, w tym równie¿ gwarancji\n" "PRZYDATNO¦CI DO SPRZEDA¯Y LUB DO KONKRETNYCH CELÓW.\n" #: lib/utils.c:98 lib/utils.c:336 #, c-format msgid "cannot remove %s: %s" msgstr "nie mo¿na usun±æ %s: %s" #: lib/utils.c:143 #, c-format msgid "couldn't open file %s: %s" msgstr "nie mo¿na otworzyæ pliku %s: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "nie mo¿na zapisaæ %d elementu do %s: %s" msgstr[1] "nie mo¿na zapisaæ %d elementów do %s: %s" msgstr[2] "nie mo¿na zapisaæ %d elementów do %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "b³±d odczytu w %s: %s" #: lib/utils.c:341 #, c-format msgid "cannot rename %s: %s" msgstr "nie mo¿na zmieniæ nazwy %s: %s" #: lib/regcomp.c:132 msgid "Success" msgstr "Sukces" #: lib/regcomp.c:135 msgid "No match" msgstr "Brak dopasowania" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Nieprawid³owe wyra¿enie regularne" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Nieprawid³owy znak porównania" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Nieprawid³owa nazwa klasy znaku" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Koñcowy znak backslash" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Nieprawid³owe odwo³anie wsteczne" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "Niedopasowany znak [ lub [^" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "Niedopasowany znak ( lub \\(" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "Niedopasowany znak \\{" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Nieprawid³owa zawarto¶æ \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Nieprawid³owy koniec zakresu" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Pamiêæ wyczerpana" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Nieprawid³owe poprzedzaj±ce wyra¿enie regularne" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Przedwczesny koniec wyra¿enia regularnego" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Wyra¿enie regularne jest zbyt du¿e" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "Niedopasowany znak ) lub \\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Brak poprzedniego wyra¿enia regularnego" kbuild-3686/src/oldsed/po/sk.gmo0000664000175000017500000001035515053010106016507 0ustar locutuslocutus•Þ'T5Œ`\aº¾%yŸ¶ÐdíRf}š¶$Îó 1:#Y}˜ ³Å× éöB/r†#¤#È&ì,@YnŠ„` ï p! `# ‚ ¦ ÅÊ á ¬ ¿ Ø ÷ , - Z s £+ °* Ü%-5TpŒ¨¼"Üÿ( 2É2ü:/1jœ»Ø!"  ' # % &$ -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessexpected newer version of sedmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: GNU sed 4.0.8 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2003-10-25 17:22+0200 Last-Translator: Marcel Telka Language-Team: Slovak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural= (n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0; -R, --regexp-perl použiÅ¥ syntax regulárnych výrazov z Perlu 5 v skripte. %s Toto je voľné programové vybavenie; podmienky pre kopírovanie a rozÅ¡irovanie nájdete v zdrojových textoch. Toto programové vybavenie je BEZ záruky, a to aj bez záruky PREDAJNOSTI alebo VHODNOSTI PRE NEJAKà KONKRÉTNY ÚČEL. %s: -e výraz #%lu, znak %lu: %s %s: %s nie je možné ÄítaÅ¥: %s %s: súbor %s, riadok %lu: %s : nechce akúkoľvek adresuSprávy o chybách zasielajte na adresu %s (iba anglicky). Prosím vložte slovo ``%s'' niekde do položky ``Predmet:'' Komentáre k slovenskému prekladu zasielajte na adresu . GNU sed verzia %s Neplatný spätný odkazNeplatný názov triedy znakovNeplatný znak pre porovnávanieNeplatný obsah \{\}Neplatný predchádzajúci regulárny výrazNeplatný koniec rozsahuNeplatný regulárny výrazVyÄerpaná pamäťNezodpovedáBez predchádzajúceho regulárneho výrazuNeoÄakávaný koniec regulárneho výrazuRegulárny výraz je príliÅ¡ veľkýÚspechUkonÄovacie opaÄné lomítkoNezodpovedajúca ( alebo \(Nezodpovedajúca ) alebo \)Nezodpovedajúca [ alebo [^Nezodpovedajúca \{príkaz `e' nie je podporovaný`}' nevyžaduje akúkoľvek adresunebolo možné zapísaÅ¥ %d položiek do %s: %snebolo možné zapísaÅ¥ %d položku do %s: %snebolo možné zapísaÅ¥ %d položky do %s: %schyba v podproceseoÄakávaná novÅ¡ia verzia programu sedviacnásobné použitie voľby `g' s príkazom `s'viacnásobné použitie voľby `p' s príkazom `s'príkaz `s' môže maÅ¥ maximálne jednu Äíselnú voľbuÄíselná voľba príkazu `s' nemôže byÅ¥ nulavoľba `e' nie je podporovanáchyba pri Äítaní z %s: %ssuper-sed verzia %s kbuild-3686/src/oldsed/po/fi.gmo0000664000175000017500000000776615053010106016504 0ustar locutuslocutus•Þ'T5Œ`\aº¾%yŸ¶ÐdíRf}š¶$Îó 1:#Y}˜ ³Å× éöB/r†#¤#È&ì,@Yn…„} Þ ˆ$ g# Œ ° Îf ç N a   ¹* × !  = J$ T+ y# ¥ É Ò å ú $1KgfÎ$å$ $/ T4uªÅá!"  ' # % &$ -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessexpected newer version of sedmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: sed-4.0.8 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2003-12-07 09:35+0200 Last-Translator: Sami J. Laine Language-Team: Finnish MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n != 1; -R, --regexp-perl käytä Perl 5:en mukaista säännöllisten lauseiden syntaksia skriptissä. %s Tämä ohjelma on vapaa ohjelmisto; tarkista jakeluehdot lähdekoodista. Tälle ohjelmalle ei anneta minkäänlaista takuuta; ei edes takuuta kaupallisesti hyväksyttävästä laadusta tai soveltuvuudesta tiettyyn tarkoitukseen. %s: -e lauseke #%lu, merkki %lu: %s %s: ei voida lukea syötettä %s: %s %s: tiedosto %s rivi %lu: %s : ei tarvitse osoitteitaLähetä virheraportit osoitteeseen %s . Sisällytä sana "%s" viestin aihekenttään ("Subject"-kenttään). GNU sed versio %s Virheellinen takaisinviittausVirhellinen merkkiluokan nimiVirheellinen vertailumerkkiVirheellinen sisältö \{\}:ssäVirheellinen edeltävä säännöllinen lausekeVirheellinen välin loppuVirheellinen säännöllinen lausekeMuisti loppuEi osumaaEi aikaisempaa säännöllistä lausettaEnnenaikainen säännöllisen lausekkeen loppuSäännöllinen lauseke on liian suuriOnnistuiSeuraava kenoviivaPariton "(" tai "\("Pariton ")" tai "\)"Pariton "[" tai "[^"Pariton "\{"komento `e' ei ole tuettu"}" ei tarvitse osoitteita%d kohdetta ei voitu kirjoittaa tulosteeseen %s: %s%d kohdetta ei voitu kirjoittaa tulosteeseen %s: %svirhe lapsiprosessissaodotettiin uudempaa versiota sed:stäuseita "g"-valitsimia "s"-komennolleuseita "p"-valitsimia "s"-komennolleuseita valitsimia "s"-komennollenumeerinen valitsin "s"-komennolle ei voi olla nollavalitsin `e' ei ole tuettulukuvirhe syötteessä %s: %ssuper-sed versio %s kbuild-3686/src/oldsed/po/ko.po0000664000175000017500000002276215053010106016344 0ustar locutuslocutus# ko.po -- Korean messages for GNU sed # Copyright (C) 2001 Free Software Foundation, Inc. # Jong-Hoon Ryu , 2001. # msgid "" msgstr "" "Project-Id-Version: GNU sed 3.02.80\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2001-10-12 17:26+0900\n" "Last-Translator: Jong-Hoon Ryu \n" "Language-Team: Korean \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=EUC-KR\n" "Content-Transfer-Encoding: 8bit\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "`!' °¡ Áߺ¹µÇ¾ú½À´Ï´Ù" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "ºÒÇÊ¿äÇÑ `,' °¡ »ç¿ëµÇ°í ÀÖ½À´Ï´Ù" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "ù¹øÂ° ÁÖ¼Ò·Î '+N' ¶Ç´Â '~N' À» »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "`{' °¡ ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "ºÒÇÊ¿äÇÑ `}' °¡ »ç¿ëµÇ°í ÀÖ½À´Ï´Ù" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "¸í·ÉµÚ¿¡ ÇÊ¿ä¾ø´Â ¹®ÀÚµéÀÌ ÀÖ½À´Ï´Ù" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' ¿¡ ¾î¶°ÇÑ ÁÖ¼Òµµ ÇÊ¿äÄ¡ ¾Ê½À´Ï´Ù" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": ¿¡ ¾î¶°ÇÑ ÁÖ¼Òµµ ÇÊ¿äÄ¡ ¾Ê½À´Ï´Ù" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "ÄÚ¸àÆ®¿¡ ¾î¶°ÇÑ ÁÖ¼Òµµ »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "¸í·ÉÀÌ ÁöÁ¤µÇÁö ¾Ê¾Ò½À´Ï´Ù" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "¸í·É¿¡ ÇϳªÀÇ ÁÖ¼Ò¸¸ »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "ÁÖ¼Ò Á¤±ÔÇ¥Çö½Ä Á¾·áµÇÁö ¾Ê¾Ò½À´Ï´Ù" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "`s' ¸í·ÉÀÌ Á¾·áµÇÁö ¾Ê¾Ò½À´Ï´Ù" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "`y' ¸í·ÉÀÌ Á¾·áµÇÁö ¾Ê¾Ò½À´Ï´Ù" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "`s' ¿¡ ¾Ë ¼ö ¾ø´Â ¿É¼ÇÀÌ ÀÖ½À´Ï´Ù" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "`s' ¸í·É¿¡ `p' ¿É¼ÇÀÌ Áߺ¹µÇ¾î ÀÖ½À´Ï´Ù" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "`s' ¸í·É¿¡ `g' ¿É¼ÇÀÌ Áߺ¹µÇ¾î ÀÖ½À´Ï´Ù" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "`s' ¸í·É¿¡ ¼ýÀÚ ¿É¼ÇÀÌ Áߺ¹µÇ¾î ÀÖ½À´Ï´Ù" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "`s' ¸í·ÉÀÇ ¼ýÀÚ ¿É¼Ç¿¡ '0' À» ÁöÁ¤ÇÒ ¼ö ¾ø½À´Ï´Ù" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "`y' ¸í·ÉÀÇ ¹®ÀÚ¿­ÀÌ ±æÀ̰¡ ´Ù¸¨´Ï´Ù" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "ÁÖ¼Ò º¯°æÀÚ(modifier)ÀÇ »ç¿ëÀÌ ¿Ã¹Ù¸£Áö ¾Ê½À´Ï´Ù" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "¾Ë ¼ö ¾ø´Â ¸í·É:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: %s ÆÄÀÏÀÇ %lu ¹øÂ° ÁÙ: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e expression #%lu, char %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "`%s' (À¸)·Î Á¡ÇÁÇÒ ·¹À̺íÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: %s (À»)¸¦ ÀÐÀ» ¼ö ¾øÀ½: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "%s ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "%s ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "%s ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "¹ö±×¸¦ º¸°íÇÒ E-mail ÁÖ¼Ò: %s .\n" "``Subject:'' Ç׸ñ¿¡ ¹Ýµå½Ã ``%s'' ´Ü¾î¸¦ Æ÷ÇÔÇØ Áֽñ⠹ٶø´Ï´Ù.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "ÀÌ ÇÁ·Î±×·¥Àº ÀÚÀ¯ ¼ÒÇÁÆ®¿þ¾î ÀÔ´Ï´Ù; ÀÚ¼¼ÇÑ ³»¿ëÀº ÀúÀÛ±Ç ³»¿ëÀÇ ¿ø¹®À»\n" "Âü°íÇϽñ⠹ٶø´Ï´Ù. ÀÌ ÇÁ·Î±×·¥Àº ¹ý¿¡ ÀúÃ˵ÇÁö ¾Ê´Â ¹üÀ§¿¡¼­ »ó¾÷ÀûÀ̳ª\n" "Ư¼ö ¸ñÀûÀ¸·Î »ç¿ëµÉ °æ¿ì¸¦ Æ÷ÇÔÇÑ ¾î¶°ÇÑ °æ¿ì¿¡µµ º¸ÁõÇÏÁö ¾Ê½À´Ï´Ù.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: %s (À»)¸¦ ÀÐÀ» ¼ö ¾øÀ½: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "%s ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù" #: lib/utils.c:220 #, fuzzy, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "%2$s ¿¡ %1$d Ç׸ñ(item)À» ±â·ÏÇÒ ¼ö ¾ø½À´Ï´Ù: %3$s" msgstr[1] "%2$s ¿¡ %1$d Ç׸ñ(item)À» ±â·ÏÇÒ ¼ö ¾ø½À´Ï´Ù: %3$s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "%s ÀÇ ³»¿ë Àб⠿À·ù: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: %s (À»)¸¦ ÀÐÀ» ¼ö ¾øÀ½: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "" #: lib/regcomp.c:135 msgid "No match" msgstr "" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "" #: lib/regcomp.c:153 #, fuzzy msgid "Unmatched [ or [^" msgstr "`{' °¡ ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù" #: lib/regcomp.c:156 #, fuzzy msgid "Unmatched ( or \\(" msgstr "`{' °¡ ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù" #: lib/regcomp.c:159 #, fuzzy msgid "Unmatched \\{" msgstr "`{' °¡ ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "" #: lib/regcomp.c:180 #, fuzzy msgid "Unmatched ) or \\)" msgstr "`{' °¡ ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "" kbuild-3686/src/oldsed/po/ChangeLog0000664000175000017500000000243515053010106017140 0ustar locutuslocutus2004-11-11 Paolo Bonzini * Makevars: New. 2004-11-02 gettextize * Makefile.in.in: Upgrade to gettext-0.10.40. 2002-10-26 Paolo Bonzini * po/*.po: updated from Translation Project 2001-10-19 gettextize * Makefile.in.in: Upgrade to gettext-0.10.40. * cat-id-tbl.c: Remove file. * stamp-cat-id: Remove file. 2001-03-02 Paolo Bonzini * po/it.po: updated * po/sed.pot: likewise. 2000-12-10 Paolo Bonzini * po/it.po: Italian translation reviewed for new POT file. * po/sed.pot: updated Mon Mar 15 16:25:53 PST 1999 Ken Pizzini * po/it.po: new translation file. Sun Feb 7 21:22:17 PST 1999 Ken Pizzini * po/de.po: new translation file. Sat Dec 12 11:18:55 PST 1998 Ken Pizzini * po/ru.po: new translation file. Sun Dec 6 00:51:23 PST 1998 Ken Pizzini * po/fr.po: new translation file. Sun Aug 16 02:59:20 PDT 1998 Ken Pizzini * sed/compile.c: added N_() markers and corresponding gettext() (er, _()) calls. * po/sed.pot: updated to reflect changed and newly marked text. 1998-07-24 Erick Branderhorst * po/nl.po: Dutch translation. kbuild-3686/src/oldsed/po/id.po0000664000175000017500000002464015053010106016324 0ustar locutuslocutus# translation of sed-4.0.9.id.po to Indonesian # sed 4.0.9 (Indonesian) # Copyright (C) 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc. # Tedi Heriyanto , 2002, 2003, 2004. # msgid "" msgstr "" "Project-Id-Version: sed 4.0.9\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2004-04-27 14:56+0700\n" "Last-Translator: Tedi Heriyanto \n" "Language-Team: Indonesian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: KBabel 1.3\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "`!' ganda" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "`,' tidak diharapkan" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "Tidak dapat menggunakan +N atau ~N sebagai alamat pertama" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "`{' tidak sesuai" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "`}' tidak diharapkan" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Karakter tambahan setelah perintah" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "Diharapkan \\ setelah `a', `c' atau `i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' tidak menginginkan alamat" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": tidak menginginkan alamat" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Komentar tidak menerima alamat" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Perintah hilang" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Perintah hanya menggunakan satu alamat" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Alamat regex yang tidak selesai" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Perintah `s' tidak selesai" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Perintah `y' tidak selesai" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Opsion tidak dikenal bagi `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "opsion `p' ganda bagi perintah `s'" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "opsion `g' ganda bagi perintah `s'" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "opsion beragam untuk perintah `s'" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "opsion angka untuk perintah `s' tidak boleh nol" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "string untuk perintah y dalam panjang yang berbeda" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "mengharapkan versi baru sed" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Penggunaan modifier alamat yang tidak valid" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Perintah tidak dikenal:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: file %s baris %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e ekspresi #%lu, char %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Tidak dapat menemukan label untuk melompat ke `%s'" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: tidak dapat membaca %s: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Tidak dapat membuka file %s %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Tidak dapat membuka file %s %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Tidak dapat membuka file temporer %s %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "kesalahan dalam subproses" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "option `e' tidak didukung" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "perintah `e' tidak didukung" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Tidak ada reguler ekspresi sebelumnya" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "Tidak dapat menspesifikasikan modified pada regexp kosong" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Referensi tidak valid \\%d pada perintah `s' RHS" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " gunakan sintaks reguler ekspresi Perl 5 dalam skrip.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " gunakan sintaks reguler ekspresi Perl 5 dalam skrip.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Email laporan kesalahan ke: %s \n" "Pastikan untuk menyertakan kata \"%s\" di field \"Subject:\".\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed versi %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "berdasarkan pada GNU sed versi 3.02.80\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed versi %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: tidak dapat membaca %s: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Tidak dapat membuka file %s %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "tidak dapat menulis %d item ke %s: %s" msgstr[1] "tidak dapat menulis %d item ke %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "kesalahan pembacaan pada %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: tidak dapat membaca %s: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "Sukses" #: lib/regcomp.c:135 msgid "No match" msgstr "Tidak cocok" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Reguler ekspresi tidak valid" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Karakter kolasi tidak valid" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Nama kelas karakter tidak valid" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Trailing backslash" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Referensi balik tidak valid" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "[ atau [^ tidak sesuai" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "( atau \\( tidak sesuai" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "\\{ tidak sesuai" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Isi \\{\\} tidak valid" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Akhir batas tidak valid" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Memori habis" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Reguler ekspresi sebelumnya tidak valid" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Akhir reguler ekspresi prematur" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Reguler ekspresi terlalu besar" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr ") atau \\) tidak sesuai" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Tidak ada reguler ekspresi sebelumnya" kbuild-3686/src/oldsed/po/tr.gmo0000664000175000017500000001001115053010106016504 0ustar locutuslocutus•Þ'T5Œ`\aº¾%yŸ¶ÐdíRf}š¶$Îó 1:#Y}˜ ³Å× éöB/r†#¤#È&ì,@Yn„^ É s = ^ v “¹ ¯ i  • ³ Ò" é  " 9 I _ } œ ¹ Å ß ö "2LMe³'Å2í2 4S4ˆ½Ûó!"  ' # % &$ -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessexpected newer version of sedmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: sed 4.0.9 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2004-05-19 18:06+0300 Last-Translator: Deniz Akkus Kanca Language-Team: Turkish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: KBabel 1.0.2 Plural-Forms: nplurals=1; plural=0; -R, --regexp-perl betikte Perl 5'in düzenli ifade sözdizimini kullanır. %s Bu serbest yazılımdır; kopyalama koÅŸulları için kaynak koduna bakınız. Hiçbir garantisi yoktur; hatta SATILABİLİRLİĞİ veya HERHANGİ BİR AMACA UYGUNLUÄžU için bile garanti verilmez. %s: -e ifade #%lu, harf %lu: %s %s: %s okunamıyor: %s %s: dosya %s satır %lu: %s : için hiç adres istenmezYazılım hatalarını %s adresine, çeviri hatalarını adresine bildirin. ``%s'' sözcüğünün Konu baÅŸlığında yer almasına dikkat edin. GNU sed sürümü %s Hatalı geri referansHatalı karakter sınıf ismiHatalı birleÅŸtirme karakteri\{\} içeriÄŸi hatalıBir önceki düzenli ifade hatalıGeçersiz kapsam sonuHatalı düzenli ifadeBellek tükendiEÅŸleÅŸme bulunamadıDaha önce düzenli ifade yokDüzenli ifade erken sonlandıDüzenli ifade fazla büyükBaÅŸarılıSonda fazla gerikesme varEÅŸleÅŸmeyen ( veya \(EÅŸleÅŸmeyen ) or \)EÅŸleÅŸmeyen [ veya [^EÅŸleÅŸmeyen \{`e' komutu desteklenmiyor'}' için adres istenmez%d sayıda öğe %s'e yazılamadı: %s%d sayıda öğe %s'e yazılamadı: %saltsüreçte hatased'in daha yeni bir sürümü beklendi`s' komutuna birden fazla `g' seçeneÄŸi verilmiÅŸ`s' komutuna birden fazla `p' seçeneÄŸi verilmiÅŸ`s' komutuna birden fazla sayı seçeneÄŸi verilmiÅŸ`s' komutuna verilen sayı seçeneÄŸi sıfır olamaz e' seçeneÄŸi desteklenmiyor%s'de okuma hatası: %ssuper-sed sürüm %s kbuild-3686/src/oldsed/po/en@quot.header0000664000175000017500000000226315053010106020152 0ustar locutuslocutus# All this catalog "translates" are quotation characters. # The msgids must be ASCII and therefore cannot contain real quotation # characters, only substitutes like grave accent (0x60), apostrophe (0x27) # and double quote (0x22). These substitutes look strange; see # http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html # # This catalog translates grave accent (0x60) and apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019). # It also translates pairs of apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019) # and pairs of quotation mark (0x22) to # left double quotation mark (U+201C) and right double quotation mark (U+201D). # # When output to an UTF-8 terminal, the quotation characters appear perfectly. # When output to an ISO-8859-1 terminal, the single quotation marks are # transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to # grave/acute accent (by libiconv), and the double quotation marks are # transliterated to 0x22. # When output to an ASCII terminal, the single quotation marks are # transliterated to apostrophes, and the double quotation marks are # transliterated to 0x22. # kbuild-3686/src/oldsed/po/nl.po0000664000175000017500000003615615053010106016346 0ustar locutuslocutus# Dutch translation of sed. # Copyright (C) 2004, 2005 Free Software Foundation, Inc. # This file is distributed under the same license as the sed package. # Taco Witte , 2004, 2005. # # msgid "" msgstr "" "Project-Id-Version: sed 4.1.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2005-04-12 20:09+0200\n" "Last-Translator: Taco Witte \n" "Language-Team: Dutch \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: sed/compile.c:162 msgid "multiple `!'s" msgstr "meerdere `!'s" #: sed/compile.c:163 msgid "unexpected `,'" msgstr "onverwachte `,'" #: sed/compile.c:164 msgid "invalid usage of +N or ~N as first address" msgstr "ongeldig gebruik van +N of ~N als eerste adres" #: sed/compile.c:165 msgid "unmatched `{'" msgstr "ongepaarde `{'" #: sed/compile.c:166 msgid "unexpected `}'" msgstr "onverwachte `}'" #: sed/compile.c:167 msgid "extra characters after command" msgstr "extra tekens na opdracht" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "verwachtte \\ na `a', `c' of `i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' wil geen adressen" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": wil geen adressen" #: sed/compile.c:171 msgid "comments don't accept any addresses" msgstr "opmerkingen accepteren geen adres" #: sed/compile.c:172 msgid "missing command" msgstr "ontbrekende opdracht" #: sed/compile.c:173 msgid "command only uses one address" msgstr "opdracht gebruikt slechts één adres" #: sed/compile.c:174 msgid "unterminated address regex" msgstr "onafgemaakte reguliere expressie voor adres" #: sed/compile.c:175 msgid "unterminated `s' command" msgstr "onafgemaakte `s'-opdracht" #: sed/compile.c:176 msgid "unterminated `y' command" msgstr "onafgemaakte `y'-opdracht" #: sed/compile.c:177 msgid "unknown option to `s'" msgstr "onbekende optie voor `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "meerdere `p'-opties voor `s'-opdracht" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "meerdere `g'-opties voor `s'-opdracht" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "meerdere getalopties voor `s'-opdracht" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "getaloptie voor `s'-opdracht mag niet nul zijn" #: sed/compile.c:182 msgid "strings for `y' command are different lengths" msgstr "tekenreeksen voor `y'-opdracht zijn van verschillende lengte" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "scheidingsteken is geen enkel-byte-teken" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "verwachtte een nieuwere versie van sed" #: sed/compile.c:185 msgid "invalid usage of line address 0" msgstr "ongeldig gebruik van regel-adres 0" #: sed/compile.c:186 #, c-format msgid "unknown command: `%c'" msgstr "onbekende opdracht: `%c'" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: bestand %s regel %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e expressie #%lu, teken %lu: %s\n" #: sed/compile.c:1644 #, c-format msgid "can't find label for jump to `%s'" msgstr "kan label voor sprong naar `%s' niet vinden" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: kan %s niet lezen: %s\n" #: sed/execute.c:673 #, c-format msgid "couldn't edit %s: is a terminal" msgstr "kon %s niet bewerken: is een terminal" #: sed/execute.c:677 #, c-format msgid "couldn't edit %s: not a regular file" msgstr "kon %s niet bewerken: geen gewoon bestand" #: sed/execute.c:684 lib/utils.c:196 #, c-format msgid "couldn't open temporary file %s: %s" msgstr "kon tijdelijk bestand %s niet openen: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "fout in deelproces" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "optie `e' wordt niet ondersteund" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "`e'-opdracht wordt niet ondersteund" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "geen eerdere reguliere expressie" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "kan geen veranderaars opgeven bij een lege reguliere expressie" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "ongeldige verwijzing \\%d op rechterhandzijde van `s'-opdracht" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " de syntaxis van Perl 5 voor reguliere expressie gebruiken " "in het script.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" "Gebruik: %s [OPTIE]... {script-alleen-als-geen-ander-script} " "[invoerbestand]...\n" "\n" #: sed/sed.c:102 #, fuzzy, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" "-n, --quiet, --silent\n" " automatische weergave van patroonruimte onderdrukken\n" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" " -e script, --expression=SCRIPT\n" " het SCRIPT toevoegen aan uit te voeren opdrachten\n" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" " -f script-file, --file=SCRIPTBESTAND\n" " de inhoud van SCRIPTBESTAND toevoegen aan uit te voeren " "opdrachten\n" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" " -i[ACHTERVOEGSEL], --in-place[=ACHTERVOEGSEL]\n" " bestanden ter plekke bewerken (maakt reservekopie als " "extensie gegeven)\n" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" " -l AANTAL, --line-length=AANTAL\n" " gewenste regelafbreeklengte opgeven voor `l'-opdracht\n" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" " --posix\n" " alle GNU-uitbreidingen uit zetten.\n" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -r, --regexp-extended\n" " uitgebreide reguliere expressies gebruiken in het script.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" " -s, --separate\n" " bestanden als losstaand beschouwen i.p.v. als enkele " "continue stroom.\n" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" " -u, --unbuffered\n" " minimale hoeveelheid gegevens laden uit invoerbestanden en\n" " uitvoerbuffers vaker leegmaken\n" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr " --help deze hulp weergeven en afsluiten\n" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr " --version versie-informatie weergeven en afsluiten\n" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" "\n" "Als geen -e, --expression, -f of --file optie gegeven is, wordt het\n" "eerste niet-optie argument genomen als het te interpreteren sed-script.\n" "Alle overblijvende argumenten zijn namen van invoerbestanden; als geen\n" "invoerbestanden opgegeven zijn, wordt standaardinvoer gelezen.\n" "\n" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Stuur foutrapporten naar: %s .\n" "Zorg ervoor dat het woord ``%s'' ergens in het ``Onderwerp:''-veld staat.\n" "Rapporteer fouten in de vertalingen bij .\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed versie %s\n" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "gebaseerd op GNU sed versie %s\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed versie %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Dit is vrije software; zie de bron voor kopieervoorwaarden. Er is GEEN\n" "garantie; zelfs niet voor VERHANDELBAARHEID of GESCHIKTHEID VOOR\n" "EEN BEPAALD DOEL, tot het uiterste dat door de wet wordt toegestaan.\n" #: lib/utils.c:98 lib/utils.c:336 #, c-format msgid "cannot remove %s: %s" msgstr "kan %s niet verwijderen: %s" #: lib/utils.c:143 #, c-format msgid "couldn't open file %s: %s" msgstr "kon bestand %s niet openen: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "kon niet %d item naar %s schrijven: %s" msgstr[1] "kon niet %d items naar %s schrijven: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "leesfout op %s: %s" #: lib/utils.c:341 #, c-format msgid "cannot rename %s: %s" msgstr "kon %s niet hernoemen: %s" #: lib/regcomp.c:132 msgid "Success" msgstr "Gelukt" #: lib/regcomp.c:135 msgid "No match" msgstr "Geen overeenkomst" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Ongeldige reguliere expressie" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Ongeldig sorteerteken" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Ongeldige tekenklassenaam" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Backslash aan het einde" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Ongeldige terugverwijzing" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "Ongepaarde [ of [^" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "Ongepaarde ( of \\(" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "Ongepaarde \\{" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Ongeldige inhoud van \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Ongeldig bereikeinde" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Onvoldoende geheugen" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Ongeldige voorafgaande reguliere expressie" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Voortijdig einde van reguliere expressie" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Reguliere expressie is te groot" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "Ongepaarde ) of \\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Geen eerdere reguliere expressie" #~ msgid "Called savchar() with unexpected pushback (%x)" #~ msgstr "savchar() aangeroepen met onverwachte pushback (%x)" #~ msgid "INTERNAL ERROR: bad address type" #~ msgstr "INTERNE FOUT: slechte adressoort" #~ msgid "INTERNAL ERROR: Bad cmd %c" #~ msgstr "INTERNE FOUT: Slechte opdracht %c" #~ msgid "" #~ "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" #~ "\n" #~ " -n, --quiet, --silent\n" #~ " suppress automatic printing of pattern space\n" #~ " -e script, --expression=script\n" #~ " add the script to the commands to be executed\n" #~ " -f script-file, --file=script-file\n" #~ " add the contents of script-file to the commands to be " #~ "executed\n" #~ " -i[suffix], --in-place[=suffix]\n" #~ " edit files in place (makes backup if extension " #~ "supplied)\n" #~ " -l N, --line-length=N\n" #~ " specify the desired line-wrap length for the `l' " #~ "command\n" #~ " -r, --regexp-extended\n" #~ " use extended regular expressions in the script.\n" #~ "%s -s, --separate\n" #~ " consider files as separate rather than as a single " #~ "continuous\n" #~ " long stream.\n" #~ " -u, --unbuffered\n" #~ " load minimal amounts of data from the input files and " #~ "flush\n" #~ " the output buffers more often\n" #~ " --help display this help and exit\n" #~ " -V, --version output version information and exit\n" #~ "\n" #~ "If no -e, --expression, -f, or --file option is given, then the first\n" #~ "non-option argument is taken as the sed script to interpret. All\n" #~ "remaining arguments are names of input files; if no input files are\n" #~ "specified, then the standard input is read.\n" #~ "\n" #~ msgstr "" #~ "Gebruik: %s [OPTIE]... {script-alleen-als-geen-ander-script} " #~ "[invoerbestand]...\n" #~ "\n" #~ " -n, --quiet, --silent\n" #~ " automatische weergave van patroonruimte onderdrukken\n" #~ " -e script, --expression=script\n" #~ " het script toevoegen aan de uit te voeren opdrachten\n" #~ " -f scriptbestand, --file=scriptbestand\n" #~ " de inhoud van scriptbestand toevoegen aan de uit te " #~ "voeren opdrachten\n" #~ " -i[achtervoegsel], --in-place[=achtervoegsel]\n" #~ " bestanden ter plekke bewerken (maakt reservekopie als " #~ "achtervoegsel is opgegeven)\n" #~ " -l N, --line-length=N\n" #~ " de gewenste afkaplengte voor regels opgeven voor de `l'-" #~ "opdracht\n" #~ " -r, --regexp-extended\n" #~ " uitgebreide reguliere uitdrukkingen gebruiken in het " #~ "script.\n" #~ "%s -s, --separate\n" #~ " bestanden afzonderlijk beschouwen in plaats van als één " #~ "continue, lange stroom.\n" #~ " -u, --unbuffered\n" #~ " minimale hoeveelheden gegevens van invoerbestanden laden " #~ "en vaker de uitvoerbuffers legen\n" #~ " --help deze hulp weergeven en afsluiten\n" #~ " -V, --version versie-informatie weergeven en afsluiten\n" #~ "\n" #~ "Als geen -e, --expression, -f of --file optie gegeven is, wordt het " #~ "eerste niet-optie\n" #~ "argument gebruikt als sed script om te interpreteren. Alle overblijvende " #~ "argumenten\n" #~ "zijn namen van invoerbestanden; als geen invoerbestanden zijn opgegeven, " #~ "wordt gelezen\n" #~ "vanaf standaard invoer.\n" #~ "\n" kbuild-3686/src/oldsed/po/pt_BR.gmo0000664000175000017500000000767615053010106017114 0ustar locutuslocutus•Þ&L5|P\Qº®%i¦ÀdÝBVmЦ$¾ãõ!*#Imˆ£µÇ ÙæBb#v#š&¾,å+@’V_ éØ I) " L m ‹p ¤  (% ? e8 …# ¾! â   0! @" b … ¥ ­ ¿ Õ è þ)\BŸ'³'Û5=9w© !  & " $ %# -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: sed 4.0.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2002-11-08 17:44-0300 Last-Translator: Aurélio Marinho Jargas Language-Team: Brazilian Portuguese MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n > 1); -R, --regexp-perl usar sintaxe de expressões regulares do Perl 5 no script. %s Este programa é Software Livre. Veja os fontes para conhecer as condições de cópia. NÃO há garantias, nem mesmo para os aspectos mercantis ou de atendimento a finalidades específicas, tanto quanto a lei permita. %s: -e expressão #%lu, caractere %lu: %s %s: não foi possível ler %s: %s %s: arquivo %s linha %lu: %s `:' não recebe endereçosEnvie relatórios de erros (em inglês) para: %s . Inclua a palavra ``%s'' no campo ``Assunto:'' ou ``Subject:''. GNU sed versão %s Retrovisor \n inválidoNome inválido de classe de caracteresCaractere de ordenação inválidoConteúdo inválido no \{\} (permitidos números e vírgula)Expressão regular anterior inválidaFim de intervalo (range) inválidoExpressão regular inválidaFalta de memóriaNada encontradoNão há expressão regular anteriorFim prematuro da expressão regularExpressão regular grande demaisSucessoEscape \ no final( ou \( não terminado) or \) inesperado[ ou [^ não terminado\{ não terminadocomando `e' não suportado`}' não recebe endereçosnão foi possível escrever %d item para %s: %snão foi possível escrever %d items para %s: %serro no subprocessoopções `g' múltiplas para o comando `s'opções `p' múltiplas para o comando `s'opções numéricas múltiplas para o comando `s' (s///n)A opção numérica para o comando `s' não pode ser zero (s///0)opção `e' não suportadaerro de leitura em %s: %ssuper-sed versão %s kbuild-3686/src/oldsed/po/ja.po0000664000175000017500000002711615053010106016323 0ustar locutuslocutus# Japanese messages for GNU sed # Copyright (C) 1999, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. # IIDA Yosiaki , 1999, 2002, 2003, 2004, 2005. # This file is distributed under the same license as the GNU sed package. # Contributed by # Yasuyuki Furukawa , 1999. # and taken over on 1999-09-24 by Japanese Team. # msgid "" msgstr "" "Project-Id-Version: GNU sed 4.1.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2005-02-01 21:02+0900\n" "Last-Translator: IIDA Yosiaki \n" "Language-Team: Japanese \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=EUC-JP\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #: sed/compile.c:162 msgid "multiple `!'s" msgstr "Ê£¿ô¤Î¡Ö!¡×¤Ç¤¹" #: sed/compile.c:163 msgid "unexpected `,'" msgstr "ͽ´ü¤»¤Ì¡Ö,¡×¤Ç¤¹" #: sed/compile.c:164 msgid "invalid usage of +N or ~N as first address" msgstr "ºÇ½é¤Î¥¢¥É¥ì¥¹¤Ø¤Î+N¤ä~N¤Î»ØÄê¤Ï̵¸ú¤Ç¤¹" #: sed/compile.c:165 msgid "unmatched `{'" msgstr "Äà¤ê¹ç¤ï¤Ê¤¤¡Ö{¡×¤Ç¤¹" #: sed/compile.c:166 msgid "unexpected `}'" msgstr "ͽ´ü¤»¤Ì¡Ö}¡×¤Ç¤¹" #: sed/compile.c:167 msgid "extra characters after command" msgstr "¥³¥Þ¥ó¥É¤Î¸å¤í¤Ë;·×¤Êʸ»ú¤¬¤¢¤ê¤Þ¤¹" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "\\¤¬¡Öa¡×¡Öc¡×¡Öi¡×¤Î¸å¤Ëͽ´ü¤µ¤ì¤Þ¤¹" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "¡Ö}¡×¤Ë¥¢¥É¥ì¥¹¤ÏÉÔÍפǤ¹" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ":¤Ë¥¢¥É¥ì¥¹¤ÏÉÔÍפǤ¹" #: sed/compile.c:171 msgid "comments don't accept any addresses" msgstr "¥³¥á¥ó¥È¤Ï¥¢¥É¥ì¥¹¤ò¼õ¤±ÉÕ¤±¤Þ¤»¤ó" #: sed/compile.c:172 msgid "missing command" msgstr "¥³¥Þ¥ó¥É¤¬Â­¤ê¤Þ¤»¤ó" #: sed/compile.c:173 msgid "command only uses one address" msgstr "¥³¥Þ¥ó¥É¤Ï¥¢¥É¥ì¥¹¤ò1¤Ä¤À¤±»È¤¤¤Þ¤¹" #: sed/compile.c:174 msgid "unterminated address regex" msgstr "¥¢¥É¥ì¥¹regex¤¬½ªÎ»¤·¤Æ¤¤¤Þ¤»¤ó" #: sed/compile.c:175 msgid "unterminated `s' command" msgstr "¡Ös¡×¥³¥Þ¥ó¥É¤¬½ªÎ»¤·¤Æ¤¤¤Þ¤»¤ó" #: sed/compile.c:176 msgid "unterminated `y' command" msgstr "¡Öy¡×¥³¥Þ¥ó¥É¤¬½ªÎ»¤·¤Æ¤¤¤Þ¤»¤ó" #: sed/compile.c:177 msgid "unknown option to `s'" msgstr "¡Ös¡×¤Ø¤Î¥ª¥×¥·¥ç¥ó¤¬Ì¤ÃΤǤ¹" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "¡Ös¡×¥³¥Þ¥ó¥É¤ËÊ£¿ô¤Î¡Öp¡×¥ª¥×¥·¥ç¥ó" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "¡Ös¡×¥³¥Þ¥ó¥É¤ËÊ£¿ô¤Î¡Ög¡×¥ª¥×¥·¥ç¥ó" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "¡Ös¡×¥³¥Þ¥ó¥É¤ËÊ£¿ô¤Î¿ôÃÍ¥ª¥×¥·¥ç¥ó" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "¡Ös¡×¥³¥Þ¥ó¥É¤Ø¤Î¿ôÃÍ¥ª¥×¥·¥ç¥ó¤ÏÎí¤Ç¤Ï¤¤¤±¤Þ¤»¤ó" #: sed/compile.c:182 msgid "strings for `y' command are different lengths" msgstr "¡Öy¡×¥³¥Þ¥ó¥É¤Ø¤Îʸ»úÎó¤ÎŤµ¤¬¡¢°ã¤¤¤Þ¤¹" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "¶èÀÚ¤êʸ»ú¤¬¡¢Ã±°ì¥Ð¥¤¥Èʸ»ú¤Ç¤¢¤ê¤Þ¤»¤ó" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "sed¤Î¿·ÈǤ¬Á°Äó¤Ç¤¹" #: sed/compile.c:185 msgid "invalid usage of line address 0" msgstr "̵¸ú¤Ê¹Ô¥¢¥É¥ì¥¹0¤Î»ÈÍÑË¡" #: sed/compile.c:186 #, c-format msgid "unknown command: `%c'" msgstr "̤ÃΤΥ³¥Þ¥ó¥É¤Ç¤¹: ¡Ö%c¡×" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: ¥Õ¥¡¥¤¥ë %s %lu¹Ô: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e ɽ¸½ #%lu, ʸ»ú¿ô %lu: %s\n" #: sed/compile.c:1644 #, c-format msgid "can't find label for jump to `%s'" msgstr "¡Ö%s¡×¤Ø¤Î¥¸¥ã¥ó¥×¤Î¥é¥Ù¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: %s¤òÆÉ¤ß¹þ¤á¤Þ¤»¤ó: %s\n" #: sed/execute.c:673 #, c-format msgid "couldn't edit %s: is a terminal" msgstr "%s¤Ï¡¢ÊÔ½¸¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿: üËö¤Ç¤¹" #: sed/execute.c:677 #, c-format msgid "couldn't edit %s: not a regular file" msgstr "%s¤Ï¡¢ÊÔ½¸¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿: Ä̾ï¥Õ¥¡¥¤¥ë¤Ç¤¢¤ê¤Þ¤»¤ó" #: sed/execute.c:684 lib/utils.c:196 #, c-format msgid "couldn't open temporary file %s: %s" msgstr "°ì»þ¥Õ¥¡¥¤¥ë¤ò³«¤±¤Þ¤»¤ó¤Ç¤·¤¿: %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "»Ò¥×¥í¥»¥¹¤Î¥¨¥é¡¼" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "¡Öe¡×¥ª¥×¥·¥ç¥ó¤Ï¡¢¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "¡Öe¡×¥³¥Þ¥ó¥É¤Ï¡¢¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "ľÁ°¤ÎÀµµ¬É½¸½¤¬¡¢¤¢¤ê¤Þ¤»¤ó" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "½¤¾þ»Ò¤Ï¡¢¶õ¤ÎÀµµ¬É½¸½¤Ë»ØÄê¤Ç¤­¤Þ¤»¤ó" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "¡Ös¡×¥³¥Þ¥ó¥É¤Î±¦Â¦¤Ë̵¸ú¤Ê\\%d¤Î»²¾È" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " ¥¹¥¯¥ê¥×¥È¤ÇPerl 5¤ÎÀµµ¬É½¸½¹½Ê¸¤ò»È¤¦¡£\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" "»ÈÍÑË¡: %s [¥ª¥×¥·¥ç¥ó]... {¥¹¥¯¥ê¥×¥È(¾¤Ë¤Ê¤±¤ì¤Ð)} [ÆþÎÏ¥Õ¥¡¥¤¥ë]...\n" "\n" #: sed/sed.c:102 #, fuzzy, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" "-n, --quiet, --silent\n" " ¥Ñ¥¿¡¼¥ó¡¦¥¹¥Ú¡¼¥¹¤Î¼«Æ°½ÐÎϤòÍÞÀ©\n" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" " -e ¥¹¥¯¥ê¥×¥È, --expression=¥¹¥¯¥ê¥×¥È\n" " ¼Â¹Ô¤¹¤ë¥³¥Þ¥ó¥É¤È¤·¤Æ¥¹¥¯¥ê¥×¥È¤òÄɲÃ\n" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" " -f ¥¹¥¯¥ê¥×¥È¡¦¥Õ¥¡¥¤¥ë, --file=¥¹¥¯¥ê¥×¥È¡¦¥Õ¥¡¥¤¥ë\n" " ¼Â¹Ô¤¹¤ë¥³¥Þ¥ó¥É¤È¤·¤Æ¥¹¥¯¥ê¥×¥È¡¦¥Õ¥¡¥¤¥ë¤ÎÆâÍÆ¤òÄɲÃ\n" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" " -i[ÀÜÈø¼­], --in-place[=ÀÜÈø¼­]\n" " ¥Õ¥¡¥¤¥ë¤ò¤½¤Î¾ì¤ÇÊÔ½¸ (³ÈÄ¥»Ò¤¬¤¢¤ì¤Ð¡¢¥Ð¥Ã¥¯¥¢¥Ã¥×¤òºî" "À®)\n" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" " -l N, --line-length=N\n" " ¡Öl¡×¥³¥Þ¥ó¥ÉÍѤιÔÀÞÊÖ¤·Ä¹¤ò»ØÄê\n" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" " --posix\n" " GNU³ÈÄ¥¤òÁ´Éô¶Ø»ß¡£\n" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -r, --regexp-extended\n" " ¥¹¥¯¥ê¥×¥È¤Ç³ÈÄ¥Àµµ¬É½¸½¤ò»ÈÍÑ¡£\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" " -s, --separate\n" " ¥Õ¥¡¥¤¥ë¤ò°ìÏ¢¤ÎÆþÎϤˤ»¤º¡¢ÊÌ¡¹¤Ë½èÍý¡£\n" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" " -u, --unbuffered\n" " ÆþÎÏ¥Õ¥¡¥¤¥ë¤«¤é¶Ë¾®¤Î¥Ç¡¼¥¿¤ò¼è¤ê¹þ¤ß¡¢\n" " ¤Á¤ç¤¯¤Á¤ç¤¯½ÐÎϥХåե¡¡¼¤ËÁݽФ·\n" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr " --help ¤³¤ÎÀâÌÀ¤òɽ¼¨¤·¤Æ½ªÎ»\n" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr " --version ¥Ð¡¼¥¸¥ç¥ó¾ðÊó¤òɽ¼¨¤·¤Æ½ªÎ»\n" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" "\n" "-e¡¢--expression¡¢-f¡¢--file¥ª¥×¥·¥ç¥ó¤Î¤É¤ì¤â¤Ê¤¤¤È¡¢¥ª¥×¥·¥ç¥ó°Ê³°¤Î\n" "ºÇ½é¤Î°ú¿ô¤òsed¥¹¥¯¥ê¥×¥È¤È¤·¤Æ²ò¼á¤·¤Þ¤¹¡£»Ä¤ê¤Î°ú¿ô¤ÏÁ´Éô¡¢ÆþÎÏ¥Õ¥¡\n" "¥¤¥ë̾¤È¤Ê¤ê¤Þ¤¹¡£ÆþÎÏ¥Õ¥¡¥¤¥ë¤Î»ØÄ꤬¤Ê¤¤¤È¡¢É¸½àÆþÎϤòÆÉ¤ß¹þ¤ß¤Þ¤¹¡£\n" "\n" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "ÅŻҥ᡼¥ë¤Ë¤è¤ë¥Ð¥°Êó¹ð¤Î°¸Àè: %s\n" "Êó¹ð¤ÎºÝ¡¢¡ÈSubject:¡É¥Õ¥£¡¼¥ë¥É¤Î¤É¤³¤«¤Ë¡È%s¡É¤òÆþ¤ì¤Æ¤¯¤À¤µ¤¤¡£\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed %sÈÇ\n" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "¸¶ºîGNU sed %sÈÇ\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "" "GNU sed %sÈÇ\n" "\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" "\n" "ÌõÃí: Èó¾ï¤Ë½ÅÍפÊʸ¾Ï¤Î¤¿¤á¡¢¸¶Ê¸¤ò»Ä¤·¤Æ¤¤¤Þ¤¹¡£\n" " -- »²¹ÍÌõ\n" "¤³¤ì¤Ï¥Õ¥ê¡¼¡¦¥½¥Õ¥È¥¦¥§¥¢¤Ç¤¹¡£Ê£À½¤Î¾ò·ï¤Ë´Ø¤·¤Æ¤Ï¡¢¥½¡¼¥¹¤ò¤´Í÷¤¯¤À¤µ\n" "¤¤¡£ÊݾڤϰìÀÚ¤¢¤ê¤Þ¤»¤ó¡£±ÄÍøÌÜŪ¤äË¡¤ÇÄê¤á¤é¤ì¤¿ÈÏ°Ï¤Ç¤ÎÆÃÄêÌÜŪ¤Î¤¿¤á\n" "¤ÎŬ¹çÀ­¤â¤¢¤ê¤Þ¤»¤ó¡£\n" #: lib/utils.c:98 lib/utils.c:336 #, c-format msgid "cannot remove %s: %s" msgstr "%s¤òºï½ü¤Ç¤­¤Þ¤»¤ó: %s" #: lib/utils.c:143 #, c-format msgid "couldn't open file %s: %s" msgstr "¥Õ¥¡¥¤¥ë%s¤ò³«¤±¤Þ¤»¤ó¤Ç¤·¤¿: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "%d¸Ä¤Î¥¢¥¤¥Æ¥à¤ò%s¤Ø½ñ¤­¹þ¤á¤Þ¤»¤ó¤Ç¤·¤¿: %s" msgstr[1] "%d¸Ä¤Î¥¢¥¤¥Æ¥à¤ò%s¤Ø½ñ¤­¹þ¤á¤Þ¤»¤ó¤Ç¤·¤¿: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "%s¤ÎÆÉ¹þ¤ß¥¨¥é¡¼: %s" #: lib/utils.c:341 #, c-format msgid "cannot rename %s: %s" msgstr "%s¤Î̾Á°¤òÊѹ¹¤Ç¤­¤Þ¤»¤ó: %s" #: lib/regcomp.c:132 msgid "Success" msgstr "À®¸ù" #: lib/regcomp.c:135 msgid "No match" msgstr "¾È¹ç¤·¤Þ¤»¤ó" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "̵¸ú¤ÊÀµµ¬É½¸½" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "̵¸ú¤Ê¹»¹çʸ»ú" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "̵¸ú¤Êʸ»ú¥¯¥é¥¹Ì¾" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "¸å³¤ÎµÕ¥¹¥é¥Ã¥·¥å" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "̵¸ú¤ÊµÕ»²¾È" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "[¤ä[^¤¬Äà¹ç¤¤¤Þ¤»¤ó" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "(¤ä\\(¤¬Äà¹ç¤¤¤Þ¤»¤ó" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "\\{¤¬Äà¹ç¤¤¤Þ¤»¤ó" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "̵¸ú¤Ê\\{\\}¤ÎÆâÍÆ\"" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "̵¸ú¤ÊÈϰϤνªÃ¼" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "¥á¥â¥ê¡¼¤¬Â­¤ê¤Þ¤»¤ó" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "̵¸ú¤ÊÀè¹ÔÀµµ¬É½¸½" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Áá²á¤®¤ëÀµµ¬É½¸½½ªÃ¼" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Â礭²á¤®¤ëÀµµ¬É½¸½" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "Äà¤ê¹ç¤ï¤Ê¤¤)¤ä\\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "ľÁ°¤ÎÀµµ¬É½¸½¤¬¡¢¤¢¤ê¤Þ¤»¤ó" kbuild-3686/src/oldsed/po/af.gmo0000664000175000017500000000740215053010106016457 0ustar locutuslocutus•Þ'T5Œ`\aº¾%yŸ¶ÐdíRf}š¶$Îó 1:#Y}˜ ³Å× éöB/r†#¤#È&ì,@Yn\„R á¿ 4* ô  < V` n Ï ä ý  3 O f }  © ¿ Ù è ï   ' :& H oH ‰ Ò ä)),+V3‚!¶Øë!"  ' # % &$ -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessexpected newer version of sedmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: sed 4.0.9 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2004-01-11 21:06+0000 Last-Translator: Ysbeer Language-Team: Afrikaans MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n!=1; -R, --regexp-perl gebruik Perl 5 se regexsintaks in die skrip. %s Hierdie is vrye sagteware; raadpleeg die bronkode vir kopiëringsinligting. Daar is GEEN waarborg nie; nie eens vir BRUIKBAARHEID of GESKIKHEID VIR 'n SPESIFIEK DOEL, binne regsperke nie. %s: -e uitdrukking #%lu, karakter %lu: %s %s: Kan nie %s lees nie: %s %s: lêer %s lyn %lu: %s : soek nie 'n adres nieRapporteer foute per e-pos aan: %s . Sluit asb. die woord ``%s'' êrens in die onderwerplyn in. GNU sed weergawe %s Ongeldige terugverwysingOngeldige karakterklasnaamOngeldige kollasiekarakterOngeldige inhoud binne \{\}Ongeldige vorige regexOngeldige bereikseindeOngeldige regexGeheue uitgeputGeen paringGeen vorige regex niePremature einde vir regexRegex te grootSuksesSleep terugstreepOngepaarde ( or \(Ongepaarde ) of \)Ongepaarde [ of [^Ongepaarde \{`e' instruksie word nie ondersteun nie`}' soek nie 'n adres niekon nie %d item na %s skryf nie: %skon nie %d items na %s skryf nie: %sfout in subproseshet nuwer sed-weergawe verwagmeervoudige `g' opsies vir `s' instruksiemeervoudige `p' opsies vir `s' instruksiemeervoudige nommeropsies vir `s' instruksienommeropsie vir `s' instruksie mag nie nul wees nieopsie `e' word nie ondersteun nieleesfout op %s: %ssuper-sed weergawe %s kbuild-3686/src/oldsed/po/gl.gmo0000664000175000017500000000773115053010106016500 0ustar locutuslocutus•Þ&L5|P\Qº®%i¦ÀdÝBVmЦ$¾ãõ!*#Imˆ£µÇ ÙæBb#v#š&¾,å+@Va Ö¹ 8( ò  8 V³ o #" 7& Z!  £% ¾ ä ü  *' 8" ` ƒ ¤ ª È Ü ð 4[O«,¾,ë2=K‰©Ã !  & " $ %# -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: sed 4.0 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2002-10-25 15:57+0200 Last-Translator: Jacobo Tarrío Barreiro Language-Team: Galician MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n!=1; -R, --regexp-perl usa-la sintaxe de expresións regulares de Perl 5 no script. %s Isto é software libre; vexa o código fonte polas condicións de copia. NON hai garantía; nin sequera de COMERCIABILIDADE ou APTITUDE PARA UN FIN DETERMINADO, ata o que permite a lei. %s: -e expresión #%lu, carácter %lu: %s %s: non se puido ler %s: %s %s: ficheiro %s liña %lu: %s : non acepta un enderezoInforme dos erros no programa a %s . Informe dos erros na traducción a gpul-traduccion@ceu.fi.udc.es . Asegúrese de incluí-la palabra ``%s'' nalgunha parte do campo ``Subject:''. GNU sed versión %s Referencia cara a atrás non válidaNome de clase de caracteres non válidoCarácter de ordeamento non válidoContido de \{\} non válidoExpresión regular anterior non válidaFin de rango non válidaExpresión regular non válidaMemoria esgotadaNon se atopouNon hai unha expresión regular anteriorFin prematura da expresión regularExpresión regular grande de máisÉxitoBarra invertida á fin de liña( ou \( sen parella) ou \) sen parella[ ou [^ sen parella\{ sen parellao comando `e' non está soportado`}' non acepta un enderezonon se puido escribir %d elemento en %s: %snon se puideron escribir %d elementos en %s: %serro no subprocesomúltiples opcións `g' para a instrucción `s'múltiples opcións `p' para a instrucción `s'múltiples opcións numéricas para a instrucción `s'unha opción numérica para a instrucción `s' non pode ser ceroa opción `e' non está soportadaerro de lectura en %s: %ssuper-sed versión %s kbuild-3686/src/oldsed/po/et.po0000664000175000017500000002604215053010106016336 0ustar locutuslocutus# Estonian translations for GNU sed. # Copyright (C) 2001 Free Software Foundation, Inc. # Toomas Soome , 2004. # msgid "" msgstr "" "Project-Id-Version: sed 4.1.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2004-07-09 16:33+0300\n" "Last-Translator: Toomas Soome \n" "Language-Team: Estonian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-15\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: sed/compile.c:162 msgid "multiple `!'s" msgstr "korduv `!'" #: sed/compile.c:163 msgid "unexpected `,'" msgstr "ootamatu `,'" #: sed/compile.c:164 msgid "invalid usage of +N or ~N as first address" msgstr "+N või ~N ei või kasutada esimese aadressina" #: sed/compile.c:165 msgid "unmatched `{'" msgstr "liigne `{'" #: sed/compile.c:166 msgid "unexpected `}'" msgstr "ootamatu `}'" #: sed/compile.c:167 msgid "extra characters after command" msgstr "lisasümbolid peale käsku" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "peale `a', `c' või `i' peab olema \\" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' ei vaja aadresse" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": ei vaja aadresse" #: sed/compile.c:171 msgid "comments don't accept any addresses" msgstr "kommentaarid ei vaja aadresse" #: sed/compile.c:172 msgid "missing command" msgstr "käsk puudub" #: sed/compile.c:173 msgid "command only uses one address" msgstr "käsk kasutab vaid üht aadressi" #: sed/compile.c:174 msgid "unterminated address regex" msgstr "lõpetamata aadressi avaldis" #: sed/compile.c:175 msgid "unterminated `s' command" msgstr "lõpetamata `s' käsk" #: sed/compile.c:176 msgid "unterminated `y' command" msgstr "lõpetamata `y' käsk" #: sed/compile.c:177 msgid "unknown option to `s'" msgstr "tundmatu võti `s' käsule" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "korduv `p' võti `s' käsus" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "korduv `g' võti `s' käsus" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "korduvad numbrivõtmed `s' käsus" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "numbrivõti `s' käsus ei või olla null" #: sed/compile.c:182 msgid "strings for `y' command are different lengths" msgstr "sõned käsus `y' on erineva pikkusega" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "eraldav sübol ei ole ühe-baidiline sümbol" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "oodati sedi uuemat versiooni" #: sed/compile.c:185 msgid "invalid usage of line address 0" msgstr "vigane rea aadressi 0 kasutamine" #: sed/compile.c:186 #, c-format msgid "unknown command: `%c'" msgstr "tundmatu käsk: `%c'" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: fail %s rida %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e avaldis #%lu, sümbol %lu: %s\n" #: sed/compile.c:1644 #, c-format msgid "can't find label for jump to `%s'" msgstr "ei leia märgendit, et hüpata kohale `%s'" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: ei saa lugeda %s: %s\n" #: sed/execute.c:673 #, c-format msgid "couldn't edit %s: is a terminal" msgstr "%s ei saa toimetada: see on terminal" #: sed/execute.c:677 #, c-format msgid "couldn't edit %s: not a regular file" msgstr "%s ei saa toimetada: see ei ole tavaline fail" #: sed/execute.c:684 lib/utils.c:196 #, c-format msgid "couldn't open temporary file %s: %s" msgstr "ajutist faili %s ei saa avada: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "viga alamprotsessis" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "võtit `e' ei toetata" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "käsku `e' ei toetata" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "eelmist regulaaravaldist pole" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "muudatusi tühjale regulaaravaldisele ei saa määrata" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "vigane viide \\%d käsu `s' paremas pooles" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " kasuta skriptis Perl 5 regulaaravaldiste süntaksit.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" "Kasutamine: %s [võti]... {ainult-skript-kui-teisi-skripte-pole} [sisend-" "fail]...\n" "\n" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" " -n, --quiet, --silent\n" " keela mustriruumi automaatne väljastamine\n" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" " -e skript, --expression=skript\n" " lisa täidetavate käskluste skript\n" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" " -f skripti-fail, --file=skripti-fail\n" " lisa skripti-faili sisu täidetavate käskluste hulka\n" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" " -i[SUFIKS], --in-place[=SUFIKS]\n" " toimeta faile (kui kasutati sifiksit, loob ka varukoopia)\n" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" " -l N, --line-length=N\n" " määra `l' käsule soovitatav rea pikkus\n" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" " --posix\n" " blokeeri kõik GNU laiendused.\n" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -r, --regexp-extended\n" " kasuta skriptis laiendatud regulaaravaldiste süntaksit.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" " -s, --separate\n" " käsitle faile ükshaaval, mitte ühe jätkuva voona.\n" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" " -u, --unbuffered\n" " loe sisendfailist minimaalne kogus andmeid ja tühjenda\n" " väljundpuhvreid sagedamini\n" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr " --help väljast see abiinfo ja lõpeta töö\n" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr " --version väljasta versiooniinfo ja lõpeta töö\n" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" "\n" "Kui võtmeid -e, --expression, -f või --file ei kasutata, loetakse\n" "esimene argument, mis pole võti, sed skriptiks. Kõik järgnevad argumendid " "on\n" "sisendfailide nimed; kui sisendfaile ei antud, loetakse standardsisendit.\n" "\n" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Postitage teated vigadest: %s .\n" "Lisage kindlasti sõna ``%s'' ``Subject:'' reale.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed versioon %s\n" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "põhineb GNU sed versioonil %s\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed versioon %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "See on vaba tarkvara; kopeerimistingimused leiate lähtetekstidest. Garantii\n" "PUUDUB; ka müügiks või mingil eesmärgil kasutamiseks, vastavalt seadustega\n" "lubatud piiridele.\n" #: lib/utils.c:98 lib/utils.c:336 #, c-format msgid "cannot remove %s: %s" msgstr "%s ei saa eemaldada: %s" #: lib/utils.c:143 #, c-format msgid "couldn't open file %s: %s" msgstr "faili %s ei saa avada: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "%d elemendi faili %s kirjutamine ebaõnnestus: %s" msgstr[1] "%d elemendi faili %s kirjutamine ebaõnnestus: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "lugemisviga %s: %s" #: lib/utils.c:341 #, c-format msgid "cannot rename %s: %s" msgstr "%s ei saa ümber nimetada: %s" #: lib/regcomp.c:132 msgid "Success" msgstr "Edukas" #: lib/regcomp.c:135 msgid "No match" msgstr "Ei leia" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Vigane regulaaravaldis" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Vigane sortimise sümbol" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Vigane sümbolite klassi nimi" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Lõpetav langkriips" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Vigane tagasi viide" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "Puudub [ või [^" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "Puudub ( või \\(" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "Puudub \\{" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Vigane \\{\\} sisu" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Vigane vahemiku lõpp" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Mälu on otsas" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Vigane eelnev regulaaravaldis" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Ootamatu regulaaravaldise lõpp" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Regulaaravaldis on liiga suur" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "Puudub ) või \\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Eelmist regulaaravaldist pole" kbuild-3686/src/oldsed/po/ja.gmo0000664000175000017500000002155315053010106016466 0ustar locutuslocutus•ÞPœkÈúÉ,Ä5ñ7'\_`¼u l “b Y c~ ½ <º Ì% ‡ ­ Ä Þd û ` t ‹ ¨ Ä$ Ü.?H#g‹¦®ÁÓå ÷HMg†!¤ÆÛ(ð#7[${ #ºBÞ2!T h‰§*Æ*ñ< L#Z#~&¢É,è.-Cq‡–¥» Ñßøz,Ö§(~.§/ÖNaU·o7K§JóK>Š£ !°Òî f† •¢µÄÖéú +H]puˆœ®ÂIÓ'E_*r´&Ñ#ø"$?4d ™&ºYá( ; d$ w œ$ °$ Õ( ú!#!=!R$!b$!‡#!¬!Ð1!í)""I)"^"ˆ"˜"ª"¼"×"õ# #+#KB(4  M 68OI,=1:AF'2</ !5+)$7%&->3DL E09P*C?NK.;G"J#@H If no -e, --expression, -f, or --file option is given, then the first non-option argument is taken as the sed script to interpret. All remaining arguments are names of input files; if no input files are specified, then the standard input is read. --help display this help and exit --version output version information and exit --posix disable all GNU extensions. -R, --regexp-perl use Perl 5's regular expressions syntax in the script. -e script, --expression=script add the script to the commands to be executed -f script-file, --file=script-file add the contents of script-file to the commands to be executed -i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if extension supplied) -l N, --line-length=N specify the desired line-wrap length for the `l' command -r, --regexp-extended use extended regular expressions in the script. -s, --separate consider files as separate rather than as a single continuous long stream. -u, --unbuffered load minimal amounts of data from the input files and flush the output buffers more often %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]... `e' command not supported`}' doesn't want any addressesbased on GNU sed version %s can't find label for jump to `%s'cannot remove %s: %scannot rename %s: %scannot specify modifiers on empty regexpcommand only uses one addresscomments don't accept any addressescouldn't edit %s: is a terminalcouldn't edit %s: not a regular filecouldn't open file %s: %scouldn't open temporary file %s: %scouldn't write %d item to %s: %scouldn't write %d items to %s: %sdelimiter character is not a single-byte charactererror in subprocessexpected \ after `a', `c' or `i'expected newer version of sedextra characters after commandinvalid reference \%d on `s' command's RHSinvalid usage of +N or ~N as first addressinvalid usage of line address 0missing commandmultiple `!'smultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandno previous regular expressionnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %sstrings for `y' command are different lengthssuper-sed version %s unexpected `,'unexpected `}'unknown command: `%c'unknown option to `s'unmatched `{'unterminated `s' commandunterminated `y' commandunterminated address regexProject-Id-Version: GNU sed 4.1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2005-02-01 21:02+0900 Last-Translator: IIDA Yosiaki Language-Team: Japanese MIME-Version: 1.0 Content-Type: text/plain; charset=EUC-JP Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; -e¡¢--expression¡¢-f¡¢--file¥ª¥×¥·¥ç¥ó¤Î¤É¤ì¤â¤Ê¤¤¤È¡¢¥ª¥×¥·¥ç¥ó°Ê³°¤Î ºÇ½é¤Î°ú¿ô¤òsed¥¹¥¯¥ê¥×¥È¤È¤·¤Æ²ò¼á¤·¤Þ¤¹¡£»Ä¤ê¤Î°ú¿ô¤ÏÁ´Éô¡¢ÆþÎÏ¥Õ¥¡ ¥¤¥ë̾¤È¤Ê¤ê¤Þ¤¹¡£ÆþÎÏ¥Õ¥¡¥¤¥ë¤Î»ØÄ꤬¤Ê¤¤¤È¡¢É¸½àÆþÎϤòÆÉ¤ß¹þ¤ß¤Þ¤¹¡£ --help ¤³¤ÎÀâÌÀ¤òɽ¼¨¤·¤Æ½ªÎ» --version ¥Ð¡¼¥¸¥ç¥ó¾ðÊó¤òɽ¼¨¤·¤Æ½ªÎ» --posix GNU³ÈÄ¥¤òÁ´Éô¶Ø»ß¡£ -R, --regexp-perl ¥¹¥¯¥ê¥×¥È¤ÇPerl 5¤ÎÀµµ¬É½¸½¹½Ê¸¤ò»È¤¦¡£ -e ¥¹¥¯¥ê¥×¥È, --expression=¥¹¥¯¥ê¥×¥È ¼Â¹Ô¤¹¤ë¥³¥Þ¥ó¥É¤È¤·¤Æ¥¹¥¯¥ê¥×¥È¤òÄɲà -f ¥¹¥¯¥ê¥×¥È¡¦¥Õ¥¡¥¤¥ë, --file=¥¹¥¯¥ê¥×¥È¡¦¥Õ¥¡¥¤¥ë ¼Â¹Ô¤¹¤ë¥³¥Þ¥ó¥É¤È¤·¤Æ¥¹¥¯¥ê¥×¥È¡¦¥Õ¥¡¥¤¥ë¤ÎÆâÍÆ¤òÄɲà -i[ÀÜÈø¼­], --in-place[=ÀÜÈø¼­] ¥Õ¥¡¥¤¥ë¤ò¤½¤Î¾ì¤ÇÊÔ½¸ (³ÈÄ¥»Ò¤¬¤¢¤ì¤Ð¡¢¥Ð¥Ã¥¯¥¢¥Ã¥×¤òºîÀ®) -l N, --line-length=N ¡Öl¡×¥³¥Þ¥ó¥ÉÍѤιÔÀÞÊÖ¤·Ä¹¤ò»ØÄê -r, --regexp-extended ¥¹¥¯¥ê¥×¥È¤Ç³ÈÄ¥Àµµ¬É½¸½¤ò»ÈÍÑ¡£ -s, --separate ¥Õ¥¡¥¤¥ë¤ò°ìÏ¢¤ÎÆþÎϤˤ»¤º¡¢ÊÌ¡¹¤Ë½èÍý¡£ -u, --unbuffered ÆþÎÏ¥Õ¥¡¥¤¥ë¤«¤é¶Ë¾®¤Î¥Ç¡¼¥¿¤ò¼è¤ê¹þ¤ß¡¢ ¤Á¤ç¤¯¤Á¤ç¤¯½ÐÎϥХåե¡¡¼¤ËÁݽФ· %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. ÌõÃí: Èó¾ï¤Ë½ÅÍפÊʸ¾Ï¤Î¤¿¤á¡¢¸¶Ê¸¤ò»Ä¤·¤Æ¤¤¤Þ¤¹¡£ -- »²¹ÍÌõ ¤³¤ì¤Ï¥Õ¥ê¡¼¡¦¥½¥Õ¥È¥¦¥§¥¢¤Ç¤¹¡£Ê£À½¤Î¾ò·ï¤Ë´Ø¤·¤Æ¤Ï¡¢¥½¡¼¥¹¤ò¤´Í÷¤¯¤À¤µ ¤¤¡£ÊݾڤϰìÀÚ¤¢¤ê¤Þ¤»¤ó¡£±ÄÍøÌÜŪ¤äË¡¤ÇÄê¤á¤é¤ì¤¿ÈÏ°Ï¤Ç¤ÎÆÃÄêÌÜŪ¤Î¤¿¤á ¤ÎŬ¹çÀ­¤â¤¢¤ê¤Þ¤»¤ó¡£ %s: -e ɽ¸½ #%lu, ʸ»ú¿ô %lu: %s %s: %s¤òÆÉ¤ß¹þ¤á¤Þ¤»¤ó: %s %s: ¥Õ¥¡¥¤¥ë %s %lu¹Ô: %s :¤Ë¥¢¥É¥ì¥¹¤ÏÉÔÍפǤ¹ÅŻҥ᡼¥ë¤Ë¤è¤ë¥Ð¥°Êó¹ð¤Î°¸Àè: %s Êó¹ð¤ÎºÝ¡¢¡ÈSubject:¡É¥Õ¥£¡¼¥ë¥É¤Î¤É¤³¤«¤Ë¡È%s¡É¤òÆþ¤ì¤Æ¤¯¤À¤µ¤¤¡£ GNU sed %sÈÇ Ìµ¸ú¤ÊµÕ»²¾È̵¸ú¤Êʸ»ú¥¯¥é¥¹Ì¾Ìµ¸ú¤Ê¹»¹çʸ»ú̵¸ú¤Ê\{\}¤ÎÆâÍÆ"̵¸ú¤ÊÀè¹ÔÀµµ¬É½¸½Ìµ¸ú¤ÊÈϰϤνªÃ¼Ìµ¸ú¤ÊÀµµ¬É½¸½¥á¥â¥ê¡¼¤¬Â­¤ê¤Þ¤»¤ó¾È¹ç¤·¤Þ¤»¤óľÁ°¤ÎÀµµ¬É½¸½¤¬¡¢¤¢¤ê¤Þ¤»¤óÁá²á¤®¤ëÀµµ¬É½¸½½ªÃ¼Â礭²á¤®¤ëÀµµ¬É½¸½À®¸ù¸å³¤ÎµÕ¥¹¥é¥Ã¥·¥å(¤ä\(¤¬Äà¹ç¤¤¤Þ¤»¤óÄà¤ê¹ç¤ï¤Ê¤¤)¤ä\)[¤ä[^¤¬Äà¹ç¤¤¤Þ¤»¤ó\{¤¬Äà¹ç¤¤¤Þ¤»¤ó»ÈÍÑË¡: %s [¥ª¥×¥·¥ç¥ó]... {¥¹¥¯¥ê¥×¥È(¾¤Ë¤Ê¤±¤ì¤Ð)} [ÆþÎÏ¥Õ¥¡¥¤¥ë]... ¡Öe¡×¥³¥Þ¥ó¥É¤Ï¡¢¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó¡Ö}¡×¤Ë¥¢¥É¥ì¥¹¤ÏÉÔÍפǤ¹¸¶ºîGNU sed %sÈÇ ¡Ö%s¡×¤Ø¤Î¥¸¥ã¥ó¥×¤Î¥é¥Ù¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó%s¤òºï½ü¤Ç¤­¤Þ¤»¤ó: %s%s¤Î̾Á°¤òÊѹ¹¤Ç¤­¤Þ¤»¤ó: %s½¤¾þ»Ò¤Ï¡¢¶õ¤ÎÀµµ¬É½¸½¤Ë»ØÄê¤Ç¤­¤Þ¤»¤ó¥³¥Þ¥ó¥É¤Ï¥¢¥É¥ì¥¹¤ò1¤Ä¤À¤±»È¤¤¤Þ¤¹¥³¥á¥ó¥È¤Ï¥¢¥É¥ì¥¹¤ò¼õ¤±ÉÕ¤±¤Þ¤»¤ó%s¤Ï¡¢ÊÔ½¸¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿: üËö¤Ç¤¹%s¤Ï¡¢ÊÔ½¸¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿: Ä̾ï¥Õ¥¡¥¤¥ë¤Ç¤¢¤ê¤Þ¤»¤ó¥Õ¥¡¥¤¥ë%s¤ò³«¤±¤Þ¤»¤ó¤Ç¤·¤¿: %s°ì»þ¥Õ¥¡¥¤¥ë¤ò³«¤±¤Þ¤»¤ó¤Ç¤·¤¿: %s: %s%d¸Ä¤Î¥¢¥¤¥Æ¥à¤ò%s¤Ø½ñ¤­¹þ¤á¤Þ¤»¤ó¤Ç¤·¤¿: %s%d¸Ä¤Î¥¢¥¤¥Æ¥à¤ò%s¤Ø½ñ¤­¹þ¤á¤Þ¤»¤ó¤Ç¤·¤¿: %s¶èÀÚ¤êʸ»ú¤¬¡¢Ã±°ì¥Ð¥¤¥Èʸ»ú¤Ç¤¢¤ê¤Þ¤»¤ó»Ò¥×¥í¥»¥¹¤Î¥¨¥é¡¼\¤¬¡Öa¡×¡Öc¡×¡Öi¡×¤Î¸å¤Ëͽ´ü¤µ¤ì¤Þ¤¹sed¤Î¿·ÈǤ¬Á°Äó¤Ç¤¹¥³¥Þ¥ó¥É¤Î¸å¤í¤Ë;·×¤Êʸ»ú¤¬¤¢¤ê¤Þ¤¹¡Ös¡×¥³¥Þ¥ó¥É¤Î±¦Â¦¤Ë̵¸ú¤Ê\%d¤Î»²¾ÈºÇ½é¤Î¥¢¥É¥ì¥¹¤Ø¤Î+N¤ä~N¤Î»ØÄê¤Ï̵¸ú¤Ç¤¹Ìµ¸ú¤Ê¹Ô¥¢¥É¥ì¥¹0¤Î»ÈÍÑË¡¥³¥Þ¥ó¥É¤¬Â­¤ê¤Þ¤»¤óÊ£¿ô¤Î¡Ö!¡×¤Ç¤¹¡Ös¡×¥³¥Þ¥ó¥É¤ËÊ£¿ô¤Î¡Ög¡×¥ª¥×¥·¥ç¥ó¡Ös¡×¥³¥Þ¥ó¥É¤ËÊ£¿ô¤Î¡Öp¡×¥ª¥×¥·¥ç¥ó¡Ös¡×¥³¥Þ¥ó¥É¤ËÊ£¿ô¤Î¿ôÃÍ¥ª¥×¥·¥ç¥óľÁ°¤ÎÀµµ¬É½¸½¤¬¡¢¤¢¤ê¤Þ¤»¤ó¡Ös¡×¥³¥Þ¥ó¥É¤Ø¤Î¿ôÃÍ¥ª¥×¥·¥ç¥ó¤ÏÎí¤Ç¤Ï¤¤¤±¤Þ¤»¤ó¡Öe¡×¥ª¥×¥·¥ç¥ó¤Ï¡¢¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó%s¤ÎÆÉ¹þ¤ß¥¨¥é¡¼: %s¡Öy¡×¥³¥Þ¥ó¥É¤Ø¤Îʸ»úÎó¤ÎŤµ¤¬¡¢°ã¤¤¤Þ¤¹super-sed %sÈÇ Í½´ü¤»¤Ì¡Ö,¡×¤Ç¤¹Í½´ü¤»¤Ì¡Ö}¡×¤Ç¤¹Ì¤ÃΤΥ³¥Þ¥ó¥É¤Ç¤¹: ¡Ö%c¡×¡Ös¡×¤Ø¤Î¥ª¥×¥·¥ç¥ó¤¬Ì¤ÃΤǤ¹Äà¤ê¹ç¤ï¤Ê¤¤¡Ö{¡×¤Ç¤¹¡Ös¡×¥³¥Þ¥ó¥É¤¬½ªÎ»¤·¤Æ¤¤¤Þ¤»¤ó¡Öy¡×¥³¥Þ¥ó¥É¤¬½ªÎ»¤·¤Æ¤¤¤Þ¤»¤ó¥¢¥É¥ì¥¹regex¤¬½ªÎ»¤·¤Æ¤¤¤Þ¤»¤ókbuild-3686/src/oldsed/po/da.po0000664000175000017500000002427615053010106016321 0ustar locutuslocutus# Danish messages for sed # Copyright (C) 2001 Free Software Foundation, Inc. # Byrial Ole Jensen , 2001-2003. # msgid "" msgstr "" "Project-Id-Version: sed 4.0.8\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2003-10-25 08:00+0200\n" "Last-Translator: Byrial Ole Jensen \n" "Language-Team: Danish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "Flere '!'" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "Uventet ','" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "Kan ikke bruge +N eller ~N som første adresse" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "Uparret '{'" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "Uventet '}'" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Ekstra tegn efter kommando" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "Forventede \\ efter 'a', 'c' eller 'i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "'}' vil ikke have adresser" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": vil ikke have adresser" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Kommentarer vil ikke have adresser" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Der mangler en kommando" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Kommandoen bruger kun én adresse" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Uafsluttet regulært udtryk for adresse" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Uafsluttet 's'-kommando" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Uafsluttet 'y'-kommando" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Ukendt tilvalg til 's'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "Flere 'p'-flag til 's'-kommando" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "Flere 'g'-flag til 's'-kommando" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "Flere tal-flag til 's'-kommando" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "s-kommandoens tal-flag må ikke være nul" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "y-kommandoens strenge har forskellige længder" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "forventede en nyere version af sed" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Forkert brug af adresse-ændrer" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Ukendt kommando:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: fil %s, linje %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e udtryk nr. %lu, tegn %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Kan ikke finde etiket for hop til '%s'" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: kan ikke læse %s: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "kunne ikke åbne filen %s: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "kunne ikke åbne filen %s: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "kunne ikke åbne midlertidig fil %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "fejl i underproces" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "tilvalg 'e' er ikke understøttet" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "'e'-kommando er ikke understøttet" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Intet forudgående regulært udtryk" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "Der kan ikke angives ændrere til tomt regulært udtryk" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Ugyldig reference \\%d på 's'-kommandos højreside" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " brug Perl 5's syntaks for regulære udtryk i skriptet\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " brug Perl 5's syntaks for regulære udtryk i skriptet\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Send fejlrapporter på engelsk pr. e-post til %s.\n" "Sørg venligst for at skrive ordet \"%s\" et sted i \"Subject:\"-feltet.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed version %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "baseret på GNU sed version 3.02.80\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed version %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Dette er frit programmel; se kildeteksten for kopieringsbetingelser.\n" "Der er INGEN garanti; end ikke for SALGBARHED eller EGNETHED TIL NOGET\n" "BESTEMT FORMÅL, i det omfang som loven tillader.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: kan ikke læse %s: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "kunne ikke åbne filen %s: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "kunne ikke skrive %d element til %s: %s" msgstr[1] "kunne ikke skrive %d elementer til %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "læsefejl på %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: kan ikke læse %s: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "Godt resultat" #: lib/regcomp.c:135 msgid "No match" msgstr "Intet resultat" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Ugyldigt regulært udtryk" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Ugyldigt sorteringstegn" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Ugyldigt navn på tegnklasse" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Afsluttende omvendt skråstreg" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Ugyldig reference bagud" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "Uparret [ eller [^" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "Uparret ( eller \\(" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "Uparret \\{" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Ugyldigt indhold af \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Ugyldig slutning på område" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Hukommelsen opbrugt" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Ugyldigt forudgående regulært udtryk" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Ufuldstændigt regulært udtryk" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Regulært udtryk for stort" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "Uparret ) eller \\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Intet forudgående regulært udtryk" kbuild-3686/src/oldsed/po/POTFILES.in0000664000175000017500000000016015053010106017134 0ustar locutuslocutussed/compile.c sed/execute.c sed/regexp.c sed/sed.c lib/utils.c lib/regcomp.c lib/regexec.c lib/regex_internal.c kbuild-3686/src/oldsed/po/zh_CN.gmo0000664000175000017500000000254715053010106017077 0ustar locutuslocutus•Þ |Ü %!G^xd•ú##=&a,ˆµ]Ê!(J_zP‹Üð ":V   %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. `}' doesn't want any addressesmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zeroread error on %s: %sProject-Id-Version: sed 3.02.80 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2002-08-18 11:11+0800 Last-Translator: Wang Li Language-Team: Chinese (simplified) MIME-Version: 1.0 Content-Type: text/plain; charset=gb2312 Content-Transfer-Encoding: 8bit %s£º-e ±í´ïʽ #%lu£¬×Ö·û %lu£º%s %s£ºÎÞ·¨¶ÁÈ¡ %s£º%s %s£ºÎļþ %s Ðкţº%lu£º%s : ²»ÐèÒªÈκεØÖ·½«´íÎ󱨸æÍ¨¹ýµç×ÓÓʼþ·¢Ë͵½£º%s . ÇëÎñ±Ø½«µ¥´Ê¡°%s¡±·ÅÔÚ¡°Subject:¡±ÓòµÄij´¦¡£ ¡°}¡±²»ÐèÒªÈκεØÖ·¶à¸ö¡°s¡±ÃüÁîµÄÑ¡Ïî¡°g¡±¶à¸ö¡°s¡±ÃüÁîµÄÑ¡Ïî¡°p¡±¶à¸ö¡°s¡±ÃüÁîµÄÊýֵѡÏî¡°s¡±ÃüÁîµÄÊýֵѡÏî²»ÄÜΪÁã¶ÁÈ¡ %s ³ö´í£º%skbuild-3686/src/oldsed/po/da.gmo0000664000175000017500000000751115053010106016456 0ustar locutuslocutus•Þ'T5Œ`\aº¾%yŸ¶ÐdíRf}š¶$Îó 1:#Y}˜ ³Å× éöB/r†#¤#È&ì,@Yni„Z îÀ I$  / I du } ó   ; S$ l ‘ ¬ Å Ù! è  ( B P n  ” §! ² ÔQ ïA"Tw—·'× ÿ 3!"  ' # % &$ -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessexpected newer version of sedmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: sed 4.0.8 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2003-10-25 08:00+0200 Last-Translator: Byrial Ole Jensen Language-Team: Danish MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n != 1; -R, --regexp-perl brug Perl 5's syntaks for regulære udtryk i skriptet %s Dette er frit programmel; se kildeteksten for kopieringsbetingelser. Der er INGEN garanti; end ikke for SALGBARHED eller EGNETHED TIL NOGET BESTEMT FORMÅL, i det omfang som loven tillader. %s: -e udtryk nr. %lu, tegn %lu: %s %s: kan ikke læse %s: %s %s: fil %s, linje %lu: %s : vil ikke have adresserSend fejlrapporter på engelsk pr. e-post til %s. Sørg venligst for at skrive ordet "%s" et sted i "Subject:"-feltet. GNU sed version %s Ugyldig reference bagudUgyldigt navn på tegnklasseUgyldigt sorteringstegnUgyldigt indhold af \{\}Ugyldigt forudgående regulært udtrykUgyldig slutning på områdeUgyldigt regulært udtrykHukommelsen opbrugtIntet resultatIntet forudgående regulært udtrykUfuldstændigt regulært udtrykRegulært udtryk for stortGodt resultatAfsluttende omvendt skråstregUparret ( eller \(Uparret ) eller \)Uparret [ eller [^Uparret \{'e'-kommando er ikke understøttet'}' vil ikke have adresserkunne ikke skrive %d element til %s: %skunne ikke skrive %d elementer til %s: %sfejl i underprocesforventede en nyere version af sedFlere 'g'-flag til 's'-kommandoFlere 'p'-flag til 's'-kommandoFlere tal-flag til 's'-kommandos-kommandoens tal-flag må ikke være nultilvalg 'e' er ikke understøttetlæsefejl på %s: %ssuper-sed version %s kbuild-3686/src/oldsed/po/fr.po0000664000175000017500000003043115053010106016332 0ustar locutuslocutus# French translation of GNU sed. # Copyright (C) 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. # Gaël Quéri , 1998. # # J'ai préféré utiliser le terme <> plutôt # qu'<> car celui-là est moins déroutant # pour ceux qui sont habitués à la formulation anglaise # msgid "" msgstr "" "Project-Id-Version: sed 4.1.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2004-07-12 00:09+0200\n" "Last-Translator: Gaël Quéri \n" "Language-Team: French \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: sed/compile.c:162 msgid "multiple `!'s" msgstr "`!' multiples" #: sed/compile.c:163 msgid "unexpected `,'" msgstr "`,' inattendue" #: sed/compile.c:164 msgid "invalid usage of +N or ~N as first address" msgstr "utilisation invalide de +N ou ~N comme première adresse" #: sed/compile.c:165 msgid "unmatched `{'" msgstr "`{' non refermée" #: sed/compile.c:166 msgid "unexpected `}'" msgstr "`}' inattendu" #: sed/compile.c:167 msgid "extra characters after command" msgstr "caractères inutiles après la commande" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "\\ attendu après `a', `c' ou `i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' n'a besoin d'aucune adresse" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": n'a besoin d'aucune adresse" #: sed/compile.c:171 msgid "comments don't accept any addresses" msgstr "les commentaires n'acceptent aucune adresse" #: sed/compile.c:172 msgid "missing command" msgstr "commande manquante" #: sed/compile.c:173 msgid "command only uses one address" msgstr "la commande n'utilise qu'une adresse" #: sed/compile.c:174 msgid "unterminated address regex" msgstr "expression régulière d'adresse inachevée" #: sed/compile.c:175 msgid "unterminated `s' command" msgstr "commande `s' inachevée" #: sed/compile.c:176 msgid "unterminated `y' command" msgstr "commande `y' inachevée" #: sed/compile.c:177 msgid "unknown option to `s'" msgstr "option inconnue pour `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "plusieurs options `p' à la commande `s'" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "plusieurs options `g' à la commande `s'" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "plusieurs options numériques à la commande `s'" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "l'option numérique de la comande `s' ne peut être nulle" #: sed/compile.c:182 msgid "strings for `y' command are different lengths" msgstr "les chaînes destinées à la commande `y' ont des longueurs différentes" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "le caractère délimiteur n'est pas un caractère à un seul octet" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "une version plus récente de sed est attendue" #: sed/compile.c:185 msgid "invalid usage of line address 0" msgstr "utilisation invalide de l'adresse de ligne 0" #: sed/compile.c:186 #, c-format msgid "unknown command: `%c'" msgstr "commande inconnue: `%c'" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: fichier %s ligne %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e expression n°%lu, caractère %lu: %s\n" #: sed/compile.c:1644 #, c-format msgid "can't find label for jump to `%s'" msgstr "impossible de trouver l'étiquette pour sauter à `%s'" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: impossible de lire %s: %s\n" #: sed/execute.c:673 #, c-format msgid "couldn't edit %s: is a terminal" msgstr "impossible d'éditer %s: est un terminal" #: sed/execute.c:677 #, c-format msgid "couldn't edit %s: not a regular file" msgstr "impossible d'éditer %s: ce n'est pas un fichier régulier" #: sed/execute.c:684 lib/utils.c:196 #, c-format msgid "couldn't open temporary file %s: %s" msgstr "impossible d'ouvrir le fichier temporaire %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "erreur dans le sous-processus" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "l'option `e' n'est pas supportée" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "la commande `e' n'est pas supportée" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "pas d'expression régulière précédente" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "" "impossible de spécifier des modifieurs sur une expression\n" "rationnelle vide" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "référence \\%d invalide dans le côté droit de la commande `s'" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " utiliser la syntaxe des expressions régulières\n" " de Perl 5 dans le script.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" "Utilisation: %s [OPTION]... {script-seulement-si-pas-d'autre-script}\n" "[fichier-d'entrée]...\n" "\n" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" " -n, --quiet, --silent\n" " supprimer l'écriture automatique de l'espace des motifs\n" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" " -e script, --expression=script\n" " ajouter le script aux commandes à être exécutées\n" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" " -f fichier-script, --file=fichier-script\n" " ajouter le contenu de fichier-script aux commandes\n" " à être exécutées\n" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" " -i[SUFFIXE], --in-place[=SUFFIXE]\n" " éditer les fichiers à leur place (fait une\n" " sauvegarde si l'extension est fournie)\n" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" " -l N, --line-length=N\n" " spécifier la longueur de coupure de ligne désirée pour la\n" " commande `l'\n" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" " --posix\n" " désactiver toutes les extensions GNU.\n" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -r, --regexp-extended\n" " utiliser la syntaxe des expressions régulières\n" " étendues dans le script.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" " -s, --separate\n" " considérer les fichiers comme séparés plutôt que comme un\n" " simple flux long et continu.\n" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" " -u, --unbuffered\n" " charger des quantités minimales de données depuis les\n" " fichiers d'entrée et libérer les tampons de sortie plus\n" " souvent\n" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr " --help afficher cette aide et sortir\n" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" " --version afficher les informations de version du logiciel et sortir\n" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" "\n" "Si aucune option -e, --expression, -f ou --file n'est donnée, le\n" "premier argument qui n'est pas une option sera pris comme étant le script\n" "sed à interpréter. Tous les arguments restants sont les noms des fichiers\n" "d'entrée; si aucun fichier d'entrée n'est spécifiée, l'entrée standard\n" "est lue.\n" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Rapporter toutes anomalies à: %s.\n" "N'oubliez pas d'inclure le mot ``%s'' quelque-part dans la zone " "``Subject:''\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed version %s\n" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "fondé sur GNU sed version %s\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed version %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Ce logiciel est libre; voir les sources pour les conditions de " "reproduction.\n" "AUCUNE garantie n'est donnée; y compris pour des RAISONS COMMERCIALES ou\n" "pour RÉPONDRE A UN BESOIN PARTICULIER, à l'étendue permise par la loi.\n" #: lib/utils.c:98 lib/utils.c:336 #, c-format msgid "cannot remove %s: %s" msgstr "impossible de supprimer %s: %s" #: lib/utils.c:143 #, c-format msgid "couldn't open file %s: %s" msgstr "impossible d'ouvrir le fichier %s: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "impossible d'écrire %d item à %s: %s" msgstr[1] "impossible d'écrire %d items à %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "erreur de lecture sur %s: %s" #: lib/utils.c:341 #, c-format msgid "cannot rename %s: %s" msgstr "impossible de renommer %s: %s" #: lib/regcomp.c:132 msgid "Success" msgstr "Succès" #: lib/regcomp.c:135 msgid "No match" msgstr "Pas de concordance" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Expression régulière invalide" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Caractère de collation invalide" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Nom de classe de caractères invalide" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Antislash de protection" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Référence arrière invalide" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "[ ou [^ non refermé" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "( ou \\( non refermé" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "\\{ non refermé" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Contenu de \\{\\} invalide" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Fin d'intervalle invalide" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Mémoire épuisée" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "L'expression régulière précédente est invalide" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Fin prématurée d'une expression régulière" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Expression régulière trop grande" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr ") ou \\) non refermé" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Pas d'expression régulière précédente" kbuild-3686/src/oldsed/po/hr.gmo0000664000175000017500000000372115053010106016502 0ustar locutuslocutus•ÞŒüHºI%*A[dxÝü##?&c,Š·’Ìž_ þ;Zet#Úþ%%@f-†´    %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. No previous regular expression`}' doesn't want any addressesmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zeroread error on %s: %sProject-Id-Version: sed 3.02a Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2002-06-14 15:17-01 Last-Translator: Denis Lackovic Language-Team: Croatian MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n==1?0:1); X-Generator: TransDict server %s Ovo je slobodni softver; pogledajte kod kako biste doznali uvjete kopiranja. NEMA garancije; Äak ni tvrdnje o ISPLATIVOSTI ili POGODNOSTI ZA NEKU SVRHU. %s: -e izraz #%lu, znak %lu: %s %s: ne mogu Äitati %s: %s %s: datoteka %s redak %lu: %s : ne želi nikakve adreseE-mail bug prijave (na engleskom) poÅ¡aljite na: %s . UkljuÄite rijeÄ ``%s'' u polju ``Subject:''. Nedostaje prethodni regularni izraz`}' ne želi nikakve adreseviÅ¡estruke `g' opcije za `s' naredbuviÅ¡estruke `p' opcije za `s' naredbuviÅ¡ak opcija za za `s' naredbubroj opcija za naredbu `s' ne smije biti nulaGreÅ¡ka u Äitanju na %s: %skbuild-3686/src/oldsed/po/he.po0000664000175000017500000002235715053010106016327 0ustar locutuslocutus# Hebrew messages for GNU Sed -*- coding: hebrew-iso-8bit -*- # Copyright (C) 2001 Free Software Foundation, Inc. # Eli Zaretskii , 2001. # msgid "" msgstr "" "Project-Id-Version: sed 3.02.80\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2001-08-04 20:37+0300\n" "Last-Translator: Eli Zaretskii \n" "Language-Team: Hebrew \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-8\n" "Content-Transfer-Encoding: 8-bit\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "`!' éåáéø" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "éåôö-éúìá `,'" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "äðåùàø úáåúëë ~N åà +N-á ùîúùäì ïúéð àì" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "âåæ-ïá åì ïéàù `{'" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "éåôö-éúìá `}'" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "äãå÷ôä éøçà íéøúåéî íéåú" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "úåáåúë ìá÷î åðéà `}'" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr "úåáåúë ìá÷î åðéà :" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "úåáåúë úåìá÷î ïðéà úåøòä" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "äøñç äãå÷ô" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "ãáìá úçà úáåúë úìá÷î åæ äãå÷ô" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "íåéñ àìì úáåúë ìù éøìåâø éåèéá" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "íåéñ àìì `s' úãå÷ô" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "íåéñ àìì `y' úãå÷ô" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "`s' ìù øëåî-éúìá ïééôàî" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "`s' äãå÷ôì íéáåøî `p' éðééôàî" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "`s' äãå÷ôì íéáåøî `g' éðééôàî" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "`s' äãå÷ôì íéáåøî øôñî éðééôàî" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "ñôà úåéäì ìåëé åðéà `s' äãå÷ôì éøôñî ïééôàî" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "äðåù êøåàá ïðéä `y' äãå÷ôì úåæåøçî" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "úáåúëä ïééöîá éåâù ùåîéù" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "úøëåî-éúìá äãå÷ô äðéä" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s úéðëúá (%s õáå÷ ìù %lu äøåù) %s äàéâù\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s úéðëúá (%lu 'ñî -e éåèéá ìù %lu 'ñî åú) %s äàéâù\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "äàöîð àì `%s' äöéô÷ úéååú" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s úéðëúá %s úàéø÷á (%s) äàéâù\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "%s õáå÷ úçéúôá äì÷ú" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "%s õáå÷ úçéúôá äì÷ú" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "%s õáå÷ úçéúôá äì÷ú" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" " .%s úáåúëì (bugs) äì÷ú éçååéã çåìùì àð\n" " .(``Subject'') ``ïåãðä'' úøåùá ``%s'' äìéî ìåìëì åãéô÷ä àðà\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "äååìî äðéà úéðëúä .øå÷îä éöá÷ úà äàø ,èåøéô øúéì ;úéùôç äðëú äðéä åæ úéðëú\n" " äãéîá úàæå ,àéäù úéìëú åæéàì äîàúä åà úåøéçñ íùì àì åìéôà ;úåéøçà áúëá\n" " .úàæ øùôàî ÷åçäù\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s úéðëúá %s úàéø÷á (%s) äàéâù\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "%s õáå÷ úçéúôá äì÷ú" #: lib/utils.c:220 #, fuzzy, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "èìôäî íé÷ìç %d ìù %s-ì äáéúëá (%s) äì÷ú" msgstr[1] "èìôäî íé÷ìç %d ìù %s-ì äáéúëá (%s) äì÷ú" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "%s úàéø÷á (%s) äì÷ú" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s úéðëúá %s úàéø÷á (%s) äàéâù\n" #: lib/regcomp.c:132 msgid "Success" msgstr "" #: lib/regcomp.c:135 msgid "No match" msgstr "" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "" #: lib/regcomp.c:153 #, fuzzy msgid "Unmatched [ or [^" msgstr "âåæ-ïá åì ïéàù `{'" #: lib/regcomp.c:156 #, fuzzy msgid "Unmatched ( or \\(" msgstr "âåæ-ïá åì ïéàù `{'" #: lib/regcomp.c:159 #, fuzzy msgid "Unmatched \\{" msgstr "âåæ-ïá åì ïéàù `{'" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "" #: lib/regcomp.c:180 #, fuzzy msgid "Unmatched ) or \\)" msgstr "âåæ-ïá åì ïéàù `{'" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "" kbuild-3686/src/oldsed/po/tr.po0000664000175000017500000002501115053010106016346 0ustar locutuslocutus# translation of sed-4.0.9.tr.po to Turkish # Copyright (C) 2003 Free Software Foundation, Inc. # Deniz Akkus Kanca , 2001,2003, 2004. # msgid "" msgstr "" "Project-Id-Version: sed 4.0.9\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2004-05-19 18:06+0300\n" "Last-Translator: Deniz Akkus Kanca \n" "Language-Team: Turkish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.0.2\n" "Plural-Forms: nplurals=1; plural=0;\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "Birden fazla '!'" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "Beklenmeyen ','" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "İlk adres olarak +N veya ~N kullanılamaz" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "EÅŸleÅŸmeyen '{'" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "Beklenmeyen '}'" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Komuttan sonra fazla karakterler var" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "`a', `c' veya `i' sonrası \\ beklendi" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "'}' için adres istenmez" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": için hiç adres istenmez" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Açıklamalarda adres kabul edilmez" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Komut eksik" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Komutta yalnızca tek adres kullanılır" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Sonlandırılmamış adres düzenli ifadesi" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Sonlandırılmamış 's' komutu" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Sonlandırılmamış 'y' komutu" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "`s' komutuna bilinmeyen seçenek verilmiÅŸ" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "`s' komutuna birden fazla `p' seçeneÄŸi verilmiÅŸ" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "`s' komutuna birden fazla `g' seçeneÄŸi verilmiÅŸ" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "`s' komutuna birden fazla sayı seçeneÄŸi verilmiÅŸ" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "`s' komutuna verilen sayı seçeneÄŸi sıfır olamaz" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "y komutu için dizgeler deÄŸiÅŸik uzunluklarda" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "sed'in daha yeni bir sürümü beklendi" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Adres deÄŸiÅŸtirici hatalı kullanılmış" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Bilinmeyen komut:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: dosya %s satır %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e ifade #%lu, harf %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "`%s'e atlamak için etiket bulunamıyor" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: %s okunamıyor: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "%d sayıda öğe %s'e yazılamadı: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "%d sayıda öğe %s'e yazılamadı: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Geçici dosya %s açılamadı: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "altsüreçte hata" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr " e' seçeneÄŸi desteklenmiyor" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "`e' komutu desteklenmiyor" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Daha önce düzenli ifade yok" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "BoÅŸ düzenli ifadeye deÄŸiÅŸtirici atanamaz" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "`s' komutunun RHS'sinde geçersiz \\%d referansı" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " betikte Perl 5'in düzenli ifade sözdizimini kullanır.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " betikte Perl 5'in düzenli ifade sözdizimini kullanır.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Yazılım hatalarını %s adresine, çeviri hatalarını \n" " adresine bildirin. \n" "``%s'' sözcüğünün Konu baÅŸlığında yer almasına dikkat edin. \n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed sürüm %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "GNU sed sürümü 3.02.80 temel alınmıştır\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed sürümü %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Bu serbest yazılımdır; kopyalama koÅŸulları için kaynak koduna bakınız.\n" "Hiçbir garantisi yoktur; hatta SATILABİLİRLİĞİ veya HERHANGİ BİR AMACA\n" "UYGUNLUÄžU için bile garanti verilmez.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: %s okunamıyor: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "%s dosyası açılamadı: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "%d sayıda öğe %s'e yazılamadı: %s" msgstr[1] "%d sayıda öğe %s'e yazılamadı: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "%s'de okuma hatası: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: %s okunamıyor: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "BaÅŸarılı" #: lib/regcomp.c:135 msgid "No match" msgstr "EÅŸleÅŸme bulunamadı" # #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Hatalı düzenli ifade" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Hatalı birleÅŸtirme karakteri" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Hatalı karakter sınıf ismi" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Sonda fazla gerikesme var" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Hatalı geri referans" # #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "EÅŸleÅŸmeyen [ veya [^" # #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "EÅŸleÅŸmeyen ( veya \\(" # #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "EÅŸleÅŸmeyen \\{" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "\\{\\} içeriÄŸi hatalı" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Geçersiz kapsam sonu" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Bellek tükendi" # #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Bir önceki düzenli ifade hatalı" # #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Düzenli ifade erken sonlandı" # #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Düzenli ifade fazla büyük" # #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "EÅŸleÅŸmeyen ) or \\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Daha önce düzenli ifade yok" kbuild-3686/src/oldsed/po/hu.gmo0000664000175000017500000000773115053010106016512 0ustar locutuslocutus•Þ'T5Œ`\aº¾%yŸ¶ÐdíRf}š¶$Îó 1:#Y}˜ ³Å× éöB/r†#¤#È&ì,@Yn}„W è Z( C l Š £{ ¹ 5 H f# † ª( Ê ó  & 6! D" f ‰ ¦ ®  ٠ð6SN¢,¸)å)*9-d’¯Ä!"  ' # % &$ -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessexpected newer version of sedmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: sed 4.0.8 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2003-10-26 09:28+0100 Last-Translator: Mihály Gyulai Language-Team: Hungarian MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-2 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; -R --regexp-perl Perl 5 reguláris kifejezés nyelvtanának használata. %s Ez egy ingyenes számítógépes program. A forrásban megtalálhatók a másolás feltételei. SEMMILYEN garanciát nem vállalunk, még azt sem állítjuk, hogy ez a program KERESKEDELMI CÉLOKRA ALKALMAS vagy HASZNÁLHATÓ EGY ADOTT FELADATRA. %s: -e kifejezés #%lu, karakter %lu: %s %s: nem lehet olvasni %s: %s %s: fájl %s sor %lu: %s : nem igényel címzéstA fordítási hibákat kérem a gyulai@fbi.hu címre küldeni. Angolul ide: %s . A levél Tárgy mezejében legyen ott a `%s' szó. GNU sed verzió %s Érvénytelen vissza-hivatkozásÉrvénytelen karakterosztály-névÉrvénytelen összehasonlító karakter\{\}-nak érvénytelen a tartalmaÉrvénytelen megelõzõ reguláris kifejezésSorozat érvénytelen végeHibás reguláris kifejezésKevés a memóriaNincs találatNincsen elõzõ reguláris kifejezésReguláris kifejezés túl korai végeTúl nagy reguláris kifejezésSikeresLezáró visszaperjelNincs párban ( vagy \(Nincs párban ) vagy \)Nincs párban [ vagy [^Nincs párban \{az `e' parancs nincs támogatva`}' nem igényel címzéstnem tudom a(z) %d elemet ide írni %s: %snem tudom a(z) %d elemeket ide írni %s: %shiba az alfolyamatbana 'sed' program újabb verziójára van szükségtöbbszörös `g' opció, `s' parancs melletttöbbszörös `p' opció, `s' parancs melletttöbbszörös szám opció, `s' parancs melletta(z) `s' parancs szám opciója nem lehet nullaaz `e' opció nincs támogatvaolvasási hiba %s: %ssuper-sed verzió %s kbuild-3686/src/oldsed/po/sed.pot0000664000175000017500000001742715053010106016674 0ustar locutuslocutus# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #: sed/compile.c:162 msgid "multiple `!'s" msgstr "" #: sed/compile.c:163 msgid "unexpected `,'" msgstr "" #: sed/compile.c:164 msgid "invalid usage of +N or ~N as first address" msgstr "" #: sed/compile.c:165 msgid "unmatched `{'" msgstr "" #: sed/compile.c:166 msgid "unexpected `}'" msgstr "" #: sed/compile.c:167 msgid "extra characters after command" msgstr "" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr "" #: sed/compile.c:171 msgid "comments don't accept any addresses" msgstr "" #: sed/compile.c:172 msgid "missing command" msgstr "" #: sed/compile.c:173 msgid "command only uses one address" msgstr "" #: sed/compile.c:174 msgid "unterminated address regex" msgstr "" #: sed/compile.c:175 msgid "unterminated `s' command" msgstr "" #: sed/compile.c:176 msgid "unterminated `y' command" msgstr "" #: sed/compile.c:177 msgid "unknown option to `s'" msgstr "" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "" #: sed/compile.c:182 msgid "strings for `y' command are different lengths" msgstr "" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "" #: sed/compile.c:185 msgid "invalid usage of line address 0" msgstr "" #: sed/compile.c:186 #, c-format msgid "unknown command: `%c'" msgstr "" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "" #: sed/compile.c:1644 #, c-format msgid "can't find label for jump to `%s'" msgstr "" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "" #: sed/execute.c:673 #, c-format msgid "couldn't edit %s: is a terminal" msgstr "" #: sed/execute.c:677 #, c-format msgid "couldn't edit %s: not a regular file" msgstr "" #: sed/execute.c:684 lib/utils.c:196 #, c-format msgid "couldn't open temporary file %s: %s" msgstr "" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" #: lib/utils.c:98 lib/utils.c:336 #, c-format msgid "cannot remove %s: %s" msgstr "" #: lib/utils.c:143 #, c-format msgid "couldn't open file %s: %s" msgstr "" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "" msgstr[1] "" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "" #: lib/utils.c:341 #, c-format msgid "cannot rename %s: %s" msgstr "" #: lib/regcomp.c:132 msgid "Success" msgstr "" #: lib/regcomp.c:135 msgid "No match" msgstr "" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "" kbuild-3686/src/oldsed/po/Rules-quot0000664000175000017500000000323115053010106017364 0ustar locutuslocutus# Special Makefile rules for English message catalogs with quotation marks. DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot .SUFFIXES: .insert-header .po-update-en en@quot.po-update: en@quot.po-update-en en@boldquot.po-update: en@boldquot.po-update-en .insert-header.po-update-en: @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ ll=`echo $$lang | sed -e 's/@.*//'`; \ LC_ALL=C; export LC_ALL; \ cd $(srcdir); \ if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$ll -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ exit 1; \ fi; \ fi; \ else \ echo "creation of $$lang.po failed!" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ fi en@quot.insert-header: insert-header.sin sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header en@boldquot.insert-header: insert-header.sin sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header mostlyclean: mostlyclean-quot mostlyclean-quot: rm -f *.insert-header kbuild-3686/src/oldsed/po/pt_BR.po0000664000175000017500000002544315053010106016740 0ustar locutuslocutus# traduções para o português do Brasil das mensagens de erro do sed # Copyright (C) 1999 Free Software Foundation, Inc. # Aurélio Marinho Jargas , 1999, 2002. # # Tradução original da versão 4.01: # Juan Carlos Castro y Castro , 2002. # msgid "" msgstr "" "Project-Id-Version: sed 4.0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2002-11-08 17:44-0300\n" "Last-Translator: Aurélio Marinho Jargas \n" "Language-Team: Brazilian Portuguese \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "Exclamações `!' múltiplas" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "Vírgula `,' inesperada" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "Não use +N ou ~N como o primeiro endereço" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "`{' não terminada" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "`}' inesperada" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Há caracteres sobrando após o comando" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "Deve haver um escape \\ depois dos comandos `a', `c' e `i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' não recebe endereços" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr "`:' não recebe endereços" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Comentários não aceitam endereços" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Falta especificar um comando ao endereço" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Este comando usa apenas um endereço" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "A expressão regular do endereço está inacabada (falta a /)" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Comando `s' inacabado (s/// - faltou delimitador)" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Comando `y' inacabado (y/// - faltou delimitador)" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Opção desconhecida para o comando `s' (s///?)" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "opções `p' múltiplas para o comando `s'" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "opções `g' múltiplas para o comando `s'" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "opções numéricas múltiplas para o comando `s' (s///n)" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "A opção numérica para o comando `s' não pode ser zero (s///0)" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "Os textos para o comando `y' têm tamanhos diferentes (y/abc/z/)" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Uso incorreto do modificador de endereço" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Comando desconhecido:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: arquivo %s linha %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e expressão #%lu, caractere %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Não foi possível encontrar a marcação `%s'" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: não foi possível ler %s: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Não foi possível abrir o arquivo %s: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Não foi possível abrir o arquivo %s: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Não foi possível abrir o arquivo %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "erro no subprocesso" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "opção `e' não suportada" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "comando `e' não suportado" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Não há expressão regular anterior" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "Não é permitido especificar modificadores numa expressão regular vazia" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Referência inválida \\%d na segunda parte do comando `s'" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " usar sintaxe de expressões regulares do Perl 5 no script.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " usar sintaxe de expressões regulares do Perl 5 no script.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Envie relatórios de erros (em inglês) para: %s .\n" "Inclua a palavra ``%s'' no campo ``Assunto:'' ou ``Subject:''.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed versão %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "baseado no GNU sed versão 3.02.80\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed versão %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Este programa é Software Livre. Veja os fontes para conhecer as condições\n" "de cópia. NÃO há garantias, nem mesmo para os aspectos mercantis ou de\n" "atendimento a finalidades específicas, tanto quanto a lei permita.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: não foi possível ler %s: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Não foi possível abrir o arquivo %s: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "não foi possível escrever %d item para %s: %s" msgstr[1] "não foi possível escrever %d items para %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "erro de leitura em %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: não foi possível ler %s: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "Sucesso" #: lib/regcomp.c:135 msgid "No match" msgstr "Nada encontrado" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Expressão regular inválida" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Caractere de ordenação inválido" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Nome inválido de classe de caracteres" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Escape \\ no final" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Retrovisor \\n inválido" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "[ ou [^ não terminado" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "( ou \\( não terminado" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "\\{ não terminado" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Conteúdo inválido no \\{\\} (permitidos números e vírgula)" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Fim de intervalo (range) inválido" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Falta de memória" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Expressão regular anterior inválida" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Fim prematuro da expressão regular" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Expressão regular grande demais" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr ") or \\) inesperado" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Não há expressão regular anterior" kbuild-3686/src/oldsed/po/Makefile.in.in0000664000175000017500000002304515053010106020040 0ustar locutuslocutus# Makefile for PO directory in any package using GNU gettext. # Copyright (C) 1995-1997, 2000-2002 by Ulrich Drepper # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU General Public # License but which still want to provide support for the GNU gettext # functionality. # Please note that the actual code of GNU gettext is covered by the GNU # General Public License and is *not* in the public domain. PACKAGE = @PACKAGE@ VERSION = @VERSION@ SHELL = /bin/sh @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datadir = @datadir@ localedir = $(datadir)/locale gettextsrcdir = $(datadir)/gettext/po INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ MKINSTALLDIRS = @MKINSTALLDIRS@ mkinstalldirs = $(SHELL) `case "$(MKINSTALLDIRS)" in /*) echo "$(MKINSTALLDIRS)" ;; *) echo "$(top_builddir)/$(MKINSTALLDIRS)" ;; esac` GMSGFMT = @GMSGFMT@ MSGFMT = @MSGFMT@ XGETTEXT = @XGETTEXT@ MSGMERGE = msgmerge MSGMERGE_UPDATE = @MSGMERGE@ --update MSGINIT = msginit MSGCONV = msgconv MSGFILTER = msgfilter POFILES = @POFILES@ GMOFILES = @GMOFILES@ UPDATEPOFILES = @UPDATEPOFILES@ DUMMYPOFILES = @DUMMYPOFILES@ DISTFILES.common = Makefile.in.in Makevars \ $(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) DISTFILES = $(DISTFILES.common) POTFILES.in $(DOMAIN).pot \ $(POFILES) $(GMOFILES) \ $(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) POTFILES = \ CATALOGS = @CATALOGS@ # Makevars gets inserted here. (Don't remove this line!) .SUFFIXES: .SUFFIXES: .po .gmo .mo .nop .po-update .po.mo: $(MSGFMT) -c -o $@ $< .po.gmo: @lang=`echo $* | sed -e 's,.*/,,'`; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o $${lang}.gmo $${lang}.po"; \ cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o $${lang}.gmo $${lang}.po all: all-@USE_NLS@ all-yes: $(CATALOGS) all-no: # Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', # otherwise packages like GCC can not be built if only parts of the source # have been downloaded. $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) \ --files-from=$(srcdir)/POTFILES.in \ --copyright-holder='$(COPYRIGHT_HOLDER)' \ && test ! -f $(DOMAIN).po \ || ( rm -f $(srcdir)/$(DOMAIN).pot \ && mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot ) $(srcdir)/$(DOMAIN).pot: $(MAKE) $(DOMAIN).pot-update $(POFILES): $(srcdir)/$(DOMAIN).pot @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot"; \ cd $(srcdir) && $(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot install: install-exec install-data install-exec: install-data: install-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext"; then \ $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ for file in $(DISTFILES.common); do \ $(INSTALL_DATA) $(srcdir)/$$file \ $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi install-data-no: all install-data-yes: all $(mkinstalldirs) $(DESTDIR)$(datadir) @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(mkinstalldirs) $(DESTDIR)$$dir; \ if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ fi; \ done; \ done install-strip: install installdirs: installdirs-exec installdirs-data installdirs-exec: installdirs-data: installdirs-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext"; then \ $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ else \ : ; \ fi installdirs-data-no: installdirs-data-yes: $(mkinstalldirs) $(DESTDIR)$(datadir) @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(mkinstalldirs) $(DESTDIR)$$dir; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ fi; \ done; \ done # Define this as empty until I found a useful application. installcheck: uninstall: uninstall-exec uninstall-data uninstall-exec: uninstall-data: uninstall-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext"; then \ for file in $(DISTFILES.common); do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi uninstall-data-no: uninstall-data-yes: catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ done; \ done check: all dvi info tags TAGS ID: mostlyclean: rm -f core core.* $(DOMAIN).po *.new.po rm -fr *.o clean: mostlyclean distclean: clean rm -f Makefile Makefile.in POTFILES *.mo maintainer-clean: distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." rm -f $(GMOFILES) distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) dist distdir: $(MAKE) update-po @$(MAKE) dist2 # This is a separate target because 'update-po' must be executed before. dist2: $(DISTFILES) dists="$(DISTFILES)"; \ if test -f $(srcdir)/ChangeLog; then dists="$$dists ChangeLog"; fi; \ if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ for file in $$dists; do \ if test -f $$file; then \ cp -p $$file $(distdir); \ else \ cp -p $(srcdir)/$$file $(distdir); \ fi; \ done update-po: Makefile $(MAKE) $(DOMAIN).pot-update $(MAKE) $(UPDATEPOFILES) $(MAKE) update-gmo # General rule for updating PO files. .nop.po-update: @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ cd $(srcdir); \ if $(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$tmpdir/$$lang.new.po; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $$lang.po failed!" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ fi $(DUMMYPOFILES): update-gmo: Makefile $(GMOFILES) @: Makefile: Makefile.in.in $(top_builddir)/config.status POTFILES.in cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \ $(SHELL) ./config.status force: # Tell versions [3.59,3.63) of GNU make not to export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: kbuild-3686/src/oldsed/po/fi.po0000664000175000017500000002506315053010106016326 0ustar locutuslocutus# Finnish translations for GNU sed. # Copyright © 2002 Free Software Foundation, Inc. # Sami J. Laine , 2002 # msgid "" msgstr "" "Project-Id-Version: sed-4.0.8\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2003-12-07 09:35+0200\n" "Last-Translator: Sami J. Laine \n" "Language-Team: Finnish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-15\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "Useita \"!\"-merkkejä" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "Odottamaton \",\"" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "Ensimmäisenä osoitteena ei voi olla +N tai ~N" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "Pariton \"{\"" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "Pariton \"}\"" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Ylimääräisiä merkkejä komennon jälkeen" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "\\ odotettiin merkkien `a', `c' tai `i' jälkeen" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "\"}\" ei tarvitse osoitteita" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": ei tarvitse osoitteita" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Kommentit eivät hyväksy osoitteita" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Puuttuva komento" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Komento käyttää vain yhtä osoitetta" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Päättymätön osoite vakiolauseessa" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Päättymätön \"s\"-komento" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Päättymätön \"y\"-komento" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Tuntematon valitsin \"s\":lle" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "useita \"p\"-valitsimia \"s\"-komennolle" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "useita \"g\"-valitsimia \"s\"-komennolle" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "useita valitsimia \"s\"-komennolle" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "numeerinen valitsin \"s\"-komennolle ei voi olla nolla" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "merkkijonot \"y\"-komennolle ovat pituudeltaan vaihtelevia" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "odotettiin uudempaa versiota sed:stä" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Komento käyttää vain yhtä osoitetta" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Tuntematon komento:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: tiedosto %s rivi %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e lauseke #%lu, merkki %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Nimikettä hypylle kohteeseen \"%s\" ei löydy" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: ei voida lukea syötettä %s: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Tiedostoa %s ei voitu avata: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Tiedostoa %s ei voitu avata: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Väliaikaistiedostoa %s ei voitu avata: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "virhe lapsiprosessissa" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "valitsin `e' ei ole tuettu" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "komento `e' ei ole tuettu" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Ei aikaisempaa säännöllistä lausetta" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "Muuttajia ei voida määritellä tyhjään säännöliseen lausekkeeseen" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Virheellinen viittaus \\%d komennon `s' oikealla puolella" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " käytä Perl 5:en mukaista säännöllisten lauseiden\n" " syntaksia skriptissä.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " käytä Perl 5:en mukaista säännöllisten lauseiden\n" " syntaksia skriptissä.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Lähetä virheraportit osoitteeseen %s .\n" "Sisällytä sana \"%s\" viestin aihekenttään (\"Subject\"-kenttään).\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed versio %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "perustuu GNU sed versioon 3.02.80\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed versio %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Tämä ohjelma on vapaa ohjelmisto; tarkista jakeluehdot lähdekoodista.\n" "Tälle ohjelmalle ei anneta minkäänlaista takuuta; ei edes takuuta\n" "kaupallisesti hyväksyttävästä laadusta tai soveltuvuudesta tiettyyn\n" "tarkoitukseen.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: ei voida lukea syötettä %s: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Tiedostoa %s ei voitu avata: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "%d kohdetta ei voitu kirjoittaa tulosteeseen %s: %s" msgstr[1] "%d kohdetta ei voitu kirjoittaa tulosteeseen %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "lukuvirhe syötteessä %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: ei voida lukea syötettä %s: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "Onnistui" #: lib/regcomp.c:135 msgid "No match" msgstr "Ei osumaa" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Virheellinen säännöllinen lauseke" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Virheellinen vertailumerkki" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Virhellinen merkkiluokan nimi" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Seuraava kenoviiva" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Virheellinen takaisinviittaus" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "Pariton \"[\" tai \"[^\"" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "Pariton \"(\" tai \"\\(\"" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "Pariton \"\\{\"" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Virheellinen sisältö \\{\\}:ssä" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Virheellinen välin loppu" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Muisti loppu" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Virheellinen edeltävä säännöllinen lauseke" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Ennenaikainen säännöllisen lausekkeen loppu" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Säännöllinen lauseke on liian suuri" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "Pariton \")\" tai \"\\)\"" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Ei aikaisempaa säännöllistä lausetta" kbuild-3686/src/oldsed/po/boldquot.sed0000664000175000017500000000033115053010106017705 0ustar locutuslocutuss/"\([^"]*\)"/“\1â€/g s/`\([^`']*\)'/‘\1’/g s/ '\([^`']*\)' / ‘\1’ /g s/ '\([^`']*\)'$/ ‘\1’/g s/^'\([^`']*\)' /‘\1’ /g s/“â€/""/g s/“/“/g s/â€/â€/g s/‘/‘/g s/’/’/g kbuild-3686/src/oldsed/po/ko.gmo0000664000175000017500000000360415053010106016502 0ustar locutuslocutus•Þ „ì0º1%ì)Cd`Å#ä#&,,S€>•ÝÔ%²Øø"a:$œ'Á'é(0:k    %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. `}' doesn't want any addressesmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zeroread error on %s: %sProject-Id-Version: GNU sed 3.02.80 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2001-10-12 17:26+0900 Last-Translator: Jong-Hoon Ryu Language-Team: Korean MIME-Version: 1.0 Content-Type: text/plain; charset=EUC-KR Content-Transfer-Encoding: 8bit %s ÀÌ ÇÁ·Î±×·¥Àº ÀÚÀ¯ ¼ÒÇÁÆ®¿þ¾î ÀÔ´Ï´Ù; ÀÚ¼¼ÇÑ ³»¿ëÀº ÀúÀÛ±Ç ³»¿ëÀÇ ¿ø¹®À» Âü°íÇϽñ⠹ٶø´Ï´Ù. ÀÌ ÇÁ·Î±×·¥Àº ¹ý¿¡ ÀúÃ˵ÇÁö ¾Ê´Â ¹üÀ§¿¡¼­ »ó¾÷ÀûÀ̳ª Ư¼ö ¸ñÀûÀ¸·Î »ç¿ëµÉ °æ¿ì¸¦ Æ÷ÇÔÇÑ ¾î¶°ÇÑ °æ¿ì¿¡µµ º¸ÁõÇÏÁö ¾Ê½À´Ï´Ù. %s: -e expression #%lu, char %lu: %s %s: %s (À»)¸¦ ÀÐÀ» ¼ö ¾øÀ½: %s %s: %s ÆÄÀÏÀÇ %lu ¹øÂ° ÁÙ: %s : ¿¡ ¾î¶°ÇÑ ÁÖ¼Òµµ ÇÊ¿äÄ¡ ¾Ê½À´Ï´Ù¹ö±×¸¦ º¸°íÇÒ E-mail ÁÖ¼Ò: %s . ``Subject:'' Ç׸ñ¿¡ ¹Ýµå½Ã ``%s'' ´Ü¾î¸¦ Æ÷ÇÔÇØ Áֽñ⠹ٶø´Ï´Ù. `}' ¿¡ ¾î¶°ÇÑ ÁÖ¼Òµµ ÇÊ¿äÄ¡ ¾Ê½À´Ï´Ù`s' ¸í·É¿¡ `g' ¿É¼ÇÀÌ Áߺ¹µÇ¾î ÀÖ½À´Ï´Ù`s' ¸í·É¿¡ `p' ¿É¼ÇÀÌ Áߺ¹µÇ¾î ÀÖ½À´Ï´Ù`s' ¸í·É¿¡ ¼ýÀÚ ¿É¼ÇÀÌ Áߺ¹µÇ¾î ÀÖ½À´Ï´Ù`s' ¸í·ÉÀÇ ¼ýÀÚ ¿É¼Ç¿¡ '0' À» ÁöÁ¤ÇÒ ¼ö ¾ø½À´Ï´Ù%s ÀÇ ³»¿ë Àб⠿À·ù: %skbuild-3686/src/oldsed/po/af.po0000664000175000017500000002434315053010106016316 0ustar locutuslocutus# SOME DESCRIPTIVE TITLE. # Copyright (C) 2004 Free Software Foundation, Inc. # This file is distributed under the same license as the sed package. # Ysbeer , 2004 # msgid "" msgstr "" "Project-Id-Version: sed 4.0.9\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2004-01-11 21:06+0000\n" "Last-Translator: Ysbeer \n" "Language-Team: Afrikaans \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n!=1;\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "Meervoudige `!'s" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "Onverwagte `,'" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "Kan nie +N or ~N as die eerste adres gebruik nie" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "Ongepaarde `{'" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "Onverwagte `}'" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Ekstra karakters na instruksie" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "Het \\ na `a', `c' or `i' verwag" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' soek nie 'n adres nie" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": soek nie 'n adres nie" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Kommentare aanvaar nie adresse nie" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Vermiste instruksie" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Instruksie gebruik slegs een adres" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Ongetermineerde adresregex" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Ongetermineerde `s' instruksie" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Ongetermineerde `y' instruksie" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Onbekende opsie vir `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "meervoudige `p' opsies vir `s' instruksie" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "meervoudige `g' opsies vir `s' instruksie" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "meervoudige nommeropsies vir `s' instruksie" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "nommeropsie vir `s' instruksie mag nie nul wees nie" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "stringe vir y-instruksie het verskillende lengtes" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "het nuwer sed-weergawe verwag" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Instruksie gebruik slegs een adres" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Onbekende instruksie:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: lêer %s lyn %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e uitdrukking #%lu, karakter %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Kan nie etiket vir sprong na `%s' kry nie" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: Kan nie %s lees nie: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Kon nie die lêer %s oopmaak nie: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Kon nie die lêer %s oopmaak nie: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Kon nie tydelike lêer %s oopmaak nie: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "fout in subproses" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "opsie `e' word nie ondersteun nie" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "`e' instruksie word nie ondersteun nie" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Geen vorige regex nie" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "Kan nie veranderaars vir leë regex spesifiseer nie" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Ongeldige regterhandsverwysing \\%d vir `s' instruksie" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " gebruik Perl 5 se regexsintaks in die skrip.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " gebruik Perl 5 se regexsintaks in die skrip.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Rapporteer foute per e-pos aan: %s .\n" "Sluit asb. die woord ``%s'' êrens in die onderwerplyn in.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed weergawe %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "gebaseer op GNU sed weergawe 3.02.80\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed weergawe %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Hierdie is vrye sagteware; raadpleeg die bronkode vir kopiëringsinligting. " "Daar is GEEN\n" "waarborg nie; nie eens vir BRUIKBAARHEID of GESKIKHEID VIR 'n SPESIFIEK " "DOEL,\n" "binne regsperke nie.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: Kan nie %s lees nie: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Kon nie die lêer %s oopmaak nie: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "kon nie %d item na %s skryf nie: %s" msgstr[1] "kon nie %d items na %s skryf nie: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "leesfout op %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: Kan nie %s lees nie: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "Sukses" #: lib/regcomp.c:135 msgid "No match" msgstr "Geen paring" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Ongeldige regex" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Ongeldige kollasiekarakter" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Ongeldige karakterklasnaam" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Sleep terugstreep" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Ongeldige terugverwysing" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "Ongepaarde [ of [^" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "Ongepaarde ( or \\(" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "Ongepaarde \\{" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Ongeldige inhoud binne \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Ongeldige bereikseinde" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Geheue uitgeput" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Ongeldige vorige regex" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Premature einde vir regex" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Regex te groot" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "Ongepaarde ) of \\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Geen vorige regex nie" kbuild-3686/src/oldsed/po/ga.po0000664000175000017500000003000215053010106016304 0ustar locutuslocutus# Irish translations for sed # Copyright (C) 2003, 2004 Free Software Foundation, Inc. # Kevin Patrick Scannell , 2003, 2004. # msgid "" msgstr "" "Project-Id-Version: sed 4.1.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2004-07-07 11:04-0500\n" "Last-Translator: Kevin Patrick Scannell \n" "Language-Team: Irish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=n==1 ? 0 : (n>1 && n<7) ? 1 : (n>6 && n " "<11) ? 2 : 3;\n" #: sed/compile.c:162 msgid "multiple `!'s" msgstr "`!'-anna iomadúla" #: sed/compile.c:163 msgid "unexpected `,'" msgstr "`,' gan choinne" #: sed/compile.c:164 msgid "invalid usage of +N or ~N as first address" msgstr "ní féidir +N nó ~N a úsáid mar an chéad seoladh" #: sed/compile.c:165 msgid "unmatched `{'" msgstr "`{' corr" #: sed/compile.c:166 msgid "unexpected `}'" msgstr "`}' gan choinne" #: sed/compile.c:167 msgid "extra characters after command" msgstr "carachtair breise i ndiaidh an t-ordú" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "bhíothas ag súil le \\ i ndiaidh `a', `c', nó `i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "Níl fáilte roimh seoltaí le `}'" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr "Níl fáilte roimh seoltaí le `:'" #: sed/compile.c:171 msgid "comments don't accept any addresses" msgstr "níl fáilte roimh seoltaí le nótaí tráchta" #: sed/compile.c:172 msgid "missing command" msgstr "ordú ar iarraidh" #: sed/compile.c:173 msgid "command only uses one address" msgstr "ní úsáidtear an t-ordú ach seoladh amháin" #: sed/compile.c:174 msgid "unterminated address regex" msgstr "seoladh regex gan chríochnú" #: sed/compile.c:175 msgid "unterminated `s' command" msgstr "ordú `s' gan chríochnú" #: sed/compile.c:176 msgid "unterminated `y' command" msgstr "ordú `y' gan chríochnú" #: sed/compile.c:177 msgid "unknown option to `s'" msgstr "rogha anaithnid i ndiaidh `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "an iomarca roghanna `p' i ndiaidh `s'" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "an iomarca roghanna `g' i ndiaidh `s'" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "an iomarca roghanna uimhriúla i ndiaidh `s'" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "ní cheadaítear nialas mar rogha uimhriúil leis an ordú `s'" #: sed/compile.c:182 msgid "strings for `y' command are different lengths" msgstr "ní aon fad amháin ar na teaghráin leis an ordú `y'" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "tá an teorantóir ina charachtar ilbheart" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "bhíothas ag súil le leagan `sed' níos úire" #: sed/compile.c:185 msgid "invalid usage of line address 0" msgstr "ní féidir an seoladh líne 0 a úsáid" #: sed/compile.c:186 #, c-format msgid "unknown command: `%c'" msgstr "ordú anaithnid: `%c'" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: comhad %s líne %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e slonn #%lu, char %lu: %s\n" #: sed/compile.c:1644 #, c-format msgid "can't find label for jump to `%s'" msgstr "níl aon fháil ar an lipéad `%s' don léim" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: ní féidir %s a léamh: %s\n" # Irish is nice this way, no initial mutation on 'rud'! -- KPS # Include all three b/c I'm using template version of "Plural-Forms" #: sed/execute.c:673 #, c-format msgid "couldn't edit %s: is a terminal" msgstr "níorbh fhéidir %s a chur in eagar; is teirminéal é" #: sed/execute.c:677 #, c-format msgid "couldn't edit %s: not a regular file" msgstr "níorbh fhéidir %s a chur in eagar: ní gnáthcomhad é" #: sed/execute.c:684 lib/utils.c:196 #, c-format msgid "couldn't open temporary file %s: %s" msgstr "níorbh fhéidir an comhad sealadach %s a oscailt: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "earráid i bhfo-phróiseas" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "níl an rogha `e' ar fáil" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "níl an t-ordú `e' ar fáil" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "níl aon slonn ionadaíochta roimh seo" # bunathraitheoir is in FARF - KPS #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "ní féidir bunathraitheoirí a shonrú le slonn bán" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "tagairt neamhbhailí \\%d ar dheis ordú `s'" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " bain úsáid as sloinn ionadaíochta atá ag Perl 5.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" "Úsáid: %s [ROGHA]... {script-mura-bhfuil-script-eile} [inchomhad]...\n" "\n" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" " -n, --quiet, --silent\n" " stop priontáil uathoibríoch den spás patrúin\n" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" " -e script, --expression=script\n" " cuir an script leis na horduithe le rith\n" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" " -f comhad-script, --file=comhad-script\n" " cuir na línte i `comhad-script' leis na horduithe le rith\n" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" " -i[IARMHÍR], --in-place[=IARMHÍR]\n" " cuir eagar ar comhaid san áit a bhfuil siad (agus déan\n" " cúltaca má tá IARMHÍR tugtha\n" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" " -l N, --line-length=N\n" " ceap an fad timfhillte le haghaidh an ordaithe `l'\n" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" " --posix\n" " díchumasaigh gach feabhsúchán GNU.\n" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -r, --regexp-extended\n" " úsáid sloinn ionadaíochta feabhsaithe sa script.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" " -s, --separate\n" " féach ar comhaid ina leith seachas mar sruth leanúnach.\n" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" " -u, --unbuffered\n" " lódáil cantaí beaga ó na comhaid ionchur agus sruthlaigh\n" " na maoláin aschur níos minice\n" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr " --help taispeáin an chabhair seo agus éirigh as\n" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr " --version taispeáin eolas faoin leagan agus éirigh as\n" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" "\n" "Mura bhfuil rogha -e, --expression, -f, nó --file ann, glacfar an chéad\n" "argóint nach raibh ina rogha mar an script `sed' a léirmhíniú. Tá gach\n" "argóint eile an t-ainm de comhad ionchuir; mura bhfuil comhad ann\n" "léigh ón ionchur caighdeánach.\n" "\n" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Seol tuairiscí fabhtanna chuig: %s .\n" "Cuir an focal ``%s'' áit éigin sa líne ``Subject:'' le do thoil.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed, leagan %s\n" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "bunaithe ar GNU sed, leagan %s\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed, leagan %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Is saorbhogearra an ríomhchlár seo; féach ar an bhunchód le haghaidh\n" "coinníollacha cóipeála. Níl baránta AR BITH ann; go fiú níl baránta ann\n" "d'INDÍOLTACHT nó FEILIÚNACHT DO FHEIDHM AR LEITH, an oiread atá ceadaithe\n" "de réir dlí.\n" #: lib/utils.c:98 lib/utils.c:336 #, c-format msgid "cannot remove %s: %s" msgstr "ní féidir %s a scriosadh: %s" #: lib/utils.c:143 #, c-format msgid "couldn't open file %s: %s" msgstr "níorbh fhéidir an comhad %s a oscailt: %s" # Irish is nice this way, no initial mutation on 'rud'! -- KPS # Include all three b/c I'm using template version of "Plural-Forms" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "níorbh fhéidir %d rud a scríobh i %s: %s" msgstr[1] "níorbh fhéidir %d rud a scríobh i %s: %s" msgstr[2] "níorbh fhéidir %d rud a scríobh i %s: %s" msgstr[3] "níorbh fhéidir %d rud a scríobh i %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "earráid ag léamh %s: %s" #: lib/utils.c:341 #, c-format msgid "cannot rename %s: %s" msgstr "ní féidir %s a athainmniú: %s" #: lib/regcomp.c:132 msgid "Success" msgstr "Bua!" #: lib/regcomp.c:135 msgid "No match" msgstr "Níl a leithéid ann" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Slonn ionadaíochta neamhbhailí" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Carachtar cóimheasa neamhbhailí" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Aicme charachtair neamhbhailí" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Cúlslais ag deireadh" # coinage - KPS #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Cúltagairt neamhbhailí" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "[ nó [^ corr" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "( nó \\( corr" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "\\{ corr" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Ábhar neamhbhailí idir \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Deireadh raoin neamhbhailí" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Cuimhne ídithe" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Is neamhbhailí an slonn ionadaíochta roimh seo" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Deireadh le slonn ionadaíochta gan choinne" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Slonn ionadaíochta rómhór" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr ") nó \\) corr" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Níl aon slonn ionadaíochta roimh seo" kbuild-3686/src/oldsed/po/id.gmo0000664000175000017500000000755715053010106016500 0ustar locutuslocutus•Þ'T5Œ`\aº¾%yŸ¶ÐdíRf}š¶$Îó 1:#Y}˜ ³Å× éöB/r†#¤#È&ì,@Yn“„Z º s# . R r Z ©   2 R n' ƒ « à à í% ù  ? ^ e x  ¦ ½ Í éKSm"‰"¬!Ï/ñ!;[!"  ' # % &$ -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessexpected newer version of sedmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: sed 4.0.9 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2004-04-27 14:56+0700 Last-Translator: Tedi Heriyanto Language-Team: Indonesian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; X-Generator: KBabel 1.3 -R, --regexp-perl gunakan sintaks reguler ekspresi Perl 5 dalam skrip. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e ekspresi #%lu, char %lu: %s %s: tidak dapat membaca %s: %s %s: file %s baris %lu: %s : tidak menginginkan alamatEmail laporan kesalahan ke: %s Pastikan untuk menyertakan kata "%s" di field "Subject:". GNU sed versi %s Referensi balik tidak validNama kelas karakter tidak validKarakter kolasi tidak validIsi \{\} tidak validReguler ekspresi sebelumnya tidak validAkhir batas tidak validReguler ekspresi tidak validMemori habisTidak cocokTidak ada reguler ekspresi sebelumnyaAkhir reguler ekspresi prematurReguler ekspresi terlalu besarSuksesTrailing backslash( atau \( tidak sesuai) atau \) tidak sesuai[ atau [^ tidak sesuai\{ tidak sesuaiperintah `e' tidak didukung`}' tidak menginginkan alamattidak dapat menulis %d item ke %s: %stidak dapat menulis %d item ke %s: %skesalahan dalam subprosesmengharapkan versi baru sedopsion `g' ganda bagi perintah `s'opsion `p' ganda bagi perintah `s'opsion beragam untuk perintah `s'opsion angka untuk perintah `s' tidak boleh noloption `e' tidak didukungkesalahan pembacaan pada %s: %ssuper-sed versi %s kbuild-3686/src/oldsed/po/sl.po0000664000175000017500000002526615053010106016353 0ustar locutuslocutus# -*- mode:po; coding:iso-latin-2;-*- Slovenian message catalogue for GNU sed. # Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. # Primo¾ Peterlin , 2000, 2001, 2002, 2003. # msgid "" msgstr "" "Project-Id-Version: sed 4.0.6\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2003-04-02 17:20+0200\n" "Last-Translator: Primo¾ Peterlin \n" "Language-Team: Slovenian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-2\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n" "%100==4 ? 3 : 0);\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "Veèterni klicaji \"!\"" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "Neprièakovana vejica \",\"" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "Obliki +N in ~N nista dovoljeni kot zaèetna naslova" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "Oklepaj { brez zaklepaja" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "Neprièakovan zaklepaj }" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Ukazu sledijo dodatni znaki" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "Za ,a`, ,c` ali ,i` se prièakuje \\" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "Zaklepaj } ne zahteva naslova" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": ne zahteva naslova" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Komentarji ne sprejemajo naslovov" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Ukaz manjka" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Ukaz uporablja le en naslov" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Regularni izraz z nezakljuèenim naslovom" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Nezakljuèen ukaz \"s\"" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Nezakljuèen ukaz \"y\"" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Neznane izbire pri ukazu \"s\"" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "veèterne izbire \"p\" pri ukazu \"s\"" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "veèterne izbire \"g\" pri ukazu \"s\"" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "veèterne ¹tevilène izbire pri ukazu \"s\"" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "¹tevilèna izbira pri ukazu \"s\" mora biti nenièelna" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "niza pri ukazu \"y\" sta razlièno dolga" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "prièakovana novej¹a izdaja programa sed" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Nepravilna uporaba modifikatorja naslova" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Neznan ukaz:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: datoteka %s vrstica %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e izraz #%lu, znak %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Oznake za skok na \"%s\" ni mo¾no najti" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: %s ni mo¾no prebrati: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Datoteke %s ni mogoèe odpreti: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Datoteke %s ni mogoèe odpreti: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Datoteke %s ni mogoèe odpreti: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "Napaka v podprocesu" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "Izbira ,e` ni podprta" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "Ukaz ,e` ni podprt" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Prej¹nji regularni izraz manjka" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "Doloèanje modifikatorjev pri praznem regularnem izrazu ni mogoèe" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Neveljavni sklic \\%d na desni strani ukaza ,s`" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " dovoli uporabo regularnih izrazov, ki jih podpira Perl 5\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " dovoli uporabo regularnih izrazov, ki jih podpira Perl 5\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Sporoèila o napakah po¹ljite na %s .\n" "Poskrbite, da bo nekje v polju ,,Subject`` nastopal izraz ,,%s``.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed, razlièica %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "na osnovi GNU sed, razlièica 3.02.80\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed, razlièica %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "To je prost program; pogoji, pod katerimi ga lahko uporabljate, " "razmno¾ujete\n" "in raz¹irjate so navedeni v izvorni kodi. Za program ni NOBENEGA JAMSTVA,\n" "niti jamstev USTREZNOSTI ZA PRODAJO ali PRIMERNOSTI ZA UPORABO.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: %s ni mo¾no prebrati: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Datoteke %s ni mogoèe odpreti: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "ni mogoèe zapisati %d elementov na %s: %s" msgstr[1] "ni mogoèe zapisati %d elementa na %s: %s" msgstr[2] "ni mogoèe zapisati %d elementov na %s: %s" msgstr[3] "ni mogoèe zapisati %d elementov na %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "napaka pri branju z %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: %s ni mo¾no prebrati: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "Uspe¹no" #: lib/regcomp.c:135 msgid "No match" msgstr "Ni ujemanja" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Neveljavni regularni izraz" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Znaka izven abecede" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Neveljavno ime razreda znakov" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Zakljuèna obrnjena po¹evnica" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Neveljavni povratni sklic" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "Oklepaj [ ali [^ brez zaklepaja" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "Oklepaj ( ali \\( brez zaklepaja" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "Oklepaj \\{ brez zaklepaja" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Neveljavna vsebina \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Neveljavna zgornja meja intervala" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Zmanjkalo pomnilnika" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Neveljaven prej¹nji regularni izraz" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Predèasni zakljuèek regularnega izraza" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Regularni izraz prevelik" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "Oklepaj ) ali \\) brez zaklepaja" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Prej¹nji regularni izraz manjka" kbuild-3686/src/oldsed/po/en@boldquot.header0000664000175000017500000000247115053010106021014 0ustar locutuslocutus# All this catalog "translates" are quotation characters. # The msgids must be ASCII and therefore cannot contain real quotation # characters, only substitutes like grave accent (0x60), apostrophe (0x27) # and double quote (0x22). These substitutes look strange; see # http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html # # This catalog translates grave accent (0x60) and apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019). # It also translates pairs of apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019) # and pairs of quotation mark (0x22) to # left double quotation mark (U+201C) and right double quotation mark (U+201D). # # When output to an UTF-8 terminal, the quotation characters appear perfectly. # When output to an ISO-8859-1 terminal, the single quotation marks are # transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to # grave/acute accent (by libiconv), and the double quotation marks are # transliterated to 0x22. # When output to an ASCII terminal, the single quotation marks are # transliterated to apostrophes, and the double quotation marks are # transliterated to 0x22. # # This catalog furthermore displays the text between the quotation marks in # bold face, assuming the VT100/XTerm escape sequences. # kbuild-3686/src/oldsed/po/LINGUAS0000664000175000017500000000014315053010106016405 0ustar locutuslocutusaf ca cs da de el eo es et fi fr ga gl he hr hu id it ja ko nl pl pt_BR ro ru sk sl sr sv tr zh_CN kbuild-3686/src/oldsed/po/cs.po0000664000175000017500000002261315053010106016333 0ustar locutuslocutus# Czech translations for GNU sed package. # Copyright (C) 1998 Free Software Foundation, Inc. # Jaroslav Fojtik , 1998. # msgid "" msgstr "" "Project-Id-Version: sed 3.02.80\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2001-08-05 19:52+02:00\n" "Last-Translator: Vladimir Michl \n" "Language-Team: Czech \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-2\n" "Content-Transfer-Encoding: 8bit\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "Vícenásobný `!'" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "Neoèekáváná `,'" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "+N nebo ~N nelze pou¾ít jako první adresu" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "Neodpovídající `{'" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "Neoèekávaná `}'" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Nadbyteèné znaky po pøíkazu" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' nevy¾aduje jakoukoliv adresu" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": nechce jakoukoliv adresu" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "V komentáøi není pøípustná jakákoliv adresa" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Chybìjící pøíkaz" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Pøíkaz pou¾ívá pouze jedinou adresu" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Neukonèená adresa regulárního výrazu" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Neukonèený pøíkaz `s'" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Neukonèený pøíkaz `y'" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Neznámý pøepínaè pro `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "vícenásobné pou¾ití pøepínaèe `p' s pøíkazem `s'" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "vícenásobné pou¾ití pøepínaèe `g' s pøíkazem `s'" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "pøíkaz `s' mù¾e mít maximálnì jednu èíselnou volbu" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "èíselná volba pøíkazu `s' nemù¾e být nula" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "øetìzce pro pøíkaz `y' musí být stejnì dlouhé" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Chybné pou¾ití adresy modifikátoru" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Neznámý pøíkaz:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: soubor %s, øádek %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e výraz #%lu, znak %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Návì¹tí pro skok na `%s' nelze najít" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: %s nelze èíst: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Soubor %s nelze otevøít" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Soubor %s nelze otevøít" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Soubor %s nelze otevøít" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Chyby v programu oznamujte na adrese: %s (anglicky).\n" "Kamkoliv do polo¾ky ``Subject:'' vlo¾te ``%s''.\n" "Pøipomínky k pøekladu zasílejte na adresu (èesky).\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" " %s\n" " Toto je volné programové vybavení; podmínky pro kopírování a roz¹iøování\n" "naleznete ve zdrojových textech. Toto programové vybavení je zcela BEZ " "ZÁRUKY,\n" "a to i bez záruky PRODEJNOSTI nebo VHODNOSTI PRO NÌJAKÝ KONKRÉTNÍ ÚÈEL.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: %s nelze èíst: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Soubor %s nelze otevøít" #: lib/utils.c:220 #, fuzzy, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "%d polo¾ek nelze do %s zapsat: %s" msgstr[1] "%d polo¾ek nelze do %s zapsat: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "chyba pøi ètení z %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: %s nelze èíst: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "" #: lib/regcomp.c:135 msgid "No match" msgstr "" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "" #: lib/regcomp.c:153 #, fuzzy msgid "Unmatched [ or [^" msgstr "Neodpovídající `{'" #: lib/regcomp.c:156 #, fuzzy msgid "Unmatched ( or \\(" msgstr "Neodpovídající `{'" #: lib/regcomp.c:159 #, fuzzy msgid "Unmatched \\{" msgstr "Neodpovídající `{'" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "" #: lib/regcomp.c:180 #, fuzzy msgid "Unmatched ) or \\)" msgstr "Neodpovídající `{'" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "" kbuild-3686/src/oldsed/po/Makevars0000664000175000017500000000341615053010106017062 0ustar locutuslocutus# Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = $(PACKAGE) # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = Free Software Foundation, Inc. # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = kbuild-3686/src/oldsed/po/et.gmo0000664000175000017500000002137215053010106016503 0ustar locutuslocutus•ÞQ¤m,àúá,Ü5 7?\w`Ôu 5l «b V {Y Ò~ , «º ;% ö  3 Md j Ï ã ú3$Kp‚®·#Öú0BT fHs¼Öõ!5J(_ˆ#¦Ê$ê#)BM2à ×ø*5*`‹« »#É#í&8,W„-²àö* @Ng€p›Û 3è69SYTçl<m©PSha¼T‡s­û$©ÎèQg|­ÅÖô  .6Ts‘˜«»Ë ÛRå8Mb(‚«Ã3à3$Q-v¤!¾aà) B l# € ¤ Á( Ú,! !0 !Q !]!h!‚!œ!¼%!Ú""$"("M "d "q"~"’ "«"¶"Ê"Þ$DQ"!@=ELB5?43 .N;2(:9%< /CP',KM #6+017F H*->J O8& I)GA If no -e, --expression, -f, or --file option is given, then the first non-option argument is taken as the sed script to interpret. All remaining arguments are names of input files; if no input files are specified, then the standard input is read. --help display this help and exit --version output version information and exit --posix disable all GNU extensions. -R, --regexp-perl use Perl 5's regular expressions syntax in the script. -e script, --expression=script add the script to the commands to be executed -f script-file, --file=script-file add the contents of script-file to the commands to be executed -i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if extension supplied) -l N, --line-length=N specify the desired line-wrap length for the `l' command -n, --quiet, --silent suppress automatic printing of pattern space -r, --regexp-extended use extended regular expressions in the script. -s, --separate consider files as separate rather than as a single continuous long stream. -u, --unbuffered load minimal amounts of data from the input files and flush the output buffers more often %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]... `e' command not supported`}' doesn't want any addressesbased on GNU sed version %s can't find label for jump to `%s'cannot remove %s: %scannot rename %s: %scannot specify modifiers on empty regexpcommand only uses one addresscomments don't accept any addressescouldn't edit %s: is a terminalcouldn't edit %s: not a regular filecouldn't open file %s: %scouldn't open temporary file %s: %scouldn't write %d item to %s: %scouldn't write %d items to %s: %sdelimiter character is not a single-byte charactererror in subprocessexpected \ after `a', `c' or `i'expected newer version of sedextra characters after commandinvalid reference \%d on `s' command's RHSinvalid usage of +N or ~N as first addressinvalid usage of line address 0missing commandmultiple `!'smultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandno previous regular expressionnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %sstrings for `y' command are different lengthssuper-sed version %s unexpected `,'unexpected `}'unknown command: `%c'unknown option to `s'unmatched `{'unterminated `s' commandunterminated `y' commandunterminated address regexProject-Id-Version: sed 4.1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2004-07-09 16:33+0300 Last-Translator: Toomas Soome Language-Team: Estonian MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-15 Content-Transfer-Encoding: 8-bit Plural-Forms: nplurals=2; plural=(n != 1); Kui võtmeid -e, --expression, -f või --file ei kasutata, loetakse esimene argument, mis pole võti, sed skriptiks. Kõik järgnevad argumendid on sisendfailide nimed; kui sisendfaile ei antud, loetakse standardsisendit. --help väljast see abiinfo ja lõpeta töö --version väljasta versiooniinfo ja lõpeta töö --posix blokeeri kõik GNU laiendused. -R, --regexp-perl kasuta skriptis Perl 5 regulaaravaldiste süntaksit. -e skript, --expression=skript lisa täidetavate käskluste skript -f skripti-fail, --file=skripti-fail lisa skripti-faili sisu täidetavate käskluste hulka -i[SUFIKS], --in-place[=SUFIKS] toimeta faile (kui kasutati sifiksit, loob ka varukoopia) -l N, --line-length=N määra `l' käsule soovitatav rea pikkus -n, --quiet, --silent keela mustriruumi automaatne väljastamine -r, --regexp-extended kasuta skriptis laiendatud regulaaravaldiste süntaksit. -s, --separate käsitle faile ükshaaval, mitte ühe jätkuva voona. -u, --unbuffered loe sisendfailist minimaalne kogus andmeid ja tühjenda väljundpuhvreid sagedamini %s See on vaba tarkvara; kopeerimistingimused leiate lähtetekstidest. Garantii PUUDUB; ka müügiks või mingil eesmärgil kasutamiseks, vastavalt seadustega lubatud piiridele. %s: -e avaldis #%lu, sümbol %lu: %s %s: ei saa lugeda %s: %s %s: fail %s rida %lu: %s : ei vaja aadressePostitage teated vigadest: %s . Lisage kindlasti sõna ``%s'' ``Subject:'' reale. GNU sed versioon %s Vigane tagasi viideVigane sümbolite klassi nimiVigane sortimise sümbolVigane \{\} sisuVigane eelnev regulaaravaldisVigane vahemiku lõppVigane regulaaravaldisMälu on otsasEi leiaEelmist regulaaravaldist poleOotamatu regulaaravaldise lõppRegulaaravaldis on liiga suurEdukasLõpetav langkriipsPuudub ( või \(Puudub ) või \)Puudub [ või [^Puudub \{Kasutamine: %s [võti]... {ainult-skript-kui-teisi-skripte-pole} [sisend-fail]... käsku `e' ei toetata`}' ei vaja aadressepõhineb GNU sed versioonil %s ei leia märgendit, et hüpata kohale `%s'%s ei saa eemaldada: %s%s ei saa ümber nimetada: %smuudatusi tühjale regulaaravaldisele ei saa määratakäsk kasutab vaid üht aadressikommentaarid ei vaja aadresse%s ei saa toimetada: see on terminal%s ei saa toimetada: see ei ole tavaline failfaili %s ei saa avada: %sajutist faili %s ei saa avada: %s%d elemendi faili %s kirjutamine ebaõnnestus: %s%d elemendi faili %s kirjutamine ebaõnnestus: %seraldav sübol ei ole ühe-baidiline sümbolviga alamprotsessispeale `a', `c' või `i' peab olema \oodati sedi uuemat versioonilisasümbolid peale käskuvigane viide \%d käsu `s' paremas pooles+N või ~N ei või kasutada esimese aadressinavigane rea aadressi 0 kasutaminekäsk puudubkorduv `!'korduv `g' võti `s' käsuskorduv `p' võti `s' käsuskorduvad numbrivõtmed `s' käsuseelmist regulaaravaldist polenumbrivõti `s' käsus ei või olla nullvõtit `e' ei toetatalugemisviga %s: %ssõned käsus `y' on erineva pikkusegasuper-sed versioon %s ootamatu `,'ootamatu `}'tundmatu käsk: `%c'tundmatu võti `s' käsuleliigne `{'lõpetamata `s' käsklõpetamata `y' käsklõpetamata aadressi avaldiskbuild-3686/src/oldsed/po/ca.gmo0000664000175000017500000002275415053010106016463 0ustar locutuslocutus•ÞQ¤m,àúá,Ü5 7?\w`Ôu 5l «b V {Y Ò~ , «º ;% ö  3 Md j Ï ã ú3$Kp‚®·#Öú0BT fHs¼Öõ!5J(_ˆ#¦Ê$ê#)BM2à ×ø*5*`‹« »#É#í&8,W„-²àö* @Ng€a› ý7 :A@||½\:z—‘¤a2X”~í™lÉ(Ðù3mK¹%Ì"ò% ;'\„žº Ì%Ú"!#EJcz¤hµ  < V) s  ·6 Ó!! %!,'!R0!z$!«-!ÐW!þ3"V%"Š$"°%"Õ("û9#$0#^!# #± #¿'#Í'#õ.$%$L2$r$¥$Ã8$Þ%%, %;%I%a%}%%¦.%½$DQ"!@=ELB5?43 .N;2(:9%< /CP',KM #6+017F H*->J O8& I)GA If no -e, --expression, -f, or --file option is given, then the first non-option argument is taken as the sed script to interpret. All remaining arguments are names of input files; if no input files are specified, then the standard input is read. --help display this help and exit --version output version information and exit --posix disable all GNU extensions. -R, --regexp-perl use Perl 5's regular expressions syntax in the script. -e script, --expression=script add the script to the commands to be executed -f script-file, --file=script-file add the contents of script-file to the commands to be executed -i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if extension supplied) -l N, --line-length=N specify the desired line-wrap length for the `l' command -n, --quiet, --silent suppress automatic printing of pattern space -r, --regexp-extended use extended regular expressions in the script. -s, --separate consider files as separate rather than as a single continuous long stream. -u, --unbuffered load minimal amounts of data from the input files and flush the output buffers more often %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]... `e' command not supported`}' doesn't want any addressesbased on GNU sed version %s can't find label for jump to `%s'cannot remove %s: %scannot rename %s: %scannot specify modifiers on empty regexpcommand only uses one addresscomments don't accept any addressescouldn't edit %s: is a terminalcouldn't edit %s: not a regular filecouldn't open file %s: %scouldn't open temporary file %s: %scouldn't write %d item to %s: %scouldn't write %d items to %s: %sdelimiter character is not a single-byte charactererror in subprocessexpected \ after `a', `c' or `i'expected newer version of sedextra characters after commandinvalid reference \%d on `s' command's RHSinvalid usage of +N or ~N as first addressinvalid usage of line address 0missing commandmultiple `!'smultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandno previous regular expressionnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %sstrings for `y' command are different lengthssuper-sed version %s unexpected `,'unexpected `}'unknown command: `%c'unknown option to `s'unmatched `{'unterminated `s' commandunterminated `y' commandunterminated address regexProject-Id-Version: sed 4.1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2004-07-10 05:51+0200 Last-Translator: Jordi Mallach Language-Team: Catalan MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n!=1; Si no es donen cap de les opcions -e, --expression, -f o --file, el primer argument no-opció es pren com el script sed a interpretar. Tots els arguments restants són noms de fitxers d'entrada; si no s'especifiquen fitxers d'entrada, es llegeix l'entrada estàndard. --help mostra aquest missatge d'ajuda i surt --version mostra la informació de la versió i surt --posix inhabilita totes les extensions GNU. -R, --regexp-perl usa la sintaxi d'expressions regulars de Perl 5 en aquesta sequència. -e script, --expression=script afegeix el script a les ordres a executar -f fitxer-script, --file=fitxer-script afegeix els continguts de fitxer-script a les ordres a executar -i[SUFIX], --in-place[=SUFIX] edita els mateixos fitxers (fa còpia de seguretat si es proveeix una extensió) -l N, --line-length=N especifica la longitud desitjada per a l'ajust de final de línia per a l'ordre «l» -n, --quiet, --silent suprimeix la impressió automàtica de l'espai de patrons -r, --regexp-extended usa expressions regulars exteses en el script. -s, --separate considera els fitxers com independents, en compte d'un llarg flux continu. -u, --unbuffered carrega una quantitat mínima de dades dels fitxers d'entrada i buida els búfers d'eixida més sovint %s Aquest és programari lliure; vegeu el codi font per les condicions de còpia. No hi ha CAP garantia; ni tan sols de COMERCIABILITAT o ADEQUACIÓ A UN PROPÒSIT PARTICULAR, fins on ho permeta la llei. %s: -e expressió #%lu, caràcter %lu: %s %s: no es pot llegir %s: %s %s: fitxer %s línia %lu: %s : no accepta cap adreçaEnvieu informes d'error a: %s. Assegureu-vos d'incloure la paraula «%s» en alguna part del camp «Assumpte:». GNU sed versió %s La referència cap enrere no és vàlidaNom de classe de caràcter no vàlidEl caràcter de comparació no és vàlidEl contingut de \{\} no és vàlidL'expressió regular precedent no vàlidaEl rang final no és vàlidExpressió regular no vàlidaMemòria exhauridaSense parellaNo hi ha una expressió regular prèviaFi prematur de l'expressió regularL'expressió regular és massa granÈxitBarra invertida al final«(» o \( no emparellat) o \) no emparellat[ o [^ no emparellat\{ no emparellatForma d'ús: %s [OPCIÓ]... {script-només-si-no-hi-ha-altres-scripts} [fitxer-entrada]... l'ordre «e» no està suportada«}» no accepta cap adreçabasat en GNU sed versió %s no es troba l'etiqueta per al salt a «%s»no es pot eliminar %s: %sno es pot reanomenar %s: %sno es poden especificar modificadors en expregs buidesl'ordre utilitza només una adreçaels comentaris no accepten cap adreçano s'ha pogut editar %s: és un terminalno s'ha pogut editar %s: no és un fitxer regularno s'ha pogut obrir el fitxer %s: %sno s'ha pogut obrir el fitxer temporal %s: %sno s'ha pogut escriure %d element a %s: %sno s'han pogut escriure %d elements a %s: %sel caràcter delimitador no és un caràcter d'un bytes'ha produït un error en el subprocéss'espera \ després de «a», «c» i «i»s'esperava una versió més nova de sedhi ha caràcters extra després de l'ordrereferència \%d no vàlida en el costat dret de l'ordre «s»no es pot utilitzar +N o ~N com a primera adreçaús de l'adreça de línia 0 invàlidcal una ordremúltiples «!»múltiples opcions «g» per a l'ordre «s»múltiples opcions «p» per a l'ordre «s»múltiples opcions numèriques per a l'ordre «s»no hi ha una expressió regular prèvial'opció numèrica per a l'ordre «s» no pot ser zerol'opció «e» no està suportadaerror de lectura en %s: %sles cadenes per a l'ordre «y» són de longituds diferentssuper-sed versió %s «,» inesperada«}» inesperatordre desconeguda: «%c»opció desconeguda per a «s»«{» no emparellatordre «s» no terminadaordre «y» no terminadal'expressió regular d'adreça no està terminadakbuild-3686/src/oldsed/po/hu.po0000664000175000017500000002464715053010106016353 0ustar locutuslocutus# Hungarian translation of GNU sed # Copyright (C) 2002 Free Software Foundation, Inc. # Gábor István , 2002. # Mihály Gyulai , 2003. msgid "" msgstr "" "Project-Id-Version: sed 4.0.8\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2003-10-26 09:28+0100\n" "Last-Translator: Mihály Gyulai \n" "Language-Team: Hungarian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-2\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "Több `!'" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "Váratlan `,'" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "Nem lehet használni a +N-t vagy ~N-t elso címként" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "Nincs párban `{'" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "Nincs párban `}'" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Extra karakterek a parancs után " #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "`a', `c' vagy `i' parancs után \\ szükséges" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' nem igényel címzést" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": nem igényel címzést" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Megjegyzésben nem lehet címzés" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Hiányzó parancs" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "A parancs csak egy címzést használ" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Befejezetlen regex cím" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Befejezetlen `s' parancs" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Befejezetlen `y' parancs" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Ismeretlen `s' opció" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "többszörös `p' opció, `s' parancs mellett" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "többszörös `g' opció, `s' parancs mellett" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "többszörös szám opció, `s' parancs mellett" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "a(z) `s' parancs szám opciója nem lehet nulla" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "a(z) `y' parancs szövegeinek hossza különbözõ" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "a 'sed' program újabb verziójára van szükség" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "A parancs csak egy címzést használ" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Ismeretlen parancs:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: fájl %s sor %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e kifejezés #%lu, karakter %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Az ugráshoz (`%s') nem találom a címkét" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: nem lehet olvasni %s: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Nem lehet megnyitni a(z) %s fájlt: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Nem lehet megnyitni a(z) %s fájlt: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Nem lehet megnyitni az átmeneti fájlt: %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "hiba az alfolyamatban" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "az `e' opció nincs támogatva" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "az `e' parancs nincs támogatva" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Nincsen elõzõ reguláris kifejezés" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "Nem lehet módosítót megadni üres reguláris kifejezéshez" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Hibás hivatkozás (\\%d) a(z) `s' parancs RHS-ére" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R --regexp-perl\n" " Perl 5 reguláris kifejezés nyelvtanának használata.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R --regexp-perl\n" " Perl 5 reguláris kifejezés nyelvtanának használata.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "A fordítási hibákat kérem a gyulai@fbi.hu címre küldeni. \n" "Angolul ide: %s . A levél Tárgy mezejében legyen ott a `%s' szó.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed verzió %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "A GNU 3.02.80-as sed verzión alapszik\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed verzió %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Ez egy ingyenes számítógépes program. A forrásban megtalálhatók a másolás " "feltételei.\n" "SEMMILYEN garanciát nem vállalunk, még azt sem állítjuk, hogy ez a program\n" "KERESKEDELMI CÉLOKRA ALKALMAS vagy HASZNÁLHATÓ EGY ADOTT FELADATRA.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: nem lehet olvasni %s: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Nem lehet megnyitni a(z) %s fájlt: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "nem tudom a(z) %d elemet ide írni %s: %s" msgstr[1] "nem tudom a(z) %d elemeket ide írni %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "olvasási hiba %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: nem lehet olvasni %s: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "Sikeres" #: lib/regcomp.c:135 msgid "No match" msgstr "Nincs találat" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Hibás reguláris kifejezés" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Érvénytelen összehasonlító karakter" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Érvénytelen karakterosztály-név" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Lezáró visszaperjel" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Érvénytelen vissza-hivatkozás" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "Nincs párban [ vagy [^" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "Nincs párban ( vagy \\(" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "Nincs párban \\{" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "\\{\\}-nak érvénytelen a tartalma" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Sorozat érvénytelen vége" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Kevés a memória" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Érvénytelen megelõzõ reguláris kifejezés" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Reguláris kifejezés túl korai vége" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Túl nagy reguláris kifejezés" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "Nincs párban ) vagy \\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Nincsen elõzõ reguláris kifejezés" kbuild-3686/src/oldsed/po/insert-header.sin0000664000175000017500000000124015053010106020624 0ustar locutuslocutus# Sed script that inserts the file called HEADER before the header entry. # # At each occurrence of a line starting with "msgid ", we execute the following # commands. At the first occurrence, insert the file. At the following # occurrences, do nothing. The distinction between the first and the following # occurrences is achieved by looking at the hold space. /^msgid /{ x # Test if the hold space is empty. s/m/m/ ta # Yes it was empty. First occurrence. Read the file. r HEADER # Output the file's contents by reading the next line. But don't lose the # current line while doing this. g N bb :a # The hold space was nonempty. Following occurrences. Do nothing. x :b } kbuild-3686/src/oldsed/po/gl.po0000664000175000017500000002507215053010106016332 0ustar locutuslocutus# Galician translation of GNU sed # Copyright (C) 1999, 2002 Free Software Foundation, Inc. # Jacobo Tarrío Barreiro , 1999, 2002. # msgid "" msgstr "" "Project-Id-Version: sed 4.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2002-10-25 15:57+0200\n" "Last-Translator: Jacobo Tarrío Barreiro \n" "Language-Team: Galician \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n!=1;\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "Múltiples `!'s" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "`,' inesperada" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "Non se pode usar +N ou ~N como primeira dirección" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "`{' sen parella" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "`}' inesperado" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Caracteres extra despois da instrucción" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "Esperábase \\ despois de `a', `c' ou `i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' non acepta un enderezo" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": non acepta un enderezo" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Os comentarios non aceptan enderezos" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Falta unha instrucción" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "A instrucción só usa un enderezo" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Expresión regular de enderezo non rematada" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Instrucción `s' non rematada" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Instrucción `y' non rematada" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Opción de `s' descoñecida" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "múltiples opcións `p' para a instrucción `s'" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "múltiples opcións `g' para a instrucción `s'" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "múltiples opcións numéricas para a instrucción `s'" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "unha opción numérica para a instrucción `s' non pode ser cero" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "as cadeas para a instrucción y teñen lonxitudes diferentes" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Uso non válido de modificador de dirección" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Instrucción descoñecida:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: ficheiro %s liña %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e expresión #%lu, carácter %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Non se puido atopa-la etiqueta para saltar a `%s'" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: non se puido ler %s: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Non se puido abri-lo ficheiro %s: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Non se puido abri-lo ficheiro %s: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Non se puido abri-lo ficheiro %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "erro no subproceso" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "a opción `e' non está soportada" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "o comando `e' non está soportado" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Non hai unha expresión regular anterior" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "Non se poden especificar modificadores nunha expresión regular baleira" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Referencia \\%d non válida no lado dereito do comando `s'" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " usa-la sintaxe de expresións regulares de Perl 5 no " "script.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " usa-la sintaxe de expresións regulares de Perl 5 no " "script.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Informe dos erros no programa a %s .\n" "Informe dos erros na traducción a gpul-traduccion@ceu.fi.udc.es .\n" "Asegúrese de incluí-la palabra ``%s'' nalgunha parte do campo ``Subject:''.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed versión %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "baseado en GNU sed versión 3.02.80\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed versión %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Isto é software libre; vexa o código fonte polas condicións de copia. NON " "hai\n" "garantía; nin sequera de COMERCIABILIDADE ou APTITUDE PARA UN FIN " "DETERMINADO,\n" "ata o que permite a lei.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: non se puido ler %s: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Non se puido abri-lo ficheiro %s: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "non se puido escribir %d elemento en %s: %s" msgstr[1] "non se puideron escribir %d elementos en %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "erro de lectura en %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: non se puido ler %s: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "Éxito" #: lib/regcomp.c:135 msgid "No match" msgstr "Non se atopou" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Expresión regular non válida" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Carácter de ordeamento non válido" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Nome de clase de caracteres non válido" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Barra invertida á fin de liña" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Referencia cara a atrás non válida" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "[ ou [^ sen parella" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "( ou \\( sen parella" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "\\{ sen parella" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Contido de \\{\\} non válido" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Fin de rango non válida" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Memoria esgotada" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Expresión regular anterior non válida" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Fin prematura da expresión regular" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Expresión regular grande de máis" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr ") ou \\) sen parella" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Non hai unha expresión regular anterior" kbuild-3686/src/oldsed/po/ca.po0000664000175000017500000002757715053010106016327 0ustar locutuslocutus# Catalan translation of sed. # Copyright © 2002, 2003, 2004 Free Software Foundation, Inc. # This file is distributed under the same license as the sed package. # Jordi Mallach , 2002, 2003, 2004. # msgid "" msgstr "" "Project-Id-Version: sed 4.1.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2004-07-10 05:51+0200\n" "Last-Translator: Jordi Mallach \n" "Language-Team: Catalan \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n!=1;\n" #: sed/compile.c:162 msgid "multiple `!'s" msgstr "múltiples «!»" #: sed/compile.c:163 msgid "unexpected `,'" msgstr "«,» inesperada" #: sed/compile.c:164 msgid "invalid usage of +N or ~N as first address" msgstr "no es pot utilitzar +N o ~N com a primera adreça" #: sed/compile.c:165 msgid "unmatched `{'" msgstr "«{» no emparellat" #: sed/compile.c:166 msgid "unexpected `}'" msgstr "«}» inesperat" #: sed/compile.c:167 msgid "extra characters after command" msgstr "hi ha caràcters extra després de l'ordre" #: sed/compile.c:168 msgid "expected \\ after `a', `c' or `i'" msgstr "s'espera \\ després de «a», «c» i «i»" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "«}» no accepta cap adreça" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": no accepta cap adreça" #: sed/compile.c:171 msgid "comments don't accept any addresses" msgstr "els comentaris no accepten cap adreça" #: sed/compile.c:172 msgid "missing command" msgstr "cal una ordre" #: sed/compile.c:173 msgid "command only uses one address" msgstr "l'ordre utilitza només una adreça" #: sed/compile.c:174 msgid "unterminated address regex" msgstr "l'expressió regular d'adreça no està terminada" #: sed/compile.c:175 msgid "unterminated `s' command" msgstr "ordre «s» no terminada" #: sed/compile.c:176 msgid "unterminated `y' command" msgstr "ordre «y» no terminada" #: sed/compile.c:177 msgid "unknown option to `s'" msgstr "opció desconeguda per a «s»" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "múltiples opcions «p» per a l'ordre «s»" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "múltiples opcions «g» per a l'ordre «s»" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "múltiples opcions numèriques per a l'ordre «s»" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "l'opció numèrica per a l'ordre «s» no pot ser zero" #: sed/compile.c:182 msgid "strings for `y' command are different lengths" msgstr "les cadenes per a l'ordre «y» són de longituds diferents" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "el caràcter delimitador no és un caràcter d'un byte" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "s'esperava una versió més nova de sed" #: sed/compile.c:185 msgid "invalid usage of line address 0" msgstr "ús de l'adreça de línia 0 invàlid" #: sed/compile.c:186 #, c-format msgid "unknown command: `%c'" msgstr "ordre desconeguda: «%c»" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: fitxer %s línia %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e expressió #%lu, caràcter %lu: %s\n" #: sed/compile.c:1644 #, c-format msgid "can't find label for jump to `%s'" msgstr "no es troba l'etiqueta per al salt a «%s»" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: no es pot llegir %s: %s\n" #: sed/execute.c:673 #, c-format msgid "couldn't edit %s: is a terminal" msgstr "no s'ha pogut editar %s: és un terminal" #: sed/execute.c:677 #, c-format msgid "couldn't edit %s: not a regular file" msgstr "no s'ha pogut editar %s: no és un fitxer regular" #: sed/execute.c:684 lib/utils.c:196 #, c-format msgid "couldn't open temporary file %s: %s" msgstr "no s'ha pogut obrir el fitxer temporal %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "s'ha produït un error en el subprocés" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "l'opció «e» no està suportada" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "l'ordre «e» no està suportada" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 msgid "no previous regular expression" msgstr "no hi ha una expressió regular prèvia" #: sed/regexp.c:40 msgid "cannot specify modifiers on empty regexp" msgstr "no es poden especificar modificadors en expregs buides" #: sed/regexp.c:115 #, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "referència \\%d no vàlida en el costat dret de l'ordre «s»" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " usa la sintaxi d'expressions regulars de Perl 5 en aquesta\n" " sequència.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" "Forma d'ús: %s [OPCIÓ]... {script-només-si-no-hi-ha-altres-scripts}\n" " [fitxer-entrada]...\n" "\n" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" " -n, --quiet, --silent\n" " suprimeix la impressió automàtica de l'espai de patrons\n" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" " -e script, --expression=script\n" " afegeix el script a les ordres a executar\n" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" " -f fitxer-script, --file=fitxer-script\n" " afegeix els continguts de fitxer-script a les ordres a " "executar\n" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" " -i[SUFIX], --in-place[=SUFIX]\n" " edita els mateixos fitxers (fa còpia de seguretat si es\n" " proveeix una extensió)\n" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" " -l N, --line-length=N\n" " especifica la longitud desitjada per a l'ajust de final de\n" " línia per a l'ordre «l»\n" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" " --posix\n" " inhabilita totes les extensions GNU.\n" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -r, --regexp-extended\n" " usa expressions regulars exteses en el script.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" " -s, --separate\n" " considera els fitxers com independents, en compte d'un\n" " llarg flux continu.\n" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" " -u, --unbuffered\n" " carrega una quantitat mínima de dades dels fitxers " "d'entrada\n" " i buida els búfers d'eixida més sovint\n" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr " --help mostra aquest missatge d'ajuda i surt\n" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr " --version mostra la informació de la versió i surt\n" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" "\n" "Si no es donen cap de les opcions -e, --expression, -f o --file, el primer\n" "argument no-opció es pren com el script sed a interpretar. Tots els " "arguments\n" "restants són noms de fitxers d'entrada; si no s'especifiquen fitxers " "d'entrada,\n" "es llegeix l'entrada estàndard.\n" "\n" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Envieu informes d'error a: %s.\n" "Assegureu-vos d'incloure la paraula «%s» en alguna part del camp " "«Assumpte:».\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed versió %s\n" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "basat en GNU sed versió %s\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed versió %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Aquest és programari lliure; vegeu el codi font per les condicions\n" "de còpia. No hi ha CAP garantia; ni tan sols de COMERCIABILITAT o\n" "ADEQUACIÓ A UN PROPÒSIT PARTICULAR, fins on ho permeta la llei.\n" #: lib/utils.c:98 lib/utils.c:336 #, c-format msgid "cannot remove %s: %s" msgstr "no es pot eliminar %s: %s" #: lib/utils.c:143 #, c-format msgid "couldn't open file %s: %s" msgstr "no s'ha pogut obrir el fitxer %s: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "no s'ha pogut escriure %d element a %s: %s" msgstr[1] "no s'han pogut escriure %d elements a %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "error de lectura en %s: %s" #: lib/utils.c:341 #, c-format msgid "cannot rename %s: %s" msgstr "no es pot reanomenar %s: %s" #: lib/regcomp.c:132 msgid "Success" msgstr "Èxit" #: lib/regcomp.c:135 msgid "No match" msgstr "Sense parella" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Expressió regular no vàlida" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "El caràcter de comparació no és vàlid" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Nom de classe de caràcter no vàlid" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Barra invertida al final" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "La referència cap enrere no és vàlida" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "[ o [^ no emparellat" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "«(» o \\( no emparellat" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "\\{ no emparellat" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "El contingut de \\{\\} no és vàlid" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "El rang final no és vàlid" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Memòria exhaurida" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "L'expressió regular precedent no vàlida" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Fi prematur de l'expressió regular" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "L'expressió regular és massa gran" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr ") o \\) no emparellat" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "No hi ha una expressió regular prèvia" kbuild-3686/src/oldsed/po/sr.po0000664000175000017500000002775415053010106016365 0ustar locutuslocutus# Serbian translation of `sed'. # Copyright (C) 2003 Free Software Foundation, Inc. # This file is distributed under the same license as the `sed' package. # Aleksandar Jelenak , 2003. msgid "" msgstr "" "Project-Id-Version: sed 4.0.9\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2004-01-13 22:51-0500\n" "Last-Translator: Aleksandar Jelenak \n" "Language-Team: Serbian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : (n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "Више „!“" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "Ðеочекиван „,“" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "Ðе може Ñе кориÑтити +N или ~N као прва адреÑа" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "ÐеÑпарена „{“" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "Ðеочекивана „}“" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Вишак знакова поÑле наредбе" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "Очекивано \\ поÑле „a“, „c“ или „i“" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "„}“ не захтева икакве адреÑе" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": не захтева икакве адреÑе" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Коментари не прихватају икакве адреÑе" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "ÐедоÑтаје наредба" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Ðаредба кориÑти Ñамо једну адреÑу" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Ðезавршена адреÑа рег. израза" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Ðезавршена наредба „s“" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Ðезавршена наредба „y“" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Ðепозната опција за „s“" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "више „p“ опција за „s“ наредбу" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "више „g“ опција за „s“ наредбу" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "више бројчаних опција за „s“ наредбу" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "бројчана опција наредбе „s“ не може бити нула" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "ниÑке за команду „y“ Ñу различите дужине" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "очекивана новија верзија sed-а" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Ðаредба кориÑти Ñамо једну адреÑу" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Ðепозната наредба:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: датотека %s ред %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e израз #%lu, знак %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Ðе могу да нађем ознаку за Ñкок на „%s“" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: не може читати %s: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Ðе може Ñе отворити датотека %s: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Ðе може Ñе отворити датотека %s: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Ðе могу отворити привремену датотеку %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "грешка у потпроцеÑу" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "опција „e“ није подржана" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "наредба „e“ није подржана" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Без претходног регуларног израза" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "Ðе може Ñе навеÑти измењивач празном рег. изразу" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "ÐеиÑправна референца \\%d на деÑној Ñтрани наредбе „s“" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " кориÑти у ÑпиÑу ÑинтакÑу Перла 5 за регуларне изразе.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " кориÑти у ÑпиÑу ÑинтакÑу Перла 5 за регуларне изразе.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Епошта за пријаву грешака: %s .\n" "ПоÑтарајте Ñе да укључите реч „%s“ негде у „Subject:“ пољу.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed верзија %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "заÑновано на ГÐУ sed верзија 3.02.80\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "ГÐУ sed верзија %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Ово је Ñлободан Ñофтвер; видети изворни кôд за уÑлове умножавања. БЕЗ " "икакве\n" "гаранције; чак ни о ТРЖИШÐОСТИ или ИСПУЊÐÐ’ÐЊУ ОДРЕЂЕÐЕ ПОТРЕБЕ.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: не може читати %s: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Ðе може Ñе отворити датотека %s: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "неуÑпешан Ð·Ð°Ð¿Ð¸Ñ %d Ñтавке на %s: %s" msgstr[1] "неуÑпешан Ð·Ð°Ð¿Ð¸Ñ %d Ñтавке на %s: %s" msgstr[2] "неуÑпешан Ð·Ð°Ð¿Ð¸Ñ %d Ñтавки на %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "грешка учитавања на %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: не може читати %s: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "УÑпех" #: lib/regcomp.c:135 msgid "No match" msgstr "Без поклапања" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "ÐеиÑправни регуларни израз" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "ÐеиÑправни знак прикупљања" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "ÐеиÑправно име клаÑе знакова" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Пратећа обрнута коÑа црта" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "ÐеиÑправна повратна референца" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "ÐеÑпарено [ или ^[" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "ÐеÑпарено ( или \\(" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "ÐеÑпарено \\{" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "ÐеиÑправни Ñадржај у \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "ÐеиÑправни крај опÑега" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Меморија иÑцрпљена" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "ÐеиÑправан претходећи регуларни израз" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Преран крај регуларног израза" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Регуларни израз Ñувише велик" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "ÐеÑпарено ) или \\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Без претходног регуларног израза" kbuild-3686/src/oldsed/po/eo.gmo0000664000175000017500000000742415053010106016500 0ustar locutuslocutus•Þ'T5Œ`\aº¾%yŸ¶ÐdíRf}š¶$Îó 1:#Y}˜ ³Å× éöB/r†#¤#È&ì,@YnŽ„^ ¹ r# , P j ˆQ ž ð   7 O g ‡ µ à Ì! ê  & . G [ o ƒ ‘ ªD  !<!^$€.¥Ôëÿ!"  ' # % &$ -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessexpected newer version of sedmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: GNU sed 4.0.8 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2003-10-26 20:57+0000 Last-Translator: Edmund GRIMLEY EVANS Language-Team: Esperanto MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8-bit Plural-Forms: nplurals=2; plural=(n != 1); -R, --regexp-perl uzi sintakso de Perl 5 por regulaj esprimoj en programo. %s Ĉi tio estas libera programo; vidu la fonton por kopi-kondiĉoj. Estas NENIA GARANTIO; eĉ ne por KOMERCA KVALITO aÅ­ ADEKVATECO POR DIFINITA CELO, laÅ­ la grado permesita de juro. %s: -e esprimo #%lu, signo %lu: %s %s: ne povas legi %s: %s %s: dosiero %s linio %lu: %s : ne deziras adresojnRetpoÅtu cimo-raportojn al: %s . Nepre menciu la vorton '%s' ie en la temlinio. GNU sed versio %s Nevalida retroreferencoNevalida nomo de signoklasoNevalida kunfanda signoNevalida enhavo de \{\}Nevalida antaÅ­a regula esprimoNevalida fino de gamoNevalida regula esprimoMankas memoroMaltrafoMankas antaÅ­a regula esprimoNeatendita fino de regula esprimoRegula esprimo tro grandaSukcesoMalsuprenstreko ĉe finoNeparigita ( aÅ­ \(Neparigita ) aÅ­ \)Neparigita [ aÅ­ [^Neparigita \{komando 'e' ne realigita'}' ne deziras adresojnne povis skribi %d eron al %s: %sne povis skribi %d erojn al %s: %seraro en subprocezoatendis pli novan version de sedpluraj 'g'-opcioj por komando 's'pluraj 'p'-opcioj por komando 's'pluraj nombro-opcioj por komando 's'nombro-opcio por komando 's' ne povas esti nulopcio 'e' ne realigitalegeraro ĉe %s: %ssuper-sed versio %s kbuild-3686/src/oldsed/po/es.po0000664000175000017500000002514115053010106016334 0ustar locutuslocutus# Mensajes en español para GNU sed. # Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. # Cristian Othón Martínez Vera , 2001, 2002, 2003. # msgid "" msgstr "" "Project-Id-Version: sed 4.0.8\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2003-10-24 12:38-0500\n" "Last-Translator: Cristian Othón Martínez Vera \n" "Language-Team: Spanish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "'!'s múltiples" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "`,' inesperada" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "No se pueden usar +N o ~N como primera dirección" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "`{' sin pareja" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "`}' inesperado" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Caracteres extra después de la orden" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "Se esperaba \\ después de `a', `c' ó `i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "`}' no acepta ninguna dirección" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": no acepta ninguna dirección" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Los comentarios no aceptan ninguna dirección" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Orden faltante" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "La orden solamente usa una dirección" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Dirección de expresión regular sin terminar" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Orden `s' sin terminar" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Orden `y' sin terminar" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Opción desconocida para `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "múltiples opciones `p' para la orden `s'" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "múltiples opciones `g' para la orden `s'" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "múltiples opciones numéricas para la orden `s'" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "una opción numérica para la orden `s' no puede ser cero" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "las cadenas para la orden y son de longitudes diferentes" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "se esperaba una versión más reciente de sed" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Uso inválido de un modificador de dirección" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Orden desconocida:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: fichero %s línea %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e expresión #%lu, carácter %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "No se puede encontrar la etiqueta para saltar a `%s'" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: no se puede leer %s: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "No se puede abrir el fichero %s: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "No se puede abrir el fichero %s: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "No se puede abrir el fichero temporal %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "error en el subproceso" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "no hay soporte para la opción `e'" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "no hay soporte para el comando `e'" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "No hay una expresión regular previa" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "No se pueden especificar modificadores en expresiones regulares vacías" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Referencia \\%d inválida en el lado derecho del comando `s'" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " utilizar la sintaxis de expresiones regulares de Perl 5\n" " en el guión.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " utilizar la sintaxis de expresiones regulares de Perl 5\n" " en el guión.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "Envíe reportes de bichos por e-mail a: %s .\n" "Asegúrese de incluir la palabra ``%s'' en algún lugar en el campo " "``Subject:''.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed versión %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "basado en GNU sed versión 3.02.80\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed versión %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Esto es software libre; vea el código fuente para las condiciones de copia.\n" "No hay NINGUNA garantía; ni siquiera de COMERCIABILIDAD o IDONEIDAD PARA UN\n" "FIN DETERMINADO, en la extensión permitida por ley.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: no se puede leer %s: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "No se puede abrir el fichero %s: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "no se puede escribir %d elemento a %s: %s" msgstr[1] "no se pueden escribir %d elementos a %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "error al leer de %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: no se puede leer %s: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "Éxito" #: lib/regcomp.c:135 msgid "No match" msgstr "No hay coincidencia" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Expresion regular inválida" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Carácter de ordenamiento inválido" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Carácter de nombre de clase inválido" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Diagonal invertida al final" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Referencia hacia atrás inválida" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "[ ó [^ sin pareja" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "( ó \\( sin pareja" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "\\{ sin pareja" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Contenido inválido de \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Final de rango inválido" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Memoria agotada" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Expresión regular precedente inválida" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Final prematuro de la expresión regular" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Expresión regular demasiado grande" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr ") ó \\) sin pareja" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "No hay una expresión regular previa" kbuild-3686/src/oldsed/po/el.po0000664000175000017500000002437715053010106016337 0ustar locutuslocutus# Greek messages for GNU sed. # Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. # Simos Xenitellis , 1998, 1999, 2000, 2001, 2002. # msgid "" msgstr "" "Project-Id-Version: GNU sed 3.02.80\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2002-03-08 12:57+0000\n" "Last-Translator: Simos Xenitellis \n" "Language-Team: Greek \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-7\n" "Content-Transfer-Encoding: 8bit\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "ÐïëëáðëÜ `!'s" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "ÁíáðÜíôå÷ï `,'" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "Äåí åßíáé äõíáôÞ ç ÷ñÞóç ôùí +N Þ ~N ãéá ðñþôç äéåýèõíóç" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "Áôáßñéáóôï `{'" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "Áôáßñéáóôï `}'" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "ÅðéðëÝïí ÷áñáêôÞñåò ìåôÜ ôçí åíôïëÞ" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "Áðáéôåßôáé \\ ìåôÜ ôéò åíôïëÝò `a', `c' Þ `i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "ôï `}' äåí ÷ñåéÜæåôáé äéåõèýíóåéò" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": äåí ÷ñåéÜæåôáé äéåõèýíóåéò" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Ôá ó÷üëéá äåí äÝ÷ïíôáé äéåõèýíóåéò" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Ëåßðåé ç åíôïëÞ" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Ç åíôïëÞ ÷ñçóéìïðïéåß ìüíï ìéá äéåýèõíóç" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Ìç ôåñìáôéóìÝíç äéåýèõíóç êáíïíéêÞò Ýêöñáóçò" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Ìç ôåñìáôéóìÝíç åíôïëÞ `s'" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Ìç ôåñìáôéóìÝíç åíôïëÞ `y'" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "¶ãíùóôç åðéëïãÞ ãéá ôï `s'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "ðïëëáðëÝò åðéëïãÝò `p' óôçí åíôïëÞ `s'" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "ðïëëáðëÝò åðéëïãÝò `g' óôçí åíôïëÞ `s'" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "ðïëëáðëüò åðéëïãÝò áñéèìïý óôçí åíôïëÞ `s'" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "ç åðéëïãÞ áñéèìïý óôçí åíôïëÞ `s' äåí ìðïñåß íá åßíáé ìçäÝí" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "ôá áëöáñéèìçôéêÜ ãéá ôçí åíôïëÞ `y' åßíáé äéáöïñåôéêïý ìåãÝèïõò" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "ÁêáôÜëëçëç ÷ñÞóç ôïõ äéáìïñöùôÞ äéåýèõíóçò" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "¶ãíùóôç åíôïëÞ:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: áñ÷åßï %s ãñáììÞ %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e Ýêöñáóç #%lu, ÷áñáêôÞñáò %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Äåí Þôáí äõíáôÞ ç åýñåóç åôéêÝôôáò ãéá ìåôÜâáóç óôï `%s'" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: áäõíáìßá óôçí áíÜãíùóç %s: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Äåí ìðüñåóá íá áíïßîù ôï áñ÷åßï %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Äåí ìðüñåóá íá áíïßîù ôï áñ÷åßï %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Äåí ìðüñåóá íá áíïßîù ôï áñ÷åßï %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "óöÜëìá óôç õðïäéáäéêáóßá" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "äåí õðïóôçñßæåôáé ç åðéëïãÞ `e'" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "äåí õðïóôçñßæåôáé ç åíôïëÞ `e'" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Äåí âñÝèçêå ðñïçãïýìåíç êáíïíéêÞ Ýêöñáóç" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "äåí åðéôñÝðåôáé ï ïñéóìüò äéáìïñöùôþí óå êåíÞ êáíïíéêÞ Ýêöñáóç" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Ìç Ýãêõñç áíáöïñÜ \\%d óôï äåîß ôìÞìá ôçò åíôïëÞò `s'" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "ÁíáöïñÝò óöáëìÜôùí ìÝóù çëåêôñïíéêïý ôá÷õäñïìåßïõ óôï: %s .\n" "ÐñïóÝîôå íá óõìðåñéëÜâåôå ôç ëÝîç ``%s'' êÜðïõ óôï ðåäßï ``Subject:''.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "" #: sed/sed.c:269 #, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Áõôü ôï ðñüãñáììá åßíáé åëåýèåñï ëïãéóìéêü· äåßôå ôïí ðçãáßï êþäéêá ãéá " "ôïõò\n" "êáíïíéóìïýò áíôéãñáöÞò. Äåí õðÜñ÷åé ÊÁÌÉÁ ÅÃÃÕÇÓÇ· ïýôå áêüìá ãéá\n" "ËÅÉÔÏÕÑÃÉÊÏÔÇÔÁ Þ ÊÁÔÁËËÇËÏÔÇÔÁ ÃÉÁ ÅÍÁ ÓÕÃÊÅÊÑÉÌÅÍÏ ÓÊÏÐÏ, ìÝ÷ñé ôï óçìåßï\n" "ðïõ åðéôñÝðåé ï íüìïò.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: áäõíáìßá óôçí áíÜãíùóç %s: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Äåí ìðüñåóá íá áíïßîù ôï áñ÷åßï %s" #: lib/utils.c:220 #, fuzzy, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "áäýíáôç ç åããñáöÞ %d óôïé÷åßùí óôï %s: %s" msgstr[1] "áäýíáôç ç åããñáöÞ %d óôïé÷åßùí óôï %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "óöÜëìá áíÜãíùóçò óôï %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: áäõíáìßá óôçí áíÜãíùóç %s: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "" #: lib/regcomp.c:135 msgid "No match" msgstr "" #: lib/regcomp.c:138 #, fuzzy msgid "Invalid regular expression" msgstr "Äåí âñÝèçêå ðñïçãïýìåíç êáíïíéêÞ Ýêöñáóç" #: lib/regcomp.c:141 #, fuzzy msgid "Invalid collation character" msgstr "ìç Ýãêõñï áêïëïõèßá äéáöõãÞò óå êëÜóç ÷áñáêôÞñùí" #: lib/regcomp.c:144 #, fuzzy msgid "Invalid character class name" msgstr "ìç Ýãêõñï áêïëïõèßá äéáöõãÞò óå êëÜóç ÷áñáêôÞñùí" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "" #: lib/regcomp.c:153 #, fuzzy msgid "Unmatched [ or [^" msgstr "Áôáßñéáóôï `{'" #: lib/regcomp.c:156 #, fuzzy msgid "Unmatched ( or \\(" msgstr "Áôáßñéáóôï `{'" #: lib/regcomp.c:159 #, fuzzy msgid "Unmatched \\{" msgstr "Áôáßñéáóôï `{'" #: lib/regcomp.c:162 #, fuzzy msgid "Invalid content of \\{\\}" msgstr "ìç Ýãêõñï ðåñéå÷üìåíï äåéêôþí åðáíÜëçøçò {}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "" #: lib/regcomp.c:171 #, fuzzy msgid "Invalid preceding regular expression" msgstr "Äåí âñÝèçêå ðñïçãïýìåíç êáíïíéêÞ Ýêöñáóç" #: lib/regcomp.c:174 #, fuzzy msgid "Premature end of regular expression" msgstr "Äåí âñÝèçêå ðñïçãïýìåíç êáíïíéêÞ Ýêöñáóç" #: lib/regcomp.c:177 #, fuzzy msgid "Regular expression too big" msgstr "ðïëý ìåãÜëç êáíïíéêÞ Ýêöñáóç" #: lib/regcomp.c:180 #, fuzzy msgid "Unmatched ) or \\)" msgstr "Áôáßñéáóôï `{'" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Äåí âñÝèçêå ðñïçãïýìåíç êáíïíéêÞ Ýêöñáóç" kbuild-3686/src/oldsed/po/de.gmo0000664000175000017500000001020315053010106016452 0ustar locutuslocutus•Þ'T5Œ`\aº¾%yŸ¶ÐdíRf}š¶$Îó 1:#Y}˜ ³Å× éöB/r†#¤#È&ì,@Yn`„_ å E& Ö ý  6} R Ð ä   :* T  – ´ Ç" Ý ! @Lfœ·#ËïQ ]r"’"µ)Ø3!6Xm!"  ' # % &$ -R, --regexp-perl use Perl 5's regular expressions syntax in the script. %s This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. %s: -e expression #%lu, char %lu: %s %s: can't read %s: %s %s: file %s line %lu: %s : doesn't want any addressesE-mail bug reports to: %s . Be sure to include the word ``%s'' somewhere in the ``Subject:'' field. GNU sed version %s Invalid back referenceInvalid character class nameInvalid collation characterInvalid content of \{\}Invalid preceding regular expressionInvalid range endInvalid regular expressionMemory exhaustedNo matchNo previous regular expressionPremature end of regular expressionRegular expression too bigSuccessTrailing backslashUnmatched ( or \(Unmatched ) or \)Unmatched [ or [^Unmatched \{`e' command not supported`}' doesn't want any addressescouldn't write %d item to %s: %scouldn't write %d items to %s: %serror in subprocessexpected newer version of sedmultiple `g' options to `s' commandmultiple `p' options to `s' commandmultiple number options to `s' commandnumber option to `s' command may not be zerooption `e' not supportedread error on %s: %ssuper-sed version %s Project-Id-Version: sed 4.0.6 Report-Msgid-Bugs-To: POT-Creation-Date: 2006-02-03 10:26+0100 PO-Revision-Date: 2003-03-21 22:03:41+0100 Last-Translator: Walter Koch Language-Team: German MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); -R, --regexp-perl Verwende die Perl 5 - Syntax für reg.Ausdrücke im Script. %s (Der folgende Text ist eine nicht überprüfte Übersetzung, die zur Information dient; in rechtlichen Fragen ist immer das englische Original ausschlaggebend) Dieses Program ist freie Software; In den Quelldateien können Sie die Bedingungen für die Weitergabe nachlesen. Es gibt KEINE GARANTIE; nicht einmal die implizite Garantie der MARKTFÄHIGKEIT oder der ERFÜLLUNG EINES BESTIMMTEN ZWECKES. %s: -e Ausdruck #%lu, Zeichen %lu: %s %s: kann %s nicht lesen: %s %s: Datei %s Zeile %lu: %s `:' erwartet keine AdressenFehlerberichte (in Englisch!) per E-Mail an: %s . Verwenden Sie dabei den Begriff ``%s'' irgendwo in der ``Betreff:''-Zeile. GNU sed Version %s Ungültiger RückwärtsverweisUngültige ZeichenklassennameUngültiger VergleichszeichenUngültiger Inhalt in \{\}Vorheriger regulärer Ausdruck ist ungültigUngültiges BereichendeUngültiger regulärer AusdruckSpeicher erschöpftKeine ÜbereinstimmungKein vorheriger regulärer AusdruckRegulärer Ausdruck endet zu frühRegulärer Ausdruck ist zu großErfolgreichAbschliessender BackslashNicht paarweises ( bzw. \(Nicht paarweises ) bzw. \)Nicht paarweises [ bzw. [^Nicht paarweises \{`e'-Kommando wird nicht unterstützt`}' erwartet keine AdressenKann %d Feld nicht auf %s schreiben: %sKann %d Felder nicht auf %s schreiben: %sFehler im SubprozessNeuere Version von sed erwartetMehrere 'g'-Optionen am `s'-BefehlMehrere 'p'-Optionen am `s'-BefehlMehrere numerische Optionen am `s'-BefehlNumerisch Option am `s'-Befehl darf nicht Null seinOption `e' wird nicht unterstütztLesefehler in %s: %sSuper-sed version %s kbuild-3686/src/oldsed/po/eo.po0000664000175000017500000002422215053010106016327 0ustar locutuslocutus# Esperantaj mesaÄoj por GNU sed. # Copyright (C) 2002 Free Software Foundation, Inc. # Edmund GRIMLEY EVANS , 2001-2003. # msgid "" msgstr "" "Project-Id-Version: GNU sed 4.0.8\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-02-03 10:26+0100\n" "PO-Revision-Date: 2003-10-26 20:57+0000\n" "Last-Translator: Edmund GRIMLEY EVANS \n" "Language-Team: Esperanto \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: sed/compile.c:162 #, fuzzy msgid "multiple `!'s" msgstr "Pluraj '!'oj" #: sed/compile.c:163 #, fuzzy msgid "unexpected `,'" msgstr "Neatendita ','" #: sed/compile.c:164 #, fuzzy msgid "invalid usage of +N or ~N as first address" msgstr "Ne eblas uzi +N aÅ­ ~N kiel unuan adreson" #: sed/compile.c:165 #, fuzzy msgid "unmatched `{'" msgstr "Neparigita '{'" #: sed/compile.c:166 #, fuzzy msgid "unexpected `}'" msgstr "Neatendita '}'" #: sed/compile.c:167 #, fuzzy msgid "extra characters after command" msgstr "Kromaj signoj post komando" #: sed/compile.c:168 #, fuzzy msgid "expected \\ after `a', `c' or `i'" msgstr "Atendita \\ post 'a', 'c' aÅ­ 'i'" #: sed/compile.c:169 msgid "`}' doesn't want any addresses" msgstr "'}' ne deziras adresojn" #: sed/compile.c:170 msgid ": doesn't want any addresses" msgstr ": ne deziras adresojn" #: sed/compile.c:171 #, fuzzy msgid "comments don't accept any addresses" msgstr "Komentoj ne akceptas adresojn" #: sed/compile.c:172 #, fuzzy msgid "missing command" msgstr "Mankas komando" #: sed/compile.c:173 #, fuzzy msgid "command only uses one address" msgstr "Komando uzas nur unu adreson" #: sed/compile.c:174 #, fuzzy msgid "unterminated address regex" msgstr "Nefinita adresa regesp" #: sed/compile.c:175 #, fuzzy msgid "unterminated `s' command" msgstr "Nefinita komando 's'" #: sed/compile.c:176 #, fuzzy msgid "unterminated `y' command" msgstr "Nefinita komando 'y'" #: sed/compile.c:177 #, fuzzy msgid "unknown option to `s'" msgstr "Nekonata opcio por 's'" #: sed/compile.c:178 msgid "multiple `p' options to `s' command" msgstr "pluraj 'p'-opcioj por komando 's'" #: sed/compile.c:179 msgid "multiple `g' options to `s' command" msgstr "pluraj 'g'-opcioj por komando 's'" #: sed/compile.c:180 msgid "multiple number options to `s' command" msgstr "pluraj nombro-opcioj por komando 's'" #: sed/compile.c:181 msgid "number option to `s' command may not be zero" msgstr "nombro-opcio por komando 's' ne povas esti nul" #: sed/compile.c:182 #, fuzzy msgid "strings for `y' command are different lengths" msgstr "ĉenoj por komando 'y' havas malsamajn longojn" #: sed/compile.c:183 msgid "delimiter character is not a single-byte character" msgstr "" #: sed/compile.c:184 msgid "expected newer version of sed" msgstr "atendis pli novan version de sed" #: sed/compile.c:185 #, fuzzy msgid "invalid usage of line address 0" msgstr "Nevalida uzo de adresmodifilo" #: sed/compile.c:186 #, fuzzy, c-format msgid "unknown command: `%c'" msgstr "Nekonata komando:" #: sed/compile.c:209 #, c-format msgid "%s: file %s line %lu: %s\n" msgstr "%s: dosiero %s linio %lu: %s\n" #: sed/compile.c:212 #, c-format msgid "%s: -e expression #%lu, char %lu: %s\n" msgstr "%s: -e esprimo #%lu, signo %lu: %s\n" #: sed/compile.c:1644 #, fuzzy, c-format msgid "can't find label for jump to `%s'" msgstr "Ne povas trovi etikedon por salto al '%s'" #: sed/execute.c:650 #, c-format msgid "%s: can't read %s: %s\n" msgstr "%s: ne povas legi %s: %s\n" #: sed/execute.c:673 #, fuzzy, c-format msgid "couldn't edit %s: is a terminal" msgstr "Ne povis malfermi dosieron %s: %s" #: sed/execute.c:677 #, fuzzy, c-format msgid "couldn't edit %s: not a regular file" msgstr "Ne povis malfermi dosieron %s: %s" #: sed/execute.c:684 lib/utils.c:196 #, fuzzy, c-format msgid "couldn't open temporary file %s: %s" msgstr "Ne povis malfermi dumtempan dosieron %s: %s" #: sed/execute.c:1206 sed/execute.c:1387 msgid "error in subprocess" msgstr "eraro en subprocezo" #: sed/execute.c:1208 msgid "option `e' not supported" msgstr "opcio 'e' ne realigita" #: sed/execute.c:1389 msgid "`e' command not supported" msgstr "komando 'e' ne realigita" #: sed/execute.c:1714 msgid "no input files" msgstr "" #: sed/regexp.c:39 #, fuzzy msgid "no previous regular expression" msgstr "Mankas antaÅ­a regula esprimo" #: sed/regexp.c:40 #, fuzzy msgid "cannot specify modifiers on empty regexp" msgstr "Ne eblas specifi modifilojn ĉe malplena regula esprimo" #: sed/regexp.c:115 #, fuzzy, c-format msgid "invalid reference \\%d on `s' command's RHS" msgstr "Nevalida referenco \\%d ĉe dekstra flanko de komando 's'" #: sed/sed.c:93 msgid "" " -R, --regexp-perl\n" " use Perl 5's regular expressions syntax in the script.\n" msgstr "" " -R, --regexp-perl\n" " uzi sintakso de Perl 5 por regulaj esprimoj en programo.\n" #: sed/sed.c:98 #, c-format msgid "" "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n" "\n" msgstr "" #: sed/sed.c:102 #, c-format msgid "" " -n, --quiet, --silent\n" " suppress automatic printing of pattern space\n" msgstr "" #: sed/sed.c:104 #, c-format msgid "" " -e script, --expression=script\n" " add the script to the commands to be executed\n" msgstr "" #: sed/sed.c:106 #, c-format msgid "" " -f script-file, --file=script-file\n" " add the contents of script-file to the commands to be " "executed\n" msgstr "" #: sed/sed.c:108 #, c-format msgid "" " -i[SUFFIX], --in-place[=SUFFIX]\n" " edit files in place (makes backup if extension supplied)\n" msgstr "" #: sed/sed.c:110 #, c-format msgid "" " -l N, --line-length=N\n" " specify the desired line-wrap length for the `l' command\n" msgstr "" #: sed/sed.c:112 #, c-format msgid "" " --posix\n" " disable all GNU extensions.\n" msgstr "" #: sed/sed.c:114 #, fuzzy, c-format msgid "" " -r, --regexp-extended\n" " use extended regular expressions in the script.\n" msgstr "" " -R, --regexp-perl\n" " uzi sintakso de Perl 5 por regulaj esprimoj en programo.\n" #: sed/sed.c:117 #, c-format msgid "" " -s, --separate\n" " consider files as separate rather than as a single " "continuous\n" " long stream.\n" msgstr "" #: sed/sed.c:120 #, c-format msgid "" " -u, --unbuffered\n" " load minimal amounts of data from the input files and " "flush\n" " the output buffers more often\n" msgstr "" #: sed/sed.c:123 #, c-format msgid " --help display this help and exit\n" msgstr "" #: sed/sed.c:124 #, c-format msgid " --version output version information and exit\n" msgstr "" #: sed/sed.c:125 #, c-format msgid "" "\n" "If no -e, --expression, -f, or --file option is given, then the first\n" "non-option argument is taken as the sed script to interpret. All\n" "remaining arguments are names of input files; if no input files are\n" "specified, then the standard input is read.\n" "\n" msgstr "" #: sed/sed.c:131 #, c-format msgid "" "E-mail bug reports to: %s .\n" "Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n" msgstr "" "RetpoÅtu cimo-raportojn al: %s .\n" "Nepre menciu la vorton '%s' ie en la temlinio.\n" #: sed/sed.c:268 #, c-format msgid "super-sed version %s\n" msgstr "super-sed versio %s\n" #: sed/sed.c:269 #, fuzzy, c-format msgid "" "based on GNU sed version %s\n" "\n" msgstr "" "bazita sur \"GNU sed\" versio 3.02.80\n" "\n" #: sed/sed.c:271 #, c-format msgid "GNU sed version %s\n" msgstr "GNU sed versio %s\n" #: sed/sed.c:273 #, c-format msgid "" "%s\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n" "to the extent permitted by law.\n" msgstr "" "%s\n" "Ĉi tio estas libera programo; vidu la fonton por kopi-kondiĉoj. Estas\n" "NENIA GARANTIO; eĉ ne por KOMERCA KVALITO aÅ­ ADEKVATECO POR DIFINITA CELO,\n" "laÅ­ la grado permesita de juro.\n" #: lib/utils.c:98 lib/utils.c:336 #, fuzzy, c-format msgid "cannot remove %s: %s" msgstr "%s: ne povas legi %s: %s\n" #: lib/utils.c:143 #, fuzzy, c-format msgid "couldn't open file %s: %s" msgstr "Ne povis malfermi dosieron %s: %s" #: lib/utils.c:220 #, c-format msgid "couldn't write %d item to %s: %s" msgid_plural "couldn't write %d items to %s: %s" msgstr[0] "ne povis skribi %d eron al %s: %s" msgstr[1] "ne povis skribi %d erojn al %s: %s" #: lib/utils.c:235 lib/utils.c:251 #, c-format msgid "read error on %s: %s" msgstr "legeraro ĉe %s: %s" #: lib/utils.c:341 #, fuzzy, c-format msgid "cannot rename %s: %s" msgstr "%s: ne povas legi %s: %s\n" #: lib/regcomp.c:132 msgid "Success" msgstr "Sukceso" #: lib/regcomp.c:135 msgid "No match" msgstr "Maltrafo" #: lib/regcomp.c:138 msgid "Invalid regular expression" msgstr "Nevalida regula esprimo" #: lib/regcomp.c:141 msgid "Invalid collation character" msgstr "Nevalida kunfanda signo" #: lib/regcomp.c:144 msgid "Invalid character class name" msgstr "Nevalida nomo de signoklaso" #: lib/regcomp.c:147 msgid "Trailing backslash" msgstr "Malsuprenstreko ĉe fino" #: lib/regcomp.c:150 msgid "Invalid back reference" msgstr "Nevalida retroreferenco" #: lib/regcomp.c:153 msgid "Unmatched [ or [^" msgstr "Neparigita [ aÅ­ [^" #: lib/regcomp.c:156 msgid "Unmatched ( or \\(" msgstr "Neparigita ( aÅ­ \\(" #: lib/regcomp.c:159 msgid "Unmatched \\{" msgstr "Neparigita \\{" #: lib/regcomp.c:162 msgid "Invalid content of \\{\\}" msgstr "Nevalida enhavo de \\{\\}" #: lib/regcomp.c:165 msgid "Invalid range end" msgstr "Nevalida fino de gamo" #: lib/regcomp.c:168 msgid "Memory exhausted" msgstr "Mankas memoro" #: lib/regcomp.c:171 msgid "Invalid preceding regular expression" msgstr "Nevalida antaÅ­a regula esprimo" #: lib/regcomp.c:174 msgid "Premature end of regular expression" msgstr "Neatendita fino de regula esprimo" #: lib/regcomp.c:177 msgid "Regular expression too big" msgstr "Regula esprimo tro granda" #: lib/regcomp.c:180 msgid "Unmatched ) or \\)" msgstr "Neparigita ) aÅ­ \\)" #: lib/regcomp.c:660 msgid "No previous regular expression" msgstr "Mankas antaÅ­a regula esprimo" kbuild-3686/src/oldsed/BUGS0000664000175000017500000001253415053010105015433 0ustar locutuslocutus* ABOUT BUGS Before reporting a bug, please check the list of known bugs and the list of oft-reported non-bugs (below). Bugs and comments may be sent to bonzini@gnu.org; please include in the Subject: header the first line of the output of ``sed --version''. Please do not send a bug report like this: [while building frobme-1.3.4] $ configure sed: file sedscr line 1: Unknown option to 's' If sed doesn't configure your favorite package, take a few extra minutes to identify the specific problem and make a stand-alone test case. A stand-alone test case includes all the data necessary to perform the test, and the specific invocation of sed that causes the problem. The smaller a stand-alone test case is, the better. A test case should not involve something as far removed from sed as ``try to configure frobme-1.3.4''. Yes, that is in principle enough information to look for the bug, but that is not a very practical prospect. * NON-BUGS `N' command on the last line Most versions of sed exit without printing anything when the `N' command is issued on the last line of a file. GNU sed instead prints pattern space before exiting unless of course the `-n' command switch has been specified. More information on the reason behind this choice can be found in the Info manual. regex syntax clashes (problems with backslashes) sed uses the Posix basic regular expression syntax. According to the standard, the meaning of some escape sequences is undefined in this syntax; notable in the case of GNU sed are `\|', `\+', `\?', `\`', `\'', `\<', `\>', `\b', `\B', `\w', and `\W'. As in all GNU programs that use Posix basic regular expressions, sed interprets these escape sequences as meta-characters. So, `x\+' matches one or more occurrences of `x'. `abc\|def' matches either `abc' or `def'. This syntax may cause problems when running scripts written for other seds. Some sed programs have been written with the assumption that `\|' and `\+' match the literal characters `|' and `+'. Such scripts must be modified by removing the spurious backslashes if they are to be used with recent versions of sed (not only GNU sed). On the other hand, some scripts use `s|abc\|def||g' to remove occurrences of _either_ `abc' or `def'. While this worked until sed 4.0.x, newer versions interpret this as removing the string `abc|def'. This is again undefined behavior according to POSIX, but this interpretation is arguably more robust: the older one, for example, required that the regex matcher parsed `\/' as `/' in the common case of escaping a slash, which is again undefined behavior; the new behavior avoids this, and this is good because the regex matcher is only partially under our control. In addition, GNU sed supports several escape characters (some of which are multi-character) to insert non-printable characters in scripts (`\a', `\c', `\d', `\o', `\r', `\t', `\v', `\x'). These can cause similar problems with scripts written for other seds. -i clobbers read-only files In short, `sed d -i' will let one delete the contents of a read-only file, and in general the `-i' option will let one clobber protected files. This is not a bug, but rather a consequence of how the Unix filesystem works. The permissions on a file say what can happen to the data in that file, while the permissions on a directory say what can happen to the list of files in that directory. `sed -i' will not ever open for writing a file that is already on disk, rather, it will work on a temporary file that is finally renamed to the original name: if you rename or delete files, you're actually modifying the contents of the directory, so the operation depends on the permissions of the directory, not of the file). For this same reason, sed will not let one use `-i' on a writeable file in a read-only directory (but unbelievably nobody reports that as a bug...). `0a' does not work (gives an error) There is no line 0. 0 is a special address that is only used to treat addresses like `0,/RE/' as active when the script starts: if you write `1,/abc/d' and the first line includes the word `abc', then that match would be ignored because address ranges must span at least two lines (barring the end of the file); but what you probably wanted is to delete every line up to the first one including `abc', and this is obtained with `0,/abc/d'. `[a-z]' is case insensitive You are encountering problems with locales. POSIX mandates that `[a-z]' uses the current locale's collation order -- in C parlance, that means strcoll(3) instead of strcmp(3). Some locales have a case insensitive strcoll, others don't: one of those that have problems is Estonian. Another problem is that [a-z] tries to use collation symbols. This only happens if you are on the GNU system, using GNU libc's regular expression matcher instead of compiling the one supplied with GNU sed. In a Danish locale, for example, the regular expression `^[a-z]$' matches the string `aa', because aa is a single collating symbol that comes after `a' and before `b'; `ll' behaves similarly in Spanish locales, or `ij' in Dutch locales. To work around these problems, which may cause bugs in shell scripts, set the LC_ALL environment variable to `C', or set the locale on a more fine-grained basis with the other LC_* environment variables. kbuild-3686/src/oldsed/config.h.freebsd0000664000175000017500000002443015053010105017775 0ustar locutuslocutus/* config.h. Generated by configure. */ /* config_h.in. Generated from configure.ac by autoheader. */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if translation of program messages to the user's native language is requested. */ /* #undef ENABLE_NLS */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ /* #undef HAVE_ALLOCA_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_ARGZ_H */ /* Define to 1 if you have the `bcopy' function. */ #define HAVE_BCOPY 1 /* Define to 1 if you have the `btowc' function. */ #define HAVE_BTOWC 1 /* Define to 1 if you have the `bzero' function. */ #define HAVE_BZERO 1 /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* #undef HAVE_DCGETTEXT */ /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ /* #undef HAVE_DOPRNT */ /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H 1 /* Define to 1 if you have the `fchmod' function. */ #define HAVE_FCHMOD 1 /* Define to 1 if you have the `fchown' function. */ #define HAVE_FCHOWN 1 /* Define to 1 if you have the `feof_unlocked' function. */ #define HAVE_FEOF_UNLOCKED 1 /* Define to 1 if you have the `fgets_unlocked' function. */ /* #undef HAVE_FGETS_UNLOCKED */ /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getc_unlocked' function. */ #define HAVE_GETC_UNLOCKED 1 /* Define to 1 if you have the `getegid' function. */ #define HAVE_GETEGID 1 /* Define to 1 if you have the `geteuid' function. */ #define HAVE_GETEUID 1 /* Define to 1 if you have the `getgid' function. */ #define HAVE_GETGID 1 /* Define to 1 if you have the `getpagesize' function. */ #define HAVE_GETPAGESIZE 1 /* Define if the GNU gettext() function is already present or preinstalled. */ /* #undef HAVE_GETTEXT */ /* Define to 1 if you have the `getuid' function. */ #define HAVE_GETUID 1 /* Define if you have the iconv() function. */ #define HAVE_ICONV 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_IO_H */ /* Define to 1 if you have the `isascii' function. */ #define HAVE_ISASCII 1 /* Define to 1 if you have the `isatty' function. */ #define HAVE_ISATTY 1 /* Define to 1 if you have the `isblank' function. */ #define HAVE_ISBLANK 1 /* Define if you have and nl_langinfo(CODESET). */ #define HAVE_LANGINFO_CODESET 1 /* Define if your file defines LC_MESSAGES. */ #define HAVE_LC_MESSAGES 1 /* Define to 1 if you have the `regex' library (-lregex). */ /* #undef HAVE_LIBREGEX */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you support file names longer than 14 characters. */ #define HAVE_LONG_FILE_NAMES 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MALLOC_H */ /* Define to 1 if mbrtowc and mbstate_t are properly declared. */ #define HAVE_MBRTOWC 1 /* Define to 1 if declares mbstate_t. */ #define HAVE_MBSTATE_T 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MCHECK_H */ /* Define to 1 if you have the `memchr' function. */ #define HAVE_MEMCHR 1 /* Define to 1 if you have the `memcmp' function. */ #define HAVE_MEMCMP 1 /* Define to 1 if you have the `memcpy' function. */ #define HAVE_MEMCPY 1 /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mempcpy' function. */ /* #undef HAVE_MEMPCPY */ /* Define to 1 if you have the `memset' function. */ #define HAVE_MEMSET 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have a working `mmap' system call. */ #define HAVE_MMAP 1 /* Define to 1 if you have the `munmap' function. */ #define HAVE_MUNMAP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_NL_TYPES_H 1 /* Define to 1 if libc includes obstacks. */ /* #undef HAVE_OBSTACK */ /* Define to 1 if you have the `pathconf' function. */ #define HAVE_PATHCONF 1 /* Define to 1 if you have the `popen' function. */ #define HAVE_POPEN 1 /* Define to 1 if you have the `putenv' function. */ #define HAVE_PUTENV 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_REGEX_H */ /* Define to 1 if you have the `setenv' function. */ #define HAVE_SETENV 1 /* Define to 1 if you have the `setlocale' function. */ #define HAVE_SETLOCALE 1 /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if stdbool.h conforms to C99. */ #define HAVE_STDBOOL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `stpcpy' function. */ #define HAVE_STPCPY 1 /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strtoul' function. */ #define HAVE_STRTOUL 1 /* Define to 1 if you have the `strverscmp' function. */ /* #undef HAVE_STRVERSCMP */ /* 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. */ #define HAVE_SYS_FILE_H 1 /* 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. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the `tsearch' function. */ #define HAVE_TSEARCH 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_WCHAR_H 1 /* Define to 1 if you have the `wcrtomb' function. */ #define HAVE_WCRTOMB 1 /* Define to 1 if you have the `wcscoll' function. */ #define HAVE_WCSCOLL 1 /* Define to 1 if you have the header file. */ #define HAVE_WCTYPE_H 1 /* Define to 1 if the system has the type `_Bool'. */ #define HAVE__BOOL 1 /* Define to 1 if you have the `__argz_count' function. */ /* #undef HAVE___ARGZ_COUNT */ /* Define to 1 if you have the `__argz_next' function. */ /* #undef HAVE___ARGZ_NEXT */ /* Define to 1 if you have the `__argz_stringify' function. */ /* #undef HAVE___ARGZ_STRINGIFY */ /* Define as const if the declaration of iconv() needs const. */ #define ICONV_CONST const /* Name of package */ #define PACKAGE "sed" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bonzini@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "sed" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "sed 4.1.5" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "sed" /* Define to the version of this package. */ #define PACKAGE_VERSION "4.1.5" /* Define to the version of GNU sed whose features are supported by this sed. */ #define SED_FEATURE_VERSION "4.1" /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ #define VERSION "4.1.5" /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* # undef _ALL_SOURCE */ #endif /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Include BSD functions in regex, used by the testsuite */ #define _REGEX_RE_COMP 1 /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to a type if does not define. */ /* #undef mbstate_t */ /* Define to `long' if does not define. */ /* #undef off_t */ /* Define to `unsigned' if does not define. */ /* #undef size_t */ /* Define to `int' if does not define. */ /* #undef ssize_t */ kbuild-3686/src/oldsed/config.h.linux0000664000175000017500000002436015053010105017524 0ustar locutuslocutus/* config.h. Generated by configure. */ /* config_h.in. Generated from configure.ac by autoheader. */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if translation of program messages to the user's native language is requested. */ /* #undef ENABLE_NLS */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ #define HAVE_ALLOCA_H 1 /* Define to 1 if you have the header file. */ #define HAVE_ARGZ_H 1 /* Define to 1 if you have the `bcopy' function. */ #define HAVE_BCOPY 1 /* Define to 1 if you have the `btowc' function. */ #define HAVE_BTOWC 1 /* Define to 1 if you have the `bzero' function. */ #define HAVE_BZERO 1 /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* #undef HAVE_DCGETTEXT */ /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ /* #undef HAVE_DOPRNT */ /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H 1 /* Define to 1 if you have the `fchmod' function. */ #define HAVE_FCHMOD 1 /* Define to 1 if you have the `fchown' function. */ #define HAVE_FCHOWN 1 /* Define to 1 if you have the `feof_unlocked' function. */ #define HAVE_FEOF_UNLOCKED 1 /* Define to 1 if you have the `fgets_unlocked' function. */ #define HAVE_FGETS_UNLOCKED 1 /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getc_unlocked' function. */ #define HAVE_GETC_UNLOCKED 1 /* Define to 1 if you have the `getegid' function. */ #define HAVE_GETEGID 1 /* Define to 1 if you have the `geteuid' function. */ #define HAVE_GETEUID 1 /* Define to 1 if you have the `getgid' function. */ #define HAVE_GETGID 1 /* Define to 1 if you have the `getpagesize' function. */ #define HAVE_GETPAGESIZE 1 /* Define if the GNU gettext() function is already present or preinstalled. */ /* #undef HAVE_GETTEXT */ /* Define to 1 if you have the `getuid' function. */ #define HAVE_GETUID 1 /* Define if you have the iconv() function. */ #define HAVE_ICONV 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_IO_H */ /* Define to 1 if you have the `isascii' function. */ #define HAVE_ISASCII 1 /* Define to 1 if you have the `isatty' function. */ #define HAVE_ISATTY 1 /* Define to 1 if you have the `isblank' function. */ #define HAVE_ISBLANK 1 /* Define if you have and nl_langinfo(CODESET). */ #define HAVE_LANGINFO_CODESET 1 /* Define if your file defines LC_MESSAGES. */ #define HAVE_LC_MESSAGES 1 /* Define to 1 if you have the `regex' library (-lregex). */ /* #undef HAVE_LIBREGEX */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you support file names longer than 14 characters. */ #define HAVE_LONG_FILE_NAMES 1 /* Define to 1 if you have the header file. */ #define HAVE_MALLOC_H 1 /* Define to 1 if mbrtowc and mbstate_t are properly declared. */ #define HAVE_MBRTOWC 1 /* Define to 1 if declares mbstate_t. */ #define HAVE_MBSTATE_T 1 /* Define to 1 if you have the header file. */ #define HAVE_MCHECK_H 1 /* Define to 1 if you have the `memchr' function. */ #define HAVE_MEMCHR 1 /* Define to 1 if you have the `memcmp' function. */ #define HAVE_MEMCMP 1 /* Define to 1 if you have the `memcpy' function. */ #define HAVE_MEMCPY 1 /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mempcpy' function. */ #define HAVE_MEMPCPY 1 /* Define to 1 if you have the `memset' function. */ #define HAVE_MEMSET 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have a working `mmap' system call. */ #define HAVE_MMAP 1 /* Define to 1 if you have the `munmap' function. */ #define HAVE_MUNMAP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_NL_TYPES_H 1 /* Define to 1 if libc includes obstacks. */ #define HAVE_OBSTACK 1 /* Define to 1 if you have the `pathconf' function. */ #define HAVE_PATHCONF 1 /* Define to 1 if you have the `popen' function. */ #define HAVE_POPEN 1 /* Define to 1 if you have the `putenv' function. */ #define HAVE_PUTENV 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_REGEX_H */ /* Define to 1 if you have the `setenv' function. */ #define HAVE_SETENV 1 /* Define to 1 if you have the `setlocale' function. */ #define HAVE_SETLOCALE 1 /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if stdbool.h conforms to C99. */ #define HAVE_STDBOOL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `stpcpy' function. */ #define HAVE_STPCPY 1 /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strtoul' function. */ #define HAVE_STRTOUL 1 /* Define to 1 if you have the `strverscmp' function. */ #define HAVE_STRVERSCMP 1 /* 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. */ #define HAVE_SYS_FILE_H 1 /* 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. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the `tsearch' function. */ #define HAVE_TSEARCH 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_WCHAR_H 1 /* Define to 1 if you have the `wcrtomb' function. */ #define HAVE_WCRTOMB 1 /* Define to 1 if you have the `wcscoll' function. */ #define HAVE_WCSCOLL 1 /* Define to 1 if you have the header file. */ #define HAVE_WCTYPE_H 1 /* Define to 1 if the system has the type `_Bool'. */ #define HAVE__BOOL 1 /* Define to 1 if you have the `__argz_count' function. */ #define HAVE___ARGZ_COUNT 1 /* Define to 1 if you have the `__argz_next' function. */ #define HAVE___ARGZ_NEXT 1 /* Define to 1 if you have the `__argz_stringify' function. */ #define HAVE___ARGZ_STRINGIFY 1 /* Define as const if the declaration of iconv() needs const. */ #define ICONV_CONST /* Name of package */ #define PACKAGE "sed" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bonzini@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "sed" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "sed 4.1.5" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "sed" /* Define to the version of this package. */ #define PACKAGE_VERSION "4.1.5" /* Define to the version of GNU sed whose features are supported by this sed. */ #define SED_FEATURE_VERSION "4.1" /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ #define VERSION "4.1.5" /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* # undef _ALL_SOURCE */ #endif /* Number of bits in a file offset, on hosts where this is settable. */ #define _FILE_OFFSET_BITS 64 /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Include BSD functions in regex, used by the testsuite */ #define _REGEX_RE_COMP 1 /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to a type if does not define. */ /* #undef mbstate_t */ /* Define to `long' if does not define. */ /* #undef off_t */ /* Define to `unsigned' if does not define. */ /* #undef size_t */ /* Define to `int' if does not define. */ /* #undef ssize_t */ kbuild-3686/src/oldsed/README.boot0000664000175000017500000000231515053010105016566 0ustar locutuslocutusBecause a working sed is a prerequisite for running the ``configure'' script, I have provided the script ``bootstrap.sh'' which will attempt to build a version of sed adequate for running ``configure''. If it fails, edit the ``config.h'' file that was created according to the comments found therein, and then try running ``bootstrap.sh'' again. The bootstrap build is quite likely to babble on and on with various compiler warnings. You may want to tell bootstrap.sh how to invoke your compiler with warnings disabled. For example, with a Bourne-like shell and gcc one could use: $ CC='gcc -w' sh bootstrap.sh or with a csh-like shell, one could try: % env CC='gcc -w' sh bootstrap.sh Once you get a working version of sed, temporarily install sed/sed somewhere in your $PATH, and then really re-build the normal way (starting with ``sh configure''); the bootstrap version is almost certainly more crippled than it needs to be on your machine. I don't much care to hear about any bugs in ``bootstrap'' versions of sed beyond those which actually keep the ``bootstrap'' version from building, or sed's configure script from running properly. I am especially uninterested in compiler warnings from the bootstrap build. kbuild-3686/src/oldsed/doc/0000775000175000017500000000000015053010106015511 5ustar locutuslocutuskbuild-3686/src/oldsed/doc/groupify.sed0000775000175000017500000000205615053010105020057 0ustar locutuslocutus#! /bin/sed -nf # Script to add @group...@end group tags to sed.texi.in # so that comments are not separated from the instructions # that they refer to. # Step 1: search for the conventional "@c start----" comment 1a\ @c Do not edit this file!! It is automatically generated from sed-in.texi. p /^@c start-*$/! b # Step 2: loop until we find a @ command :a n p /^@/! ba # Step 3: process everything until a "@end" command # Step 3.1: Print the blank lines before the group. If we reach the "@end", # we go back to step 1. :b n /^@end/ { p b } /^[ ]*$/ { p bb } # Step 3.2: Add to hold space every line until an empty one or "@end" h :c n /^@end example/! { /^[ ]*$/! { H bc } } # Step 3.3: Working in hold space, add @group...@end group if there are # at least two lines. Then print the lines we processed and # switch back to pattern space. x /\n/ { s/.*/@group\ &\ @end group/ } p # Step 3.4: Switch back to pattern space, print the first blank line # and possibly go back to step 3.1 x p /^@end/ !bb kbuild-3686/src/oldsed/doc/sed.info-10000664000175000017500000014234515053010106017310 0ustar locutuslocutusThis is ../../doc/sed.info, produced by makeinfo version 4.5 from ../../doc/sed.texi. INFO-DIR-SECTION Text creation and manipulation START-INFO-DIR-ENTRY * sed: (sed). Stream EDitor. END-INFO-DIR-ENTRY This file documents version 4.1.5 of GNU `sed', a stream editor. Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This document is released under the terms of the GNU Free Documentation License as published by the Free Software Foundation; either version 1.1, or (at your option) any later version. You should have received a copy of the GNU Free Documentation License along with GNU `sed'; see the file `COPYING.DOC'. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02110-1301, USA. There are no Cover Texts and no Invariant Sections; this text, along with its equivalent in the printed manual, constitutes the Title Page.  File: sed.info, Node: Top, Next: Introduction, Up: (dir) This file documents version 4.1.5 of GNU `sed', a stream editor. Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This document is released under the terms of the GNU Free Documentation License as published by the Free Software Foundation; either version 1.1, or (at your option) any later version. You should have received a copy of the GNU Free Documentation License along with GNU `sed'; see the file `COPYING.DOC'. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02110-1301, USA. There are no Cover Texts and no Invariant Sections; this text, along with its equivalent in the printed manual, constitutes the Title Page. * Menu: * Introduction:: Introduction * Invoking sed:: Invocation * sed Programs:: `sed' programs * Examples:: Some sample scripts * Limitations:: Limitations and (non-)limitations of GNU `sed' * Other Resources:: Other resources for learning about `sed' * Reporting Bugs:: Reporting bugs * Extended regexps:: `egrep'-style regular expressions * Concept Index:: A menu with all the topics in this manual. * Command and Option Index:: A menu with all `sed' commands and command-line options. --- The detailed node listing --- sed Programs: * Execution Cycle:: How `sed' works * Addresses:: Selecting lines with `sed' * Regular Expressions:: Overview of regular expression syntax * Common Commands:: Often used commands * The "s" Command:: `sed''s Swiss Army Knife * Other Commands:: Less frequently used commands * Programming Commands:: Commands for `sed' gurus * Extended Commands:: Commands specific of GNU `sed' * Escapes:: Specifying special characters Examples: * Centering lines:: * Increment a number:: * Rename files to lower case:: * Print bash environment:: * Reverse chars of lines:: * tac:: Reverse lines of files * cat -n:: Numbering lines * cat -b:: Numbering non-blank lines * wc -c:: Counting chars * wc -w:: Counting words * wc -l:: Counting lines * head:: Printing the first lines * tail:: Printing the last lines * uniq:: Make duplicate lines unique * uniq -d:: Print duplicated lines of input * uniq -u:: Remove all duplicated lines * cat -s:: Squeezing blank lines  File: sed.info, Node: Introduction, Next: Invoking sed, Prev: Top, Up: Top Introduction ************ `sed' is a stream editor. A stream editor is used to perform basic text transformations on an input stream (a file or input from a pipeline). While in some ways similar to an editor which permits scripted edits (such as `ed'), `sed' works by making only one pass over the input(s), and is consequently more efficient. But it is `sed''s ability to filter text in a pipeline which particularly distinguishes it from other types of editors.  File: sed.info, Node: Invoking sed, Next: sed Programs, Prev: Introduction, Up: Top Invocation ********** Normally `sed' is invoked like this: sed SCRIPT INPUTFILE... The full format for invoking `sed' is: sed OPTIONS... [SCRIPT] [INPUTFILE...] If you do not specify INPUTFILE, or if INPUTFILE is `-', `sed' filters the contents of the standard input. The SCRIPT is actually the first non-option parameter, which `sed' specially considers a script and not an input file if (and only if) none of the other OPTIONS specifies a script to be executed, that is if neither of the `-e' and `-f' options is specified. `sed' may be invoked with the following command-line options: `--version' Print out the version of `sed' that is being run and a copyright notice, then exit. `--help' Print a usage message briefly summarizing these command-line options and the bug-reporting address, then exit. `-n' `--quiet' `--silent' By default, `sed' prints out the pattern space at the end of each cycle through the script. These options disable this automatic printing, and `sed' only produces output when explicitly told to via the `p' command. `-i[SUFFIX]' `--in-place[=SUFFIX]' This option specifies that files are to be edited in-place. GNU `sed' does this by creating a temporary file and sending output to this file rather than to the standard output.(1). This option implies `-s'. When the end of the file is reached, the temporary file is renamed to the output file's original name. The extension, if supplied, is used to modify the name of the old file before renaming the temporary file, thereby making a backup copy(2)). This rule is followed: if the extension doesn't contain a `*', then it is appended to the end of the current filename as a suffix; if the extension does contain one or more `*' characters, then _each_ asterisk is replaced with the current filename. This allows you to add a prefix to the backup file, instead of (or in addition to) a suffix, or even to place backup copies of the original files into another directory (provided the directory already exists). If no extension is supplied, the original file is overwritten without making a backup. `-l N' `--line-length=N' Specify the default line-wrap length for the `l' command. A length of 0 (zero) means to never wrap long lines. If not specified, it is taken to be 70. `--posix' GNU `sed' includes several extensions to POSIX sed. In order to simplify writing portable scripts, this option disables all the extensions that this manual documents, including additional commands. Most of the extensions accept `sed' programs that are outside the syntax mandated by POSIX, but some of them (such as the behavior of the `N' command described in *note Reporting Bugs::) actually violate the standard. If you want to disable only the latter kind of extension, you can set the `POSIXLY_CORRECT' variable to a non-empty value. `-r' `--regexp-extended' Use extended regular expressions rather than basic regular expressions. Extended regexps are those that `egrep' accepts; they can be clearer because they usually have less backslashes, but are a GNU extension and hence scripts that use them are not portable. *Note Extended regular expressions: Extended regexps. `-s' `--separate' By default, `sed' will consider the files specified on the command line as a single continuous long stream. This GNU `sed' extension allows the user to consider them as separate files: range addresses (such as `/abc/,/def/') are not allowed to span several files, line numbers are relative to the start of each file, `$' refers to the last line of each file, and files invoked from the `R' commands are rewound at the start of each file. `-u' `--unbuffered' Buffer both input and output as minimally as practical. (This is particularly useful if the input is coming from the likes of `tail -f', and you wish to see the transformed output as soon as possible.) `-e SCRIPT' `--expression=SCRIPT' Add the commands in SCRIPT to the set of commands to be run while processing the input. `-f SCRIPT-FILE' `--file=SCRIPT-FILE' Add the commands contained in the file SCRIPT-FILE to the set of commands to be run while processing the input. If no `-e', `-f', `--expression', or `--file' options are given on the command-line, then the first non-option argument on the command line is taken to be the SCRIPT to be executed. If any command-line parameters remain after processing the above, these parameters are interpreted as the names of input files to be processed. A file name of `-' refers to the standard input stream. The standard input will be processed if no file names are specified. ---------- Footnotes ---------- (1) This applies to commands such as `=', `a', `c', `i', `l', `p'. You can still write to the standard output by using the `w' or `W' commands together with the `/dev/stdout' special file (2) Note that GNU `sed' creates the backup file whether or not any output is actually changed.  File: sed.info, Node: sed Programs, Next: Examples, Prev: Invoking sed, Up: Top `sed' Programs ************** A `sed' program consists of one or more `sed' commands, passed in by one or more of the `-e', `-f', `--expression', and `--file' options, or the first non-option argument if zero of these options are used. This document will refer to "the" `sed' script; this is understood to mean the in-order catenation of all of the SCRIPTs and SCRIPT-FILEs passed in. Each `sed' command consists of an optional address or address range, followed by a one-character command name and any additional command-specific code. * Menu: * Execution Cycle:: How `sed' works * Addresses:: Selecting lines with `sed' * Regular Expressions:: Overview of regular expression syntax * Common Commands:: Often used commands * The "s" Command:: `sed''s Swiss Army Knife * Other Commands:: Less frequently used commands * Programming Commands:: Commands for `sed' gurus * Extended Commands:: Commands specific of GNU `sed' * Escapes:: Specifying special characters  File: sed.info, Node: Execution Cycle, Next: Addresses, Up: sed Programs How `sed' Works =============== `sed' maintains two data buffers: the active _pattern_ space, and the auxiliary _hold_ space. Both are initially empty. `sed' operates by performing the following cycle on each lines of input: first, `sed' reads one line from the input stream, removes any trailing newline, and places it in the pattern space. Then commands are executed; each command can have an address associated to it: addresses are a kind of condition code, and a command is only executed if the condition is verified before the command is to be executed. When the end of the script is reached, unless the `-n' option is in use, the contents of pattern space are printed out to the output stream, adding back the trailing newline if it was removed.(1) Then the next cycle starts for the next input line. Unless special commands (like `D') are used, the pattern space is deleted between two cycles. The hold space, on the other hand, keeps its data between cycles (see commands `h', `H', `x', `g', `G' to move data between both buffers). ---------- Footnotes ---------- (1) Actually, if `sed' prints a line without the terminating newline, it will nevertheless print the missing newline as soon as more text is sent to the same output stream, which gives the "least expected surprise" even though it does not make commands like `sed -n p' exactly identical to `cat'.  File: sed.info, Node: Addresses, Next: Regular Expressions, Prev: Execution Cycle, Up: sed Programs Selecting lines with `sed' ========================== Addresses in a `sed' script can be in any of the following forms: `NUMBER' Specifying a line number will match only that line in the input. (Note that `sed' counts lines continuously across all input files unless `-i' or `-s' options are specified.) `FIRST~STEP' This GNU extension matches every STEPth line starting with line FIRST. In particular, lines will be selected when there exists a non-negative N such that the current line-number equals FIRST + (N * STEP). Thus, to select the odd-numbered lines, one would use `1~2'; to pick every third line starting with the second, `2~3' would be used; to pick every fifth line starting with the tenth, use `10~5'; and `50~0' is just an obscure way of saying `50'. `$' This address matches the last line of the last file of input, or the last line of each file when the `-i' or `-s' options are specified. `/REGEXP/' This will select any line which matches the regular expression REGEXP. If REGEXP itself includes any `/' characters, each must be escaped by a backslash (`\'). The empty regular expression `//' repeats the last regular expression match (the same holds if the empty regular expression is passed to the `s' command). Note that modifiers to regular expressions are evaluated when the regular expression is compiled, thus it is invalid to specify them together with the empty regular expression. `\%REGEXP%' (The `%' may be replaced by any other single character.) This also matches the regular expression REGEXP, but allows one to use a different delimiter than `/'. This is particularly useful if the REGEXP itself contains a lot of slashes, since it avoids the tedious escaping of every `/'. If REGEXP itself includes any delimiter characters, each must be escaped by a backslash (`\'). `/REGEXP/I' `\%REGEXP%I' The `I' modifier to regular-expression matching is a GNU extension which causes the REGEXP to be matched in a case-insensitive manner. `/REGEXP/M' `\%REGEXP%M' The `M' modifier to regular-expression matching is a GNU `sed' extension which causes `^' and `$' to match respectively (in addition to the normal behavior) the empty string after a newline, and the empty string before a newline. There are special character sequences (`\`' and `\'') which always match the beginning or the end of the buffer. `M' stands for `multi-line'. If no addresses are given, then all lines are matched; if one address is given, then only lines matching that address are matched. An address range can be specified by specifying two addresses separated by a comma (`,'). An address range matches lines starting from where the first address matches, and continues until the second address matches (inclusively). If the second address is a REGEXP, then checking for the ending match will start with the line _following_ the line which matched the first address: a range will always span at least two lines (except of course if the input stream ends). If the second address is a NUMBER less than (or equal to) the line matching the first address, then only the one line is matched. GNU `sed' also supports some special two-address forms; all these are GNU extensions: `0,/REGEXP/' A line number of `0' can be used in an address specification like `0,/REGEXP/' so that `sed' will try to match REGEXP in the first input line too. In other words, `0,/REGEXP/' is similar to `1,/REGEXP/', except that if ADDR2 matches the very first line of input the `0,/REGEXP/' form will consider it to end the range, whereas the `1,/REGEXP/' form will match the beginning of its range and hence make the range span up to the _second_ occurrence of the regular expression. Note that this is the only place where the `0' address makes sense; there is no 0-th line and commands which are given the `0' address in any other way will give an error. `ADDR1,+N' Matches ADDR1 and the N lines following ADDR1. `ADDR1,~N' Matches ADDR1 and the lines following ADDR1 until the next line whose input line number is a multiple of N. Appending the `!' character to the end of an address specification negates the sense of the match. That is, if the `!' character follows an address range, then only lines which do _not_ match the address range will be selected. This also works for singleton addresses, and, perhaps perversely, for the null address.  File: sed.info, Node: Regular Expressions, Next: Common Commands, Prev: Addresses, Up: sed Programs Overview of Regular Expression Syntax ===================================== To know how to use `sed', people should understand regular expressions ("regexp" for short). A regular expression is a pattern that is matched against a subject string from left to right. Most characters are "ordinary": they stand for themselves in a pattern, and match the corresponding characters in the subject. As a trivial example, the pattern The quick brown fox matches a portion of a subject string that is identical to itself. The power of regular expressions comes from the ability to include alternatives and repetitions in the pattern. These are encoded in the pattern by the use of "special characters", which do not stand for themselves but instead are interpreted in some special way. Here is a brief description of regular expression syntax as used in `sed'. `CHAR' A single ordinary character matches itself. `*' Matches a sequence of zero or more instances of matches for the preceding regular expression, which must be an ordinary character, a special character preceded by `\', a `.', a grouped regexp (see below), or a bracket expression. As a GNU extension, a postfixed regular expression can also be followed by `*'; for example, `a**' is equivalent to `a*'. POSIX 1003.1-2001 says that `*' stands for itself when it appears at the start of a regular expression or subexpression, but many nonGNU implementations do not support this and portable scripts should instead use `\*' in these contexts. `\+' As `*', but matches one or more. It is a GNU extension. `\?' As `*', but only matches zero or one. It is a GNU extension. `\{I\}' As `*', but matches exactly I sequences (I is a decimal integer; for portability, keep it between 0 and 255 inclusive). `\{I,J\}' Matches between I and J, inclusive, sequences. `\{I,\}' Matches more than or equal to I sequences. `\(REGEXP\)' Groups the inner REGEXP as a whole, this is used to: * Apply postfix operators, like `\(abcd\)*': this will search for zero or more whole sequences of `abcd', while `abcd*' would search for `abc' followed by zero or more occurrences of `d'. Note that support for `\(abcd\)*' is required by POSIX 1003.1-2001, but many non-GNU implementations do not support it and hence it is not universally portable. * Use back references (see below). `.' Matches any character, including newline. `^' Matches the null string at beginning of line, i.e. what appears after the circumflex must appear at the beginning of line. `^#include' will match only lines where `#include' is the first thing on line--if there are spaces before, for example, the match fails. `^' acts as a special character only at the beginning of the regular expression or subexpression (that is, after `\(' or `\|'). Portable scripts should avoid `^' at the beginning of a subexpression, though, as POSIX allows implementations that treat `^' as an ordinary character in that context. `$' It is the same as `^', but refers to end of line. `$' also acts as a special character only at the end of the regular expression or subexpression (that is, before `\)' or `\|'), and its use at the end of a subexpression is not portable. `[LIST]' `[^LIST]' Matches any single character in LIST: for example, `[aeiou]' matches all vowels. A list may include sequences like `CHAR1-CHAR2', which matches any character between (inclusive) CHAR1 and CHAR2. A leading `^' reverses the meaning of LIST, so that it matches any single character _not_ in LIST. To include `]' in the list, make it the first character (after the `^' if needed), to include `-' in the list, make it the first or last; to include `^' put it after the first character. The characters `$', `*', `.', `[', and `\' are normally not special within LIST. For example, `[\*]' matches either `\' or `*', because the `\' is not special here. However, strings like `[.ch.]', `[=a=]', and `[:space:]' are special within LIST and represent collating symbols, equivalence classes, and character classes, respectively, and `[' is therefore special within LIST when it is followed by `.', `=', or `:'. Also, when not in `POSIXLY_CORRECT' mode, special escapes like `\n' and `\t' are recognized within LIST. *Note Escapes::. `REGEXP1\|REGEXP2' Matches either REGEXP1 or REGEXP2. Use parentheses to use complex alternative regular expressions. The matching process tries each alternative in turn, from left to right, and the first one that succeeds is used. It is a GNU extension. `REGEXP1REGEXP2' Matches the concatenation of REGEXP1 and REGEXP2. Concatenation binds more tightly than `\|', `^', and `$', but less tightly than the other regular expression operators. `\DIGIT' Matches the DIGIT-th `\(...\)' parenthesized subexpression in the regular expression. This is called a "back reference". Subexpressions are implicity numbered by counting occurrences of `\(' left-to-right. `\n' Matches the newline character. `\CHAR' Matches CHAR, where CHAR is one of `$', `*', `.', `[', `\', or `^'. Note that the only C-like backslash sequences that you can portably assume to be interpreted are `\n' and `\\'; in particular `\t' is not portable, and matches a `t' under most implementations of `sed', rather than a tab character. Note that the regular expression matcher is greedy, i.e., matches are attempted from left to right and, if two or more matches are possible starting at the same character, it selects the longest. Examples: `abcdef' Matches `abcdef'. `a*b' Matches zero or more `a's followed by a single `b'. For example, `b' or `aaaaab'. `a\?b' Matches `b' or `ab'. `a\+b\+' Matches one or more `a's followed by one or more `b's: `ab' is the shortest possible match, but other examples are `aaaab' or `abbbbb' or `aaaaaabbbbbbb'. `.*' `.\+' These two both match all the characters in a string; however, the first matches every string (including the empty string), while the second matches only strings containing at least one character. `^main.*(.*)' his matches a string starting with `main', followed by an opening and closing parenthesis. The `n', `(' and `)' need not be adjacent. `^#' This matches a string beginning with `#'. `\\$' This matches a string ending with a single backslash. The regexp contains two backslashes for escaping. `\$' Instead, this matches a string consisting of a single dollar sign, because it is escaped. `[a-zA-Z0-9]' In the C locale, this matches any ASCII letters or digits. `[^ tab]\+' (Here `tab' stands for a single tab character.) This matches a string of one or more characters, none of which is a space or a tab. Usually this means a word. `^\(.*\)\n\1$' This matches a string consisting of two equal substrings separated by a newline. `.\{9\}A$' This matches nine characters followed by an `A'. `^.\{15\}A' This matches the start of a string that contains 16 characters, the last of which is an `A'.  File: sed.info, Node: Common Commands, Next: The "s" Command, Prev: Regular Expressions, Up: sed Programs Often-Used Commands =================== If you use `sed' at all, you will quite likely want to know these commands. `#' [No addresses allowed.] The `#' character begins a comment; the comment continues until the next newline. If you are concerned about portability, be aware that some implementations of `sed' (which are not POSIX conformant) may only support a single one-line comment, and then only when the very first character of the script is a `#'. Warning: if the first two characters of the `sed' script are `#n', then the `-n' (no-autoprint) option is forced. If you want to put a comment in the first line of your script and that comment begins with the letter `n' and you do not want this behavior, then be sure to either use a capital `N', or place at least one space before the `n'. `q [EXIT-CODE]' This command only accepts a single address. Exit `sed' without processing any more commands or input. Note that the current pattern space is printed if auto-print is not disabled with the `-n' options. The ability to return an exit code from the `sed' script is a GNU `sed' extension. `d' Delete the pattern space; immediately start next cycle. `p' Print out the pattern space (to the standard output). This command is usually only used in conjunction with the `-n' command-line option. `n' If auto-print is not disabled, print the pattern space, then, regardless, replace the pattern space with the next line of input. If there is no more input then `sed' exits without processing any more commands. `{ COMMANDS }' A group of commands may be enclosed between `{' and `}' characters. This is particularly useful when you want a group of commands to be triggered by a single address (or address-range) match.  File: sed.info, Node: The "s" Command, Next: Other Commands, Prev: Common Commands, Up: sed Programs The `s' Command =============== The syntax of the `s' (as in substitute) command is `s/REGEXP/REPLACEMENT/FLAGS'. The `/' characters may be uniformly replaced by any other single character within any given `s' command. The `/' character (or whatever other character is used in its stead) can appear in the REGEXP or REPLACEMENT only if it is preceded by a `\' character. The `s' command is probably the most important in `sed' and has a lot of different options. Its basic concept is simple: the `s' command attempts to match the pattern space against the supplied REGEXP; if the match is successful, then that portion of the pattern space which was matched is replaced with REPLACEMENT. The REPLACEMENT can contain `\N' (N being a number from 1 to 9, inclusive) references, which refer to the portion of the match which is contained between the Nth `\(' and its matching `\)'. Also, the REPLACEMENT can contain unescaped `&' characters which reference the whole matched portion of the pattern space. Finally, as a GNU `sed' extension, you can include a special sequence made of a backslash and one of the letters `L', `l', `U', `u', or `E'. The meaning is as follows: `\L' Turn the replacement to lowercase until a `\U' or `\E' is found, `\l' Turn the next character to lowercase, `\U' Turn the replacement to uppercase until a `\L' or `\E' is found, `\u' Turn the next character to uppercase, `\E' Stop case conversion started by `\L' or `\U'. To include a literal `\', `&', or newline in the final replacement, be sure to precede the desired `\', `&', or newline in the REPLACEMENT with a `\'. The `s' command can be followed by zero or more of the following FLAGS: `g' Apply the replacement to _all_ matches to the REGEXP, not just the first. `NUMBER' Only replace the NUMBERth match of the REGEXP. Note: the POSIX standard does not specify what should happen when you mix the `g' and NUMBER modifiers, and currently there is no widely agreed upon meaning across `sed' implementations. For GNU `sed', the interaction is defined to be: ignore matches before the NUMBERth, and then match and replace all matches from the NUMBERth on. `p' If the substitution was made, then print the new pattern space. Note: when both the `p' and `e' options are specified, the relative ordering of the two produces very different results. In general, `ep' (evaluate then print) is what you want, but operating the other way round can be useful for debugging. For this reason, the current version of GNU `sed' interprets specially the presence of `p' options both before and after `e', printing the pattern space before and after evaluation, while in general flags for the `s' command show their effect just once. This behavior, although documented, might change in future versions. `w FILE-NAME' If the substitution was made, then write out the result to the named file. As a GNU `sed' extension, two special values of FILE-NAME are supported: `/dev/stderr', which writes the result to the standard error, and `/dev/stdout', which writes to the standard output.(1) `e' This command allows one to pipe input from a shell command into pattern space. If a substitution was made, the command that is found in pattern space is executed and pattern space is replaced with its output. A trailing newline is suppressed; results are undefined if the command to be executed contains a NUL character. This is a GNU `sed' extension. `I' `i' The `I' modifier to regular-expression matching is a GNU extension which makes `sed' match REGEXP in a case-insensitive manner. `M' `m' The `M' modifier to regular-expression matching is a GNU `sed' extension which causes `^' and `$' to match respectively (in addition to the normal behavior) the empty string after a newline, and the empty string before a newline. There are special character sequences (`\`' and `\'') which always match the beginning or the end of the buffer. `M' stands for `multi-line'. ---------- Footnotes ---------- (1) This is equivalent to `p' unless the `-i' option is being used.  File: sed.info, Node: Other Commands, Next: Programming Commands, Prev: The "s" Command, Up: sed Programs Less Frequently-Used Commands ============================= Though perhaps less frequently used than those in the previous section, some very small yet useful `sed' scripts can be built with these commands. `y/SOURCE-CHARS/DEST-CHARS/' (The `/' characters may be uniformly replaced by any other single character within any given `y' command.) Transliterate any characters in the pattern space which match any of the SOURCE-CHARS with the corresponding character in DEST-CHARS. Instances of the `/' (or whatever other character is used in its stead), `\', or newlines can appear in the SOURCE-CHARS or DEST-CHARS lists, provide that each instance is escaped by a `\'. The SOURCE-CHARS and DEST-CHARS lists _must_ contain the same number of characters (after de-escaping). `a\' `TEXT' As a GNU extension, this command accepts two addresses. Queue the lines of text which follow this command (each but the last ending with a `\', which are removed from the output) to be output at the end of the current cycle, or when the next input line is read. Escape sequences in TEXT are processed, so you should use `\\' in TEXT to print a single backslash. As a GNU extension, if between the `a' and the newline there is other than a whitespace-`\' sequence, then the text of this line, starting at the first non-whitespace character after the `a', is taken as the first line of the TEXT block. (This enables a simplification in scripting a one-line add.) This extension also works with the `i' and `c' commands. `i\' `TEXT' As a GNU extension, this command accepts two addresses. Immediately output the lines of text which follow this command (each but the last ending with a `\', which are removed from the output). `c\' `TEXT' Delete the lines matching the address or address-range, and output the lines of text which follow this command (each but the last ending with a `\', which are removed from the output) in place of the last line (or in place of each line, if no addresses were specified). A new cycle is started after this command is done, since the pattern space will have been deleted. `=' As a GNU extension, this command accepts two addresses. Print out the current input line number (with a trailing newline). `l N' Print the pattern space in an unambiguous form: non-printable characters (and the `\' character) are printed in C-style escaped form; long lines are split, with a trailing `\' character to indicate the split; the end of each line is marked with a `$'. N specifies the desired line-wrap length; a length of 0 (zero) means to never wrap long lines. If omitted, the default as specified on the command line is used. The N parameter is a GNU `sed' extension. `r FILENAME' As a GNU extension, this command accepts two addresses. Queue the contents of FILENAME to be read and inserted into the output stream at the end of the current cycle, or when the next input line is read. Note that if FILENAME cannot be read, it is treated as if it were an empty file, without any error indication. As a GNU `sed' extension, the special value `/dev/stdin' is supported for the file name, which reads the contents of the standard input. `w FILENAME' Write the pattern space to FILENAME. As a GNU `sed' extension, two special values of FILE-NAME are supported: `/dev/stderr', which writes the result to the standard error, and `/dev/stdout', which writes to the standard output.(1) The file will be created (or truncated) before the first input line is read; all `w' commands (including instances of `w' flag on successful `s' commands) which refer to the same FILENAME are output without closing and reopening the file. `D' Delete text in the pattern space up to the first newline. If any text is left, restart cycle with the resultant pattern space (without reading a new line of input), otherwise start a normal new cycle. `N' Add a newline to the pattern space, then append the next line of input to the pattern space. If there is no more input then `sed' exits without processing any more commands. `P' Print out the portion of the pattern space up to the first newline. `h' Replace the contents of the hold space with the contents of the pattern space. `H' Append a newline to the contents of the hold space, and then append the contents of the pattern space to that of the hold space. `g' Replace the contents of the pattern space with the contents of the hold space. `G' Append a newline to the contents of the pattern space, and then append the contents of the hold space to that of the pattern space. `x' Exchange the contents of the hold and pattern spaces. ---------- Footnotes ---------- (1) This is equivalent to `p' unless the `-i' option is being used.  File: sed.info, Node: Programming Commands, Next: Extended Commands, Prev: Other Commands, Up: sed Programs Commands for `sed' gurus ======================== In most cases, use of these commands indicates that you are probably better off programming in something like `awk' or Perl. But occasionally one is committed to sticking with `sed', and these commands can enable one to write quite convoluted scripts. `: LABEL' [No addresses allowed.] Specify the location of LABEL for branch commands. In all other respects, a no-op. `b LABEL' Unconditionally branch to LABEL. The LABEL may be omitted, in which case the next cycle is started. `t LABEL' Branch to LABEL only if there has been a successful `s'ubstitution since the last input line was read or conditional branch was taken. The LABEL may be omitted, in which case the next cycle is started.  File: sed.info, Node: Extended Commands, Next: Escapes, Prev: Programming Commands, Up: sed Programs Commands Specific to GNU `sed' ============================== These commands are specific to GNU `sed', so you must use them with care and only when you are sure that hindering portability is not evil. They allow you to check for GNU `sed' extensions or to do tasks that are required quite often, yet are unsupported by standard `sed's. `e [COMMAND]' This command allows one to pipe input from a shell command into pattern space. Without parameters, the `e' command executes the command that is found in pattern space and replaces the pattern space with the output; a trailing newline is suppressed. If a parameter is specified, instead, the `e' command interprets it as a command and sends its output to the output stream (like `r' does). The command can run across multiple lines, all but the last ending with a back-slash. In both cases, the results are undefined if the command to be executed contains a NUL character. `L N' This GNU `sed' extension fills and joins lines in pattern space to produce output lines of (at most) N characters, like `fmt' does; if N is omitted, the default as specified on the command line is used. This command is considered a failed experiment and unless there is enough request (which seems unlikely) will be removed in future versions. `Q [EXIT-CODE]' This command only accepts a single address. This command is the same as `q', but will not print the contents of pattern space. Like `q', it provides the ability to return an exit code to the caller. This command can be useful because the only alternative ways to accomplish this apparently trivial function are to use the `-n' option (which can unnecessarily complicate your script) or resorting to the following snippet, which wastes time by reading the whole file without any visible effect: :eat $d Quit silently on the last line N Read another line, silently g Overwrite pattern space each time to save memory b eat `R FILENAME' Queue a line of FILENAME to be read and inserted into the output stream at the end of the current cycle, or when the next input line is read. Note that if FILENAME cannot be read, or if its end is reached, no line is appended, without any error indication. As with the `r' command, the special value `/dev/stdin' is supported for the file name, which reads a line from the standard input. `T LABEL' Branch to LABEL only if there have been no successful `s'ubstitutions since the last input line was read or conditional branch was taken. The LABEL may be omitted, in which case the next cycle is started. `v VERSION' This command does nothing, but makes `sed' fail if GNU `sed' extensions are not supported, simply because other versions of `sed' do not implement it. In addition, you can specify the version of `sed' that your script requires, such as `4.0.5'. The default is `4.0' because that is the first version that implemented this command. This command enables all GNU extensions even if `POSIXLY_CORRECT' is set in the environment. `W FILENAME' Write to the given filename the portion of the pattern space up to the first newline. Everything said under the `w' command about file handling holds here too.  File: sed.info, Node: Escapes, Prev: Extended Commands, Up: sed Programs GNU Extensions for Escapes in Regular Expressions ================================================= Until this chapter, we have only encountered escapes of the form `\^', which tell `sed' not to interpret the circumflex as a special character, but rather to take it literally. For example, `\*' matches a single asterisk rather than zero or more backslashes. This chapter introduces another kind of escape(1)--that is, escapes that are applied to a character or sequence of characters that ordinarily are taken literally, and that `sed' replaces with a special character. This provides a way of encoding non-printable characters in patterns in a visible manner. There is no restriction on the appearance of non-printing characters in a `sed' script but when a script is being prepared in the shell or by text editing, it is usually easier to use one of the following escape sequences than the binary character it represents: The list of these escapes is: `\a' Produces or matches a BEL character, that is an "alert" (ASCII 7). `\f' Produces or matches a form feed (ASCII 12). `\n' Produces or matches a newline (ASCII 10). `\r' Produces or matches a carriage return (ASCII 13). `\t' Produces or matches a horizontal tab (ASCII 9). `\v' Produces or matches a so called "vertical tab" (ASCII 11). `\cX' Produces or matches `CONTROL-X', where X is any character. The precise effect of `\cX' is as follows: if X is a lower case letter, it is converted to upper case. Then bit 6 of the character (hex 40) is inverted. Thus `\cz' becomes hex 1A, but `\c{' becomes hex 3B, while `\c;' becomes hex 7B. `\dXXX' Produces or matches a character whose decimal ASCII value is XXX. `\oXXX' Produces or matches a character whose octal ASCII value is XXX. `\xXX' Produces or matches a character whose hexadecimal ASCII value is XX. `\b' (backspace) was omitted because of the conflict with the existing "word boundary" meaning. Other escapes match a particular character class and are valid only in regular expressions: `\w' Matches any "word" character. A "word" character is any letter or digit or the underscore character. `\W' Matches any "non-word" character. `\b' Matches a word boundary; that is it matches if the character to the left is a "word" character and the character to the right is a "non-word" character, or vice-versa. `\B' Matches everywhere but on a word boundary; that is it matches if the character to the left and the character to the right are either both "word" characters or both "non-word" characters. `\`' Matches only at the start of pattern space. This is different from `^' in multi-line mode. `\'' Matches only at the end of pattern space. This is different from `$' in multi-line mode. ---------- Footnotes ---------- (1) All the escapes introduced here are GNU extensions, with the exception of `\n'. In basic regular expression mode, setting `POSIXLY_CORRECT' disables them inside bracket expressions.  File: sed.info, Node: Examples, Next: Limitations, Prev: sed Programs, Up: Top Some Sample Scripts ******************* Here are some `sed' scripts to guide you in the art of mastering `sed'. * Menu: Some exotic examples: * Centering lines:: * Increment a number:: * Rename files to lower case:: * Print bash environment:: * Reverse chars of lines:: Emulating standard utilities: * tac:: Reverse lines of files * cat -n:: Numbering lines * cat -b:: Numbering non-blank lines * wc -c:: Counting chars * wc -w:: Counting words * wc -l:: Counting lines * head:: Printing the first lines * tail:: Printing the last lines * uniq:: Make duplicate lines unique * uniq -d:: Print duplicated lines of input * uniq -u:: Remove all duplicated lines * cat -s:: Squeezing blank lines  File: sed.info, Node: Centering lines, Next: Increment a number, Up: Examples Centering Lines =============== This script centers all lines of a file on a 80 columns width. To change that width, the number in `\{...\}' must be replaced, and the number of added spaces also must be changed. Note how the buffer commands are used to separate parts in the regular expressions to be matched--this is a common technique. #!/usr/bin/sed -f # Put 80 spaces in the buffer 1 { x s/^$/ / s/^.*$/&&&&&&&&/ x } # del leading and trailing spaces y/tab/ / s/^ *// s/ *$// # add a newline and 80 spaces to end of line G # keep first 81 chars (80 + a newline) s/^\(.\{81\}\).*$/\1/ # \2 matches half of the spaces, which are moved to the beginning s/^\(.*\)\n\(.*\)\2/\2\1/  File: sed.info, Node: Increment a number, Next: Rename files to lower case, Prev: Centering lines, Up: Examples Increment a Number ================== This script is one of a few that demonstrate how to do arithmetic in `sed'. This is indeed possible,(1) but must be done manually. To increment one number you just add 1 to last digit, replacing it by the following digit. There is one exception: when the digit is a nine the previous digits must be also incremented until you don't have a nine. This solution by Bruno Haible is very clever and smart because it uses a single buffer; if you don't have this limitation, the algorithm used in *Note Numbering lines: cat -n, is faster. It works by replacing trailing nines with an underscore, then using multiple `s' commands to increment the last digit, and then again substituting underscores with zeros. #!/usr/bin/sed -f /[^0-9]/ d # replace all leading 9s by _ (any other character except digits, could # be used) :d s/9\(_*\)$/_\1/ td # incr last digit only. The first line adds a most-significant # digit of 1 if we have to add a digit. # # The `tn' commands are not necessary, but make the thing # faster s/^\(_*\)$/1\1/; tn s/8\(_*\)$/9\1/; tn s/7\(_*\)$/8\1/; tn s/6\(_*\)$/7\1/; tn s/5\(_*\)$/6\1/; tn s/4\(_*\)$/5\1/; tn s/3\(_*\)$/4\1/; tn s/2\(_*\)$/3\1/; tn s/1\(_*\)$/2\1/; tn s/0\(_*\)$/1\1/; tn :n y/_/0/ ---------- Footnotes ---------- (1) `sed' guru Greg Ubben wrote an implementation of the `dc' RPN calculator! It is distributed together with sed.  File: sed.info, Node: Rename files to lower case, Next: Print bash environment, Prev: Increment a number, Up: Examples Rename Files to Lower Case ========================== This is a pretty strange use of `sed'. We transform text, and transform it to be shell commands, then just feed them to shell. Don't worry, even worse hacks are done when using `sed'; I have seen a script converting the output of `date' into a `bc' program! The main body of this is the `sed' script, which remaps the name from lower to upper (or vice-versa) and even checks out if the remapped name is the same as the original name. Note how the script is parameterized using shell variables and proper quoting. #! /bin/sh # rename files to lower/upper case... # # usage: # move-to-lower * # move-to-upper * # or # move-to-lower -R . # move-to-upper -R . # help() { cat << eof Usage: $0 [-n] [-r] [-h] files... -n do nothing, only see what would be done -R recursive (use find) -h this message files files to remap to lower case Examples: $0 -n * (see if everything is ok, then...) $0 * $0 -R . eof } apply_cmd='sh' finder='echo "$@" | tr " " "\n"' files_only= while : do case "$1" in -n) apply_cmd='cat' ;; -R) finder='find "$@" -type f';; -h) help ; exit 1 ;; *) break ;; esac shift done if [ -z "$1" ]; then echo Usage: $0 [-h] [-n] [-r] files... exit 1 fi LOWER='abcdefghijklmnopqrstuvwxyz' UPPER='ABCDEFGHIJKLMNOPQRSTUVWXYZ' case `basename $0` in *upper*) TO=$UPPER; FROM=$LOWER ;; *) FROM=$UPPER; TO=$LOWER ;; esac eval $finder | sed -n ' # remove all trailing slashes s/\/*$// # add ./ if there is no path, only a filename /\//! s/^/.\// # save path+filename h # remove path s/.*\/// # do conversion only on filename y/'$FROM'/'$TO'/ # now line contains original path+file, while # hold space contains the new filename x # add converted file name to line, which now contains # path/file-name\nconverted-file-name G # check if converted file name is equal to original file name, # if it is, do not print nothing /^.*\/\(.*\)\n\1/b # now, transform path/fromfile\n, into # mv path/fromfile path/tofile and print it s/^\(.*\/\)\(.*\)\n\(.*\)$/mv "\1\2" "\1\3"/p ' | $apply_cmd kbuild-3686/src/oldsed/doc/Makefile.am0000664000175000017500000000307415053010105017550 0ustar locutuslocutus## Process this file with automake to produce Makefile.in info_TEXINFOS = sed.texi sed_TEXINFOS = config.texi version.texi dist_man_MANS = sed.1 dist_noinst_DATA = sed.x sed-in.texi dist_noinst_SCRIPTS = groupify.sed CLEANFILES = sed.html TEXI2DVI = $(top_srcdir)/config/texi2dvi --expand HELP2MAN = $(top_srcdir)/config/help2man SED = $(top_builddir)/sed/sed # To produce better quality output, in the example sed # scripts we group comments with lines following them; # since mantaining the "@group...@end group" manually # is a burden, we do this automatically $(srcdir)/sed.texi: sed-in.texi $(srcdir)/groupify.sed sed -nf $(srcdir)/groupify.sed \ < $(srcdir)/sed-in.texi > $(srcdir)/sed.texi sed.1: $(top_srcdir)/sed/sed.c $(top_srcdir)/configure.ac $(srcdir)/sed.x $(HELP2MAN) --name "stream editor for filtering and transforming text" \ -p sed --include $(srcdir)/sed.x $(SED) > $(srcdir)/sed.1 dist-hook: touch $(distdir)/sed.1 # This rule is used if --enable-html is passed if BUILD_HTML docdir = $(datadir)/doc pkgdocdir = $(datadir)/doc/$(PACKAGE)-$(VERSION) pkgdoc_DATA = sed.html all: html html: sed.html .PHONY: html endif # Having a dependancy on sed.info automatically makes # sed.html dependant on sed.texi and all the included # sources if MAKEINFO_HTML sed.html: sed.texi sed.info builddir=`pwd` && cd $(srcdir) && \ $(MAKEINFO) --html --no-split -o $$builddir/sed.html sed.texi endif # These rules are used together with TEXI2HTML if TEXI2HTML_HTML sed.html: sed.texi sed.info cp $(srcdir)/*.texi . && \ $(TEXI2HTML) sed.texi && \ rm *.texi endif kbuild-3686/src/oldsed/doc/stamp-vti0000664000175000017500000000014315053010105017355 0ustar locutuslocutus@set UPDATED 30 January 2006 @set UPDATED-MONTH January 2006 @set EDITION 4.1.5 @set VERSION 4.1.5 kbuild-3686/src/oldsed/doc/Makefile.in0000664000175000017500000004765315053010105017574 0ustar locutuslocutus# Makefile.in generated by automake 1.9.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = doc DIST_COMMON = $(dist_man_MANS) $(dist_noinst_DATA) \ $(dist_noinst_SCRIPTS) $(sed_TEXINFOS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/stamp-vti \ $(srcdir)/version.texi ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/codeset.m4 \ $(top_srcdir)/config/getline.m4 \ $(top_srcdir)/config/gettext-ver.m4 \ $(top_srcdir)/config/gettext.m4 \ $(top_srcdir)/config/glibc21.m4 $(top_srcdir)/config/iconv.m4 \ $(top_srcdir)/config/lcmessage.m4 \ $(top_srcdir)/config/lib-ld.m4 \ $(top_srcdir)/config/lib-link.m4 \ $(top_srcdir)/config/lib-prefix.m4 \ $(top_srcdir)/config/progtest.m4 \ $(top_srcdir)/config/stdbool.m4 \ $(top_srcdir)/config/strverscmp.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = SCRIPTS = $(dist_noinst_SCRIPTS) SOURCES = DIST_SOURCES = INFO_DEPS = $(srcdir)/sed.info TEXINFO_TEX = $(top_srcdir)/config/texinfo.tex am__TEXINFO_TEX_DIR = $(top_srcdir)/config DVIS = sed.dvi PDFS = sed.pdf PSS = sed.ps HTMLS = sed.html TEXINFOS = sed.texi TEXI2PDF = $(TEXI2DVI) --pdf --batch MAKEINFOHTML = $(MAKEINFO) --html AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS) DVIPS = dvips am__installdirs = "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)" \ "$(DESTDIR)$(pkgdocdir)" man1dir = $(mandir)/man1 NROFF = nroff MANS = $(dist_man_MANS) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; pkgdocDATA_INSTALL = $(INSTALL_DATA) DATA = $(dist_noinst_DATA) $(pkgdoc_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_HTML_FALSE = @BUILD_HTML_FALSE@ BUILD_HTML_TRUE = @BUILD_HTML_TRUE@ BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GENCAT = @GENCAT@ GLIBC21 = @GLIBC21@ GMSGFMT = @GMSGFMT@ HAVE__BOOL = @HAVE__BOOL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLBISON = @INTLBISON@ INTLLIBS = @INTLLIBS@ INTLOBJS = @INTLOBJS@ INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MAKEINFO_HTML_FALSE = @MAKEINFO_HTML_FALSE@ MAKEINFO_HTML_TRUE = @MAKEINFO_HTML_TRUE@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ RANLIB = @RANLIB@ SED_FEATURE_VERSION = @SED_FEATURE_VERSION@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TEST_REGEX_FALSE = @TEST_REGEX_FALSE@ TEST_REGEX_TRUE = @TEST_REGEX_TRUE@ TEXI2HTML = @TEXI2HTML@ TEXI2HTML_HTML_FALSE = @TEXI2HTML_HTML_FALSE@ TEXI2HTML_HTML_TRUE = @TEXI2HTML_HTML_TRUE@ USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ info_TEXINFOS = sed.texi sed_TEXINFOS = config.texi version.texi dist_man_MANS = sed.1 dist_noinst_DATA = sed.x sed-in.texi dist_noinst_SCRIPTS = groupify.sed CLEANFILES = sed.html TEXI2DVI = $(top_srcdir)/config/texi2dvi --expand HELP2MAN = $(top_srcdir)/config/help2man SED = $(top_builddir)/sed/sed # This rule is used if --enable-html is passed @BUILD_HTML_TRUE@docdir = $(datadir)/doc @BUILD_HTML_TRUE@pkgdocdir = $(datadir)/doc/$(PACKAGE)-$(VERSION) @BUILD_HTML_TRUE@pkgdoc_DATA = sed.html all: all-am .SUFFIXES: .SUFFIXES: .dvi .html .info .pdf .ps .texi $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits doc/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnits doc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh .texi.info: restore=: && backupdir="$(am__leading_dot)am$$$$" && \ am__cwd=`pwd` && cd $(srcdir) && \ rm -rf $$backupdir && mkdir $$backupdir && \ for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \ if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \ done; \ cd "$$am__cwd"; \ if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ -o $@ $<; \ then \ rc=0; \ cd $(srcdir); \ else \ rc=$$?; \ cd $(srcdir) && \ $$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \ fi; \ rm -rf $$backupdir; exit $$rc .texi.dvi: TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ $(TEXI2DVI) $< .texi.pdf: TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ $(TEXI2PDF) $< .texi.html: rm -rf $(@:.html=.htp) if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ -o $(@:.html=.htp) $<; \ then \ rm -rf $@; \ if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \ else \ if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \ exit 1; \ fi $(srcdir)/sed.info: sed.texi $(srcdir)/version.texi $(sed_TEXINFOS) sed.dvi: sed.texi $(srcdir)/version.texi $(sed_TEXINFOS) sed.pdf: sed.texi $(srcdir)/version.texi $(sed_TEXINFOS) @MAKEINFO_HTML_FALSE@@TEXI2HTML_HTML_FALSE@sed.html: sed.texi $(srcdir)/version.texi $(sed_TEXINFOS) $(srcdir)/version.texi: $(srcdir)/stamp-vti $(srcdir)/stamp-vti: sed.texi $(top_srcdir)/configure @(dir=.; test -f ./sed.texi || dir=$(srcdir); \ set `$(SHELL) $(top_srcdir)/config/mdate-sh $$dir/sed.texi`; \ echo "@set UPDATED $$1 $$2 $$3"; \ echo "@set UPDATED-MONTH $$2 $$3"; \ echo "@set EDITION $(VERSION)"; \ echo "@set VERSION $(VERSION)") > vti.tmp @cmp -s vti.tmp $(srcdir)/version.texi \ || (echo "Updating $(srcdir)/version.texi"; \ cp vti.tmp $(srcdir)/version.texi) -@rm -f vti.tmp @cp $(srcdir)/version.texi $@ mostlyclean-vti: -rm -f vti.tmp maintainer-clean-vti: -rm -f $(srcdir)/stamp-vti $(srcdir)/version.texi .dvi.ps: $(DVIPS) -o $@ $< uninstall-info-am: @$(PRE_UNINSTALL) @if (install-info --version && \ install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \ list='$(INFO_DEPS)'; \ for file in $$list; do \ relfile=`echo "$$file" | sed 's|^.*/||'`; \ echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \ install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \ done; \ else :; fi @$(NORMAL_UNINSTALL) @list='$(INFO_DEPS)'; \ for file in $$list; do \ relfile=`echo "$$file" | sed 's|^.*/||'`; \ relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \ (if cd "$(DESTDIR)$(infodir)"; then \ echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \ rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \ else :; fi); \ done dist-info: $(INFO_DEPS) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ list='$(INFO_DEPS)'; \ for base in $$list; do \ case $$base in \ $(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \ esac; \ if test -f $$base; then d=.; else d=$(srcdir); fi; \ for file in $$d/$$base*; do \ relfile=`expr "$$file" : "$$d/\(.*\)"`; \ test -f $(distdir)/$$relfile || \ cp -p $$file $(distdir)/$$relfile; \ done; \ done mostlyclean-aminfo: -rm -rf sed.aux sed.cp sed.cps sed.fn sed.fns sed.ky sed.log sed.op sed.pg \ sed.tmp sed.toc sed.tp sed.vr sed.vrs sed.dvi sed.pdf sed.ps \ sed.html maintainer-clean-aminfo: @list='$(INFO_DEPS)'; for i in $$list; do \ i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \ echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \ rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \ done install-man1: $(man1_MANS) $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man1dir)" || $(mkdir_p) "$(DESTDIR)$(man1dir)" @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 1*) ;; \ *) ext='1' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \ done uninstall-man1: @$(NORMAL_UNINSTALL) @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 1*) ;; \ *) ext='1' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \ rm -f "$(DESTDIR)$(man1dir)/$$inst"; \ done install-pkgdocDATA: $(pkgdoc_DATA) @$(NORMAL_INSTALL) test -z "$(pkgdocdir)" || $(mkdir_p) "$(DESTDIR)$(pkgdocdir)" @list='$(pkgdoc_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(pkgdocDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgdocdir)/$$f'"; \ $(pkgdocDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgdocdir)/$$f"; \ done uninstall-pkgdocDATA: @$(NORMAL_UNINSTALL) @list='$(pkgdoc_DATA)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(pkgdocdir)/$$f'"; \ rm -f "$(DESTDIR)$(pkgdocdir)/$$f"; \ done tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-info dist-hook check-am: all-am check: check-am all-am: Makefile $(INFO_DEPS) $(SCRIPTS) $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(pkgdocdir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: $(DVIS) @BUILD_HTML_FALSE@html: html-am html-am: $(HTMLS) info: info-am info-am: $(INFO_DEPS) install-data-am: install-info-am install-man install-pkgdocDATA install-exec-am: install-info: install-info-am install-info-am: $(INFO_DEPS) @$(NORMAL_INSTALL) test -z "$(infodir)" || $(mkdir_p) "$(DESTDIR)$(infodir)" @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ list='$(INFO_DEPS)'; \ for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ esac; \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \ for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \ $$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \ if test -f $$ifile; then \ relfile=`echo "$$ifile" | sed 's|^.*/||'`; \ echo " $(INSTALL_DATA) '$$ifile' '$(DESTDIR)$(infodir)/$$relfile'"; \ $(INSTALL_DATA) "$$ifile" "$(DESTDIR)$(infodir)/$$relfile"; \ else : ; fi; \ done; \ done @$(POST_INSTALL) @if (install-info --version && \ install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \ list='$(INFO_DEPS)'; \ for file in $$list; do \ relfile=`echo "$$file" | sed 's|^.*/||'`; \ echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\ install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\ done; \ else : ; fi install-man: install-man1 installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-aminfo \ maintainer-clean-generic maintainer-clean-vti mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-aminfo mostlyclean-generic mostlyclean-vti pdf: pdf-am pdf-am: $(PDFS) ps: ps-am ps-am: $(PSS) uninstall-am: uninstall-info-am uninstall-man uninstall-pkgdocDATA uninstall-man: uninstall-man1 .PHONY: all all-am check check-am clean clean-generic dist-hook \ dist-info distclean distclean-generic distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-man1 install-pkgdocDATA \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-aminfo \ maintainer-clean-generic maintainer-clean-vti mostlyclean \ mostlyclean-aminfo mostlyclean-generic mostlyclean-vti pdf \ pdf-am ps ps-am uninstall uninstall-am uninstall-info-am \ uninstall-man uninstall-man1 uninstall-pkgdocDATA # To produce better quality output, in the example sed # scripts we group comments with lines following them; # since mantaining the "@group...@end group" manually # is a burden, we do this automatically $(srcdir)/sed.texi: sed-in.texi $(srcdir)/groupify.sed sed -nf $(srcdir)/groupify.sed \ < $(srcdir)/sed-in.texi > $(srcdir)/sed.texi sed.1: $(top_srcdir)/sed/sed.c $(top_srcdir)/configure.ac $(srcdir)/sed.x $(HELP2MAN) --name "stream editor for filtering and transforming text" \ -p sed --include $(srcdir)/sed.x $(SED) > $(srcdir)/sed.1 dist-hook: touch $(distdir)/sed.1 @BUILD_HTML_TRUE@all: html @BUILD_HTML_TRUE@html: sed.html @BUILD_HTML_TRUE@.PHONY: html # Having a dependancy on sed.info automatically makes # sed.html dependant on sed.texi and all the included # sources @MAKEINFO_HTML_TRUE@sed.html: sed.texi sed.info @MAKEINFO_HTML_TRUE@ builddir=`pwd` && cd $(srcdir) && \ @MAKEINFO_HTML_TRUE@ $(MAKEINFO) --html --no-split -o $$builddir/sed.html sed.texi # These rules are used together with TEXI2HTML @TEXI2HTML_HTML_TRUE@sed.html: sed.texi sed.info @TEXI2HTML_HTML_TRUE@ cp $(srcdir)/*.texi . && \ @TEXI2HTML_HTML_TRUE@ $(TEXI2HTML) sed.texi && \ @TEXI2HTML_HTML_TRUE@ rm *.texi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: kbuild-3686/src/oldsed/doc/version.texi0000664000175000017500000000014315053010106020067 0ustar locutuslocutus@set UPDATED 30 January 2006 @set UPDATED-MONTH January 2006 @set EDITION 4.1.5 @set VERSION 4.1.5 kbuild-3686/src/oldsed/doc/sed.info-20000664000175000017500000011375715053010105017315 0ustar locutuslocutusThis is ../../doc/sed.info, produced by makeinfo version 4.5 from ../../doc/sed.texi. INFO-DIR-SECTION Text creation and manipulation START-INFO-DIR-ENTRY * sed: (sed). Stream EDitor. END-INFO-DIR-ENTRY This file documents version 4.1.5 of GNU `sed', a stream editor. Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This document is released under the terms of the GNU Free Documentation License as published by the Free Software Foundation; either version 1.1, or (at your option) any later version. You should have received a copy of the GNU Free Documentation License along with GNU `sed'; see the file `COPYING.DOC'. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02110-1301, USA. There are no Cover Texts and no Invariant Sections; this text, along with its equivalent in the printed manual, constitutes the Title Page.  File: sed.info, Node: Print bash environment, Next: Reverse chars of lines, Prev: Rename files to lower case, Up: Examples Print `bash' Environment ======================== This script strips the definition of the shell functions from the output of the `set' Bourne-shell command. #!/bin/sh set | sed -n ' :x # if no occurrence of "=()" print and load next line /=()/! { p; b; } / () $/! { p; b; } # possible start of functions section # save the line in case this is a var like FOO="() " h # if the next line has a brace, we quit because # nothing comes after functions n /^{/ q # print the old line x; p # work on the new line now x; bx '  File: sed.info, Node: Reverse chars of lines, Next: tac, Prev: Print bash environment, Up: Examples Reverse Characters of Lines =========================== This script can be used to reverse the position of characters in lines. The technique moves two characters at a time, hence it is faster than more intuitive implementations. Note the `tx' command before the definition of the label. This is often needed to reset the flag that is tested by the `t' command. Imaginative readers will find uses for this script. An example is reversing the output of `banner'.(1) #!/usr/bin/sed -f /../! b # Reverse a line. Begin embedding the line between two newlines s/^.*$/\ &\ / # Move first character at the end. The regexp matches until # there are zero or one characters between the markers tx :x s/\(\n.\)\(.*\)\(.\n\)/\3\2\1/ tx # Remove the newline markers s/\n//g ---------- Footnotes ---------- (1) This requires another script to pad the output of banner; for example #! /bin/sh banner -w $1 $2 $3 $4 | sed -e :a -e '/^.\{0,'$1'\}$/ { s/$/ /; ba; }' | ~/sedscripts/reverseline.sed  File: sed.info, Node: tac, Next: cat -n, Prev: Reverse chars of lines, Up: Examples Reverse Lines of Files ====================== This one begins a series of totally useless (yet interesting) scripts emulating various Unix commands. This, in particular, is a `tac' workalike. Note that on implementations other than GNU `sed' this script might easily overflow internal buffers. #!/usr/bin/sed -nf # reverse all lines of input, i.e. first line became last, ... # from the second line, the buffer (which contains all previous lines) # is *appended* to current line, so, the order will be reversed 1! G # on the last line we're done -- print everything $ p # store everything on the buffer again h  File: sed.info, Node: cat -n, Next: cat -b, Prev: tac, Up: Examples Numbering Lines =============== This script replaces `cat -n'; in fact it formats its output exactly like GNU `cat' does. Of course this is completely useless and for two reasons: first, because somebody else did it in C, second, because the following Bourne-shell script could be used for the same purpose and would be much faster: #! /bin/sh sed -e "=" $@ | sed -e ' s/^/ / N s/^ *\(......\)\n/\1 / ' It uses `sed' to print the line number, then groups lines two by two using `N'. Of course, this script does not teach as much as the one presented below. The algorithm used for incrementing uses both buffers, so the line is printed as soon as possible and then discarded. The number is split so that changing digits go in a buffer and unchanged ones go in the other; the changed digits are modified in a single step (using a `y' command). The line number for the next line is then composed and stored in the hold space, to be used in the next iteration. #!/usr/bin/sed -nf # Prime the pump on the first line x /^$/ s/^.*$/1/ # Add the correct line number before the pattern G h # Format it and print it s/^/ / s/^ *\(......\)\n/\1 /p # Get the line number from hold space; add a zero # if we're going to add a digit on the next line g s/\n.*$// /^9*$/ s/^/0/ # separate changing/unchanged digits with an x s/.9*$/x&/ # keep changing digits in hold space h s/^.*x// y/0123456789/1234567890/ x # keep unchanged digits in pattern space s/x.*$// # compose the new number, remove the newline implicitly added by G G s/\n// h  File: sed.info, Node: cat -b, Next: wc -c, Prev: cat -n, Up: Examples Numbering Non-blank Lines ========================= Emulating `cat -b' is almost the same as `cat -n'--we only have to select which lines are to be numbered and which are not. The part that is common to this script and the previous one is not commented to show how important it is to comment `sed' scripts properly... #!/usr/bin/sed -nf /^$/ { p b } # Same as cat -n from now x /^$/ s/^.*$/1/ G h s/^/ / s/^ *\(......\)\n/\1 /p x s/\n.*$// /^9*$/ s/^/0/ s/.9*$/x&/ h s/^.*x// y/0123456789/1234567890/ x s/x.*$// G s/\n// h  File: sed.info, Node: wc -c, Next: wc -w, Prev: cat -b, Up: Examples Counting Characters =================== This script shows another way to do arithmetic with `sed'. In this case we have to add possibly large numbers, so implementing this by successive increments would not be feasible (and possibly even more complicated to contrive than this script). The approach is to map numbers to letters, kind of an abacus implemented with `sed'. `a's are units, `b's are tens and so on: we simply add the number of characters on the current line as units, and then propagate the carry to tens, hundreds, and so on. As usual, running totals are kept in hold space. On the last line, we convert the abacus form back to decimal. For the sake of variety, this is done with a loop rather than with some 80 `s' commands(1): first we convert units, removing `a's from the number; then we rotate letters so that tens become `a's, and so on until no more letters remain. #!/usr/bin/sed -nf # Add n+1 a's to hold space (+1 is for the newline) s/./a/g H x s/\n/a/ # Do the carry. The t's and b's are not necessary, # but they do speed up the thing t a : a; s/aaaaaaaaaa/b/g; t b; b done : b; s/bbbbbbbbbb/c/g; t c; b done : c; s/cccccccccc/d/g; t d; b done : d; s/dddddddddd/e/g; t e; b done : e; s/eeeeeeeeee/f/g; t f; b done : f; s/ffffffffff/g/g; t g; b done : g; s/gggggggggg/h/g; t h; b done : h; s/hhhhhhhhhh//g : done $! { h b } # On the last line, convert back to decimal : loop /a/! s/[b-h]*/&0/ s/aaaaaaaaa/9/ s/aaaaaaaa/8/ s/aaaaaaa/7/ s/aaaaaa/6/ s/aaaaa/5/ s/aaaa/4/ s/aaa/3/ s/aa/2/ s/a/1/ : next y/bcdefgh/abcdefg/ /[a-h]/ b loop p ---------- Footnotes ---------- (1) Some implementations have a limit of 199 commands per script  File: sed.info, Node: wc -w, Next: wc -l, Prev: wc -c, Up: Examples Counting Words ============== This script is almost the same as the previous one, once each of the words on the line is converted to a single `a' (in the previous script each letter was changed to an `a'). It is interesting that real `wc' programs have optimized loops for `wc -c', so they are much slower at counting words rather than characters. This script's bottleneck, instead, is arithmetic, and hence the word-counting one is faster (it has to manage smaller numbers). Again, the common parts are not commented to show the importance of commenting `sed' scripts. #!/usr/bin/sed -nf # Convert words to a's s/[ tab][ tab]*/ /g s/^/ / s/ [^ ][^ ]*/a /g s/ //g # Append them to hold space H x s/\n// # From here on it is the same as in wc -c. /aaaaaaaaaa/! bx; s/aaaaaaaaaa/b/g /bbbbbbbbbb/! bx; s/bbbbbbbbbb/c/g /cccccccccc/! bx; s/cccccccccc/d/g /dddddddddd/! bx; s/dddddddddd/e/g /eeeeeeeeee/! bx; s/eeeeeeeeee/f/g /ffffffffff/! bx; s/ffffffffff/g/g /gggggggggg/! bx; s/gggggggggg/h/g s/hhhhhhhhhh//g :x $! { h; b; } :y /a/! s/[b-h]*/&0/ s/aaaaaaaaa/9/ s/aaaaaaaa/8/ s/aaaaaaa/7/ s/aaaaaa/6/ s/aaaaa/5/ s/aaaa/4/ s/aaa/3/ s/aa/2/ s/a/1/ y/bcdefgh/abcdefg/ /[a-h]/ by p  File: sed.info, Node: wc -l, Next: head, Prev: wc -w, Up: Examples Counting Lines ============== No strange things are done now, because `sed' gives us `wc -l' functionality for free!!! Look: #!/usr/bin/sed -nf $=  File: sed.info, Node: head, Next: tail, Prev: wc -l, Up: Examples Printing the First Lines ======================== This script is probably the simplest useful `sed' script. It displays the first 10 lines of input; the number of displayed lines is right before the `q' command. #!/usr/bin/sed -f 10q  File: sed.info, Node: tail, Next: uniq, Prev: head, Up: Examples Printing the Last Lines ======================= Printing the last N lines rather than the first is more complex but indeed possible. N is encoded in the second line, before the bang character. This script is similar to the `tac' script in that it keeps the final output in the hold space and prints it at the end: #!/usr/bin/sed -nf 1! {; H; g; } 1,10 !s/[^\n]*\n// $p h Mainly, the scripts keeps a window of 10 lines and slides it by adding a line and deleting the oldest (the substitution command on the second line works like a `D' command but does not restart the loop). The "sliding window" technique is a very powerful way to write efficient and complex `sed' scripts, because commands like `P' would require a lot of work if implemented manually. To introduce the technique, which is fully demonstrated in the rest of this chapter and is based on the `N', `P' and `D' commands, here is an implementation of `tail' using a simple "sliding window." This looks complicated but in fact the working is the same as the last script: after we have kicked in the appropriate number of lines, however, we stop using the hold space to keep inter-line state, and instead use `N' and `D' to slide pattern space by one line: #!/usr/bin/sed -f 1h 2,10 {; H; g; } $q 1,9d N D Note how the first, second and fourth line are inactive after the first ten lines of input. After that, all the script does is: exiting on the last line of input, appending the next input line to pattern space, and removing the first line.  File: sed.info, Node: uniq, Next: uniq -d, Prev: tail, Up: Examples Make Duplicate Lines Unique =========================== This is an example of the art of using the `N', `P' and `D' commands, probably the most difficult to master. #!/usr/bin/sed -f h :b # On the last line, print and exit $b N /^\(.*\)\n\1$/ { # The two lines are identical. Undo the effect of # the n command. g bb } # If the `N' command had added the last line, print and exit $b # The lines are different; print the first and go # back working on the second. P D As you can see, we mantain a 2-line window using `P' and `D'. This technique is often used in advanced `sed' scripts.  File: sed.info, Node: uniq -d, Next: uniq -u, Prev: uniq, Up: Examples Print Duplicated Lines of Input =============================== This script prints only duplicated lines, like `uniq -d'. #!/usr/bin/sed -nf $b N /^\(.*\)\n\1$/ { # Print the first of the duplicated lines s/.*\n// p # Loop until we get a different line :b $b N /^\(.*\)\n\1$/ { s/.*\n// bb } } # The last line cannot be followed by duplicates $b # Found a different one. Leave it alone in the pattern space # and go back to the top, hunting its duplicates D  File: sed.info, Node: uniq -u, Next: cat -s, Prev: uniq -d, Up: Examples Remove All Duplicated Lines =========================== This script prints only unique lines, like `uniq -u'. #!/usr/bin/sed -f # Search for a duplicate line --- until that, print what you find. $b N /^\(.*\)\n\1$/ ! { P D } :c # Got two equal lines in pattern space. At the # end of the file we simply exit $d # Else, we keep reading lines with `N' until we # find a different one s/.*\n// N /^\(.*\)\n\1$/ { bc } # Remove the last instance of the duplicate line # and go back to the top D  File: sed.info, Node: cat -s, Prev: uniq -u, Up: Examples Squeezing Blank Lines ===================== As a final example, here are three scripts, of increasing complexity and speed, that implement the same function as `cat -s', that is squeezing blank lines. The first leaves a blank line at the beginning and end if there are some already. #!/usr/bin/sed -f # on empty lines, join with next # Note there is a star in the regexp :x /^\n*$/ { N bx } # now, squeeze all '\n', this can be also done by: # s/^\(\n\)*/\1/ s/\n*/\ / This one is a bit more complex and removes all empty lines at the beginning. It does leave a single blank line at end if one was there. #!/usr/bin/sed -f # delete all leading empty lines 1,/^./{ /./!d } # on an empty line we remove it and all the following # empty lines, but one :x /./!{ N s/^\n$// tx } This removes leading and trailing blank lines. It is also the fastest. Note that loops are completely done with `n' and `b', without relying on `sed' to restart the the script automatically at the end of a line. #!/usr/bin/sed -nf # delete all (leading) blanks /./!d # get here: so there is a non empty :x # print it p # get next n # got chars? print it again, etc... /./bx # no, don't have chars: got an empty line :z # get next, if last line we finish here so no trailing # empty lines are written n # also empty? then ignore it, and get next... this will # remove ALL empty lines /./!bz # all empty lines were deleted/ignored, but we have a non empty. As # what we want to do is to squeeze, insert a blank line artificially i\ bx  File: sed.info, Node: Limitations, Next: Other Resources, Prev: Examples, Up: Top GNU `sed''s Limitations and Non-limitations ******************************************* For those who want to write portable `sed' scripts, be aware that some implementations have been known to limit line lengths (for the pattern and hold spaces) to be no more than 4000 bytes. The POSIX standard specifies that conforming `sed' implementations shall support at least 8192 byte line lengths. GNU `sed' has no built-in limit on line length; as long as it can `malloc()' more (virtual) memory, you can feed or construct lines as long as you like. However, recursion is used to handle subpatterns and indefinite repetition. This means that the available stack space may limit the size of the buffer that can be processed by certain patterns.  File: sed.info, Node: Other Resources, Next: Reporting Bugs, Prev: Limitations, Up: Top Other Resources for Learning About `sed' **************************************** In addition to several books that have been written about `sed' (either specifically or as chapters in books which discuss shell programming), one can find out more about `sed' (including suggestions of a few books) from the FAQ for the `sed-users' mailing list, available from any of: `http://www.student.northpark.edu/pemente/sed/sedfaq.html' `http://sed.sf.net/grabbag/tutorials/sedfaq.html' Also of interest are `http://www.student.northpark.edu/pemente/sed/index.htm' and `http://sed.sf.net/grabbag', which include `sed' tutorials and other `sed'-related goodies. The `sed-users' mailing list itself maintained by Sven Guckes. To subscribe, visit `http://groups.yahoo.com' and search for the `sed-users' mailing list.  File: sed.info, Node: Reporting Bugs, Next: Extended regexps, Prev: Other Resources, Up: Top Reporting Bugs ************** Email bug reports to . Be sure to include the word "sed" somewhere in the `Subject:' field. Also, please include the output of `sed --version' in the body of your report if at all possible. Please do not send a bug report like this: while building frobme-1.3.4 $ configure error--> sed: file sedscr line 1: Unknown option to 's' If GNU `sed' doesn't configure your favorite package, take a few extra minutes to identify the specific problem and make a stand-alone test case. Unlike other programs such as C compilers, making such test cases for `sed' is quite simple. A stand-alone test case includes all the data necessary to perform the test, and the specific invocation of `sed' that causes the problem. The smaller a stand-alone test case is, the better. A test case should not involve something as far removed from `sed' as "try to configure frobme-1.3.4". Yes, that is in principle enough information to look for the bug, but that is not a very practical prospect. Here are a few commonly reported bugs that are not bugs. `N' command on the last line Most versions of `sed' exit without printing anything when the `N' command is issued on the last line of a file. GNU `sed' prints pattern space before exiting unless of course the `-n' command switch has been specified. This choice is by design. For example, the behavior of sed N foo bar would depend on whether foo has an even or an odd number of lines(1). Or, when writing a script to read the next few lines following a pattern match, traditional implementations of `sed' would force you to write something like /foo/{ $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N } instead of just /foo/{ N;N;N;N;N;N;N;N;N; } In any case, the simplest workaround is to use `$d;N' in scripts that rely on the traditional behavior, or to set the `POSIXLY_CORRECT' variable to a non-empty value. Regex syntax clashes (problems with backslashes) `sed' uses the POSIX basic regular expression syntax. According to the standard, the meaning of some escape sequences is undefined in this syntax; notable in the case of `sed' are `\|', `\+', `\?', `\`', `\'', `\<', `\>', `\b', `\B', `\w', and `\W'. As in all GNU programs that use POSIX basic regular expressions, `sed' interprets these escape sequences as special characters. So, `x\+' matches one or more occurrences of `x'. `abc\|def' matches either `abc' or `def'. This syntax may cause problems when running scripts written for other `sed's. Some `sed' programs have been written with the assumption that `\|' and `\+' match the literal characters `|' and `+'. Such scripts must be modified by removing the spurious backslashes if they are to be used with modern implementations of `sed', like GNU `sed'. On the other hand, some scripts use s|abc\|def||g to remove occurrences of _either_ `abc' or `def'. While this worked until `sed' 4.0.x, newer versions interpret this as removing the string `abc|def'. This is again undefined behavior according to POSIX, and this interpretation is arguably more robust: older `sed's, for example, required that the regex matcher parsed `\/' as `/' in the common case of escaping a slash, which is again undefined behavior; the new behavior avoids this, and this is good because the regex matcher is only partially under our control. In addition, this version of `sed' supports several escape characters (some of which are multi-character) to insert non-printable characters in scripts (`\a', `\c', `\d', `\o', `\r', `\t', `\v', `\x'). These can cause similar problems with scripts written for other `sed's. `-i' clobbers read-only files In short, `sed -i' will let you delete the contents of a read-only file, and in general the `-i' option (*note Invocation: Invoking sed.) lets you clobber protected files. This is not a bug, but rather a consequence of how the Unix filesystem works. The permissions on a file say what can happen to the data in that file, while the permissions on a directory say what can happen to the list of files in that directory. `sed -i' will not ever open for writing a file that is already on disk. Rather, it will work on a temporary file that is finally renamed to the original name: if you rename or delete files, you're actually modifying the contents of the directory, so the operation depends on the permissions of the directory, not of the file. For this same reason, `sed' does not let you use `-i' on a writeable file in a read-only directory (but unbelievably nobody reports that as a bug...). `0a' does not work (gives an error) There is no line 0. 0 is a special address that is only used to treat addresses like `0,/RE/' as active when the script starts: if you write `1,/abc/d' and the first line includes the word `abc', then that match would be ignored because address ranges must span at least two lines (barring the end of the file); but what you probably wanted is to delete every line up to the first one including `abc', and this is obtained with `0,/abc/d'. `[a-z]' is case insensitive You are encountering problems with locales. POSIX mandates that `[a-z]' uses the current locale's collation order - in C parlance, that means using `strcoll(3)' instead of `strcmp(3)'. Some locales have a case-insensitive collation order, others don't: one of those that have problems is Estonian. Another problem is that `[a-z]' tries to use collation symbols. This only happens if you are on the GNU system, using GNU libc's regular expression matcher instead of compiling the one supplied with GNU sed. In a Danish locale, for example, the regular expression `^[a-z]$' matches the string `aa', because this is a single collating symbol that comes after `a' and before `b'; `ll' behaves similarly in Spanish locales, or `ij' in Dutch locales. To work around these problems, which may cause bugs in shell scripts, set the `LC_COLLATE' and `LC_CTYPE' environment variables to `C'. ---------- Footnotes ---------- (1) which is the actual "bug" that prompted the change in behavior  File: sed.info, Node: Extended regexps, Next: Concept Index, Prev: Reporting Bugs, Up: Top Extended regular expressions **************************** The only difference between basic and extended regular expressions is in the behavior of a few characters: `?', `+', parentheses, and braces (`{}'). While basic regular expressions require these to be escaped if you want them to behave as special characters, when using extended regular expressions you must escape them if you want them _to match a literal character_. Examples: `abc?' becomes `abc\?' when using extended regular expressions. It matches the literal string `abc?'. `c\+' becomes `c+' when using extended regular expressions. It matches one or more `c's. `a\{3,\}' becomes `a{3,}' when using extended regular expressions. It matches three or more `a's. `\(abc\)\{2,3\}' becomes `(abc){2,3}' when using extended regular expressions. It matches either `abcabc' or `abcabcabc'. `\(abc*\)\1' becomes `(abc*)\1' when using extended regular expressions. Backreferences must still be escaped when using extended regular expressions.  File: sed.info, Node: Concept Index, Next: Command and Option Index, Prev: Extended regexps, Up: Top Concept Index ************* This is a general index of all issues discussed in this manual, with the exception of the `sed' commands and command-line options. * Menu: * Additional reading about sed: Other Resources. * ADDR1,+N: Addresses. * ADDR1,~N: Addresses. * Address, as a regular expression: Addresses. * Address, last line: Addresses. * Address, numeric: Addresses. * Addresses, in sed scripts: Addresses. * Append hold space to pattern space: Other Commands. * Append next input line to pattern space: Other Commands. * Append pattern space to hold space: Other Commands. * Appending text after a line: Other Commands. * Backreferences, in regular expressions: The "s" Command. * Branch to a label, if s/// failed: Extended Commands. * Branch to a label, if s/// succeeded: Programming Commands. * Branch to a label, unconditionally: Programming Commands. * Buffer spaces, pattern and hold: Execution Cycle. * Bugs, reporting: Reporting Bugs. * Case-insensitive matching: The "s" Command. * Caveat -- #n on first line: Common Commands. * Command groups: Common Commands. * Comments, in scripts: Common Commands. * Conditional branch <1>: Extended Commands. * Conditional branch: Programming Commands. * Copy hold space into pattern space: Other Commands. * Copy pattern space into hold space: Other Commands. * Delete first line from pattern space: Other Commands. * Disabling autoprint, from command line: Invoking sed. * empty regular expression: Addresses. * Evaluate Bourne-shell commands: Extended Commands. * Evaluate Bourne-shell commands, after substitution: The "s" Command. * Exchange hold space with pattern space: Other Commands. * Excluding lines: Addresses. * Extended regular expressions, choosing: Invoking sed. * Extended regular expressions, syntax: Extended regexps. * Files to be processed as input: Invoking sed. * Flow of control in scripts: Programming Commands. * Global substitution: The "s" Command. * GNU extensions, /dev/stderr file <1>: The "s" Command. * GNU extensions, /dev/stderr file: Other Commands. * GNU extensions, /dev/stdin file <1>: Other Commands. * GNU extensions, /dev/stdin file: Extended Commands. * GNU extensions, /dev/stdout file <1>: Invoking sed. * GNU extensions, /dev/stdout file <2>: The "s" Command. * GNU extensions, /dev/stdout file: Other Commands. * GNU extensions, 0 address: Addresses. * GNU extensions, 0,ADDR2 addressing: Addresses. * GNU extensions, ADDR1,+N addressing: Addresses. * GNU extensions, ADDR1,~N addressing: Addresses. * GNU extensions, branch if s/// failed: Extended Commands. * GNU extensions, case modifiers in s commands: The "s" Command. * GNU extensions, checking for their presence: Extended Commands. * GNU extensions, disabling: Invoking sed. * GNU extensions, evaluating Bourne-shell commands <1>: Extended Commands. * GNU extensions, evaluating Bourne-shell commands: The "s" Command. * GNU extensions, extended regular expressions: Invoking sed. * GNU extensions, g and NUMBER modifier interaction in s command: The "s" Command. * GNU extensions, I modifier <1>: Addresses. * GNU extensions, I modifier: The "s" Command. * GNU extensions, in-place editing <1>: Reporting Bugs. * GNU extensions, in-place editing: Invoking sed. * GNU extensions, L command: Extended Commands. * GNU extensions, M modifier: The "s" Command. * GNU extensions, modifiers and the empty regular expression: Addresses. * GNU extensions, N~M addresses: Addresses. * GNU extensions, quitting silently: Extended Commands. * GNU extensions, R command: Extended Commands. * GNU extensions, reading a file a line at a time: Extended Commands. * GNU extensions, reformatting paragraphs: Extended Commands. * GNU extensions, returning an exit code <1>: Common Commands. * GNU extensions, returning an exit code: Extended Commands. * GNU extensions, setting line length: Other Commands. * GNU extensions, special escapes <1>: Reporting Bugs. * GNU extensions, special escapes: Escapes. * GNU extensions, special two-address forms: Addresses. * GNU extensions, subprocesses <1>: The "s" Command. * GNU extensions, subprocesses: Extended Commands. * GNU extensions, to basic regular expressions <1>: Reporting Bugs. * GNU extensions, to basic regular expressions: Regular Expressions. * GNU extensions, two addresses supported by most commands: Other Commands. * GNU extensions, unlimited line length: Limitations. * GNU extensions, writing first line to a file: Extended Commands. * Goto, in scripts: Programming Commands. * Greedy regular expression matching: Regular Expressions. * Grouping commands: Common Commands. * Hold space, appending from pattern space: Other Commands. * Hold space, appending to pattern space: Other Commands. * Hold space, copy into pattern space: Other Commands. * Hold space, copying pattern space into: Other Commands. * Hold space, definition: Execution Cycle. * Hold space, exchange with pattern space: Other Commands. * In-place editing: Reporting Bugs. * In-place editing, activating: Invoking sed. * In-place editing, Perl-style backup file names: Invoking sed. * Inserting text before a line: Other Commands. * Labels, in scripts: Programming Commands. * Last line, selecting: Addresses. * Line length, setting <1>: Invoking sed. * Line length, setting: Other Commands. * Line number, printing: Other Commands. * Line selection: Addresses. * Line, selecting by number: Addresses. * Line, selecting by regular expression match: Addresses. * Line, selecting last: Addresses. * List pattern space: Other Commands. * Mixing g and NUMBER modifiers in the s command: The "s" Command. * Next input line, append to pattern space: Other Commands. * Next input line, replace pattern space with: Common Commands. * Non-bugs, in-place editing: Reporting Bugs. * Non-bugs, N command on the last line: Reporting Bugs. * Non-bugs, regex syntax clashes: Reporting Bugs. * Parenthesized substrings: The "s" Command. * Pattern space, definition: Execution Cycle. * Perl-style regular expressions, multiline: Addresses. * Portability, comments: Common Commands. * Portability, line length limitations: Limitations. * Portability, N command on the last line: Reporting Bugs. * POSIXLY_CORRECT behavior, bracket expressions: Regular Expressions. * POSIXLY_CORRECT behavior, enabling: Invoking sed. * POSIXLY_CORRECT behavior, escapes: Escapes. * POSIXLY_CORRECT behavior, N command: Reporting Bugs. * Print first line from pattern space: Other Commands. * Printing line number: Other Commands. * Printing text unambiguously: Other Commands. * Quitting <1>: Extended Commands. * Quitting: Common Commands. * Range of lines: Addresses. * Range with start address of zero: Addresses. * Read next input line: Common Commands. * Read text from a file <1>: Extended Commands. * Read text from a file: Other Commands. * Reformat pattern space: Extended Commands. * Reformatting paragraphs: Extended Commands. * Replace hold space with copy of pattern space: Other Commands. * Replace pattern space with copy of hold space: Other Commands. * Replacing all text matching regexp in a line: The "s" Command. * Replacing only Nth match of regexp in a line: The "s" Command. * Replacing selected lines with other text: Other Commands. * Requiring GNU sed: Extended Commands. * Script structure: sed Programs. * Script, from a file: Invoking sed. * Script, from command line: Invoking sed. * sed program structure: sed Programs. * Selecting lines to process: Addresses. * Selecting non-matching lines: Addresses. * Several lines, selecting: Addresses. * Slash character, in regular expressions: Addresses. * Spaces, pattern and hold: Execution Cycle. * Special addressing forms: Addresses. * Standard input, processing as input: Invoking sed. * Stream editor: Introduction. * Subprocesses <1>: Extended Commands. * Subprocesses: The "s" Command. * Substitution of text, options: The "s" Command. * Text, appending: Other Commands. * Text, deleting: Common Commands. * Text, insertion: Other Commands. * Text, printing: Common Commands. * Text, printing after substitution: The "s" Command. * Text, writing to a file after substitution: The "s" Command. * Transliteration: Other Commands. * Unbuffered I/O, choosing: Invoking sed. * Usage summary, printing: Invoking sed. * Version, printing: Invoking sed. * Working on separate files: Invoking sed. * Write first line to a file: Extended Commands. * Write to a file: Other Commands. * Zero, as range start address: Addresses.  File: sed.info, Node: Command and Option Index, Prev: Concept Index, Up: Top Command and Option Index ************************ This is an alphabetical list of all `sed' commands and command-line options. * Menu: * # (comments): Common Commands. * --expression: Invoking sed. * --file: Invoking sed. * --help: Invoking sed. * --in-place: Invoking sed. * --line-length: Invoking sed. * --quiet: Invoking sed. * --regexp-extended: Invoking sed. * --silent: Invoking sed. * --unbuffered: Invoking sed. * --version: Invoking sed. * -e: Invoking sed. * -f: Invoking sed. * -i: Invoking sed. * -l: Invoking sed. * -n: Invoking sed. * -n, forcing from within a script: Common Commands. * -r: Invoking sed. * -u: Invoking sed. * : (label) command: Programming Commands. * = (print line number) command: Other Commands. * a (append text lines) command: Other Commands. * b (branch) command: Programming Commands. * c (change to text lines) command: Other Commands. * D (delete first line) command: Other Commands. * d (delete) command: Common Commands. * e (evaluate) command: Extended Commands. * G (appending Get) command: Other Commands. * g (get) command: Other Commands. * H (append Hold) command: Other Commands. * h (hold) command: Other Commands. * i (insert text lines) command: Other Commands. * L (fLow paragraphs) command: Extended Commands. * l (list unambiguously) command: Other Commands. * N (append Next line) command: Other Commands. * n (next-line) command: Common Commands. * P (print first line) command: Other Commands. * p (print) command: Common Commands. * q (quit) command: Common Commands. * Q (silent Quit) command: Extended Commands. * r (read file) command: Other Commands. * R (read line) command: Extended Commands. * s command, option flags: The "s" Command. * T (test and branch if failed) command: Extended Commands. * t (test and branch if successful) command: Programming Commands. * v (version) command: Extended Commands. * w (write file) command: Other Commands. * W (write first line) command: Extended Commands. * x (eXchange) command: Other Commands. * y (transliterate) command: Other Commands. * {} command grouping: Common Commands. kbuild-3686/src/oldsed/doc/sed-in.texi0000664000175000017500000041534315053010106017575 0ustar locutuslocutus\input texinfo @c -*-texinfo-*- @c @c -- Stuff that needs adding: ---------------------------------------------- @c (document the `;' command-separator) @c -------------------------------------------------------------------------- @c Check for consistency: regexps in @code, text that they match in @samp. @c @c Tips: @c @command for command @c @samp for command fragments: @samp{cat -s} @c @code for sed commands and flags @c Use ``quote'' not `quote' or "quote". @c @c %**start of header @setfilename sed.info @settitle sed, a stream editor @c %**end of header @c @smallbook @include version.texi @c Combine indices. @syncodeindex ky cp @syncodeindex pg cp @syncodeindex tp cp @defcodeindex op @syncodeindex op fn @include config.texi @copying This file documents version @value{VERSION} of @value{SSED}, a stream editor. Copyright @copyright{} 1998, 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This document is released under the terms of the @acronym{GNU} Free Documentation License as published by the Free Software Foundation; either version 1.1, or (at your option) any later version. You should have received a copy of the @acronym{GNU} Free Documentation License along with @value{SSED}; see the file @file{COPYING.DOC}. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02110-1301, USA. There are no Cover Texts and no Invariant Sections; this text, along with its equivalent in the printed manual, constitutes the Title Page. @end copying @setchapternewpage off @titlepage @title @command{sed}, a stream editor @subtitle version @value{VERSION}, @value{UPDATED} @author by Ken Pizzini, Paolo Bonzini @page @vskip 0pt plus 1filll Copyright @copyright{} 1998, 1999 Free Software Foundation, Inc. @insertcopying Published by the Free Software Foundation, @* 51 Franklin Street, Fifth Floor @* Boston, MA 02110-1301, USA @end titlepage @node Top @top @ifnottex @insertcopying @end ifnottex @menu * Introduction:: Introduction * Invoking sed:: Invocation * sed Programs:: @command{sed} programs * Examples:: Some sample scripts * Limitations:: Limitations and (non-)limitations of @value{SSED} * Other Resources:: Other resources for learning about @command{sed} * Reporting Bugs:: Reporting bugs * Extended regexps:: @command{egrep}-style regular expressions @ifset PERL * Perl regexps:: Perl-style regular expressions @end ifset * Concept Index:: A menu with all the topics in this manual. * Command and Option Index:: A menu with all @command{sed} commands and command-line options. @detailmenu --- The detailed node listing --- sed Programs: * Execution Cycle:: How @command{sed} works * Addresses:: Selecting lines with @command{sed} * Regular Expressions:: Overview of regular expression syntax * Common Commands:: Often used commands * The "s" Command:: @command{sed}'s Swiss Army Knife * Other Commands:: Less frequently used commands * Programming Commands:: Commands for @command{sed} gurus * Extended Commands:: Commands specific of @value{SSED} * Escapes:: Specifying special characters Examples: * Centering lines:: * Increment a number:: * Rename files to lower case:: * Print bash environment:: * Reverse chars of lines:: * tac:: Reverse lines of files * cat -n:: Numbering lines * cat -b:: Numbering non-blank lines * wc -c:: Counting chars * wc -w:: Counting words * wc -l:: Counting lines * head:: Printing the first lines * tail:: Printing the last lines * uniq:: Make duplicate lines unique * uniq -d:: Print duplicated lines of input * uniq -u:: Remove all duplicated lines * cat -s:: Squeezing blank lines @ifset PERL Perl regexps:: Perl-style regular expressions * Backslash:: Introduces special sequences * Circumflex/dollar sign/period:: Behave specially with regard to new lines * Square brackets:: Are a bit different in strange cases * Options setting:: Toggle modifiers in the middle of a regexp * Non-capturing subpatterns:: Are not counted when backreferencing * Repetition:: Allows for non-greedy matching * Backreferences:: Allows for more than 10 back references * Assertions:: Allows for complex look ahead matches * Non-backtracking subpatterns:: Often gives more performance * Conditional subpatterns:: Allows if/then/else branches * Recursive patterns:: For example to match parentheses * Comments:: Because things can get complex... @end ifset @end detailmenu @end menu @node Introduction @chapter Introduction @cindex Stream editor @command{sed} is a stream editor. A stream editor is used to perform basic text transformations on an input stream (a file or input from a pipeline). While in some ways similar to an editor which permits scripted edits (such as @command{ed}), @command{sed} works by making only one pass over the input(s), and is consequently more efficient. But it is @command{sed}'s ability to filter text in a pipeline which particularly distinguishes it from other types of editors. @node Invoking sed @chapter Invocation Normally @command{sed} is invoked like this: @example sed SCRIPT INPUTFILE... @end example The full format for invoking @command{sed} is: @example sed OPTIONS... [SCRIPT] [INPUTFILE...] @end example If you do not specify @var{INPUTFILE}, or if @var{INPUTFILE} is @file{-}, @command{sed} filters the contents of the standard input. The @var{script} is actually the first non-option parameter, which @command{sed} specially considers a script and not an input file if (and only if) none of the other @var{options} specifies a script to be executed, that is if neither of the @option{-e} and @option{-f} options is specified. @command{sed} may be invoked with the following command-line options: @table @code @item --version @opindex --version @cindex Version, printing Print out the version of @command{sed} that is being run and a copyright notice, then exit. @item --help @opindex --help @cindex Usage summary, printing Print a usage message briefly summarizing these command-line options and the bug-reporting address, then exit. @item -n @itemx --quiet @itemx --silent @opindex -n @opindex --quiet @opindex --silent @cindex Disabling autoprint, from command line By default, @command{sed} prints out the pattern space at the end of each cycle through the script. These options disable this automatic printing, and @command{sed} only produces output when explicitly told to via the @code{p} command. @item -i[@var{SUFFIX}] @itemx --in-place[=@var{SUFFIX}] @opindex -i @opindex --in-place @cindex In-place editing, activating @cindex @value{SSEDEXT}, in-place editing This option specifies that files are to be edited in-place. @value{SSED} does this by creating a temporary file and sending output to this file rather than to the standard output.@footnote{This applies to commands such as @code{=}, @code{a}, @code{c}, @code{i}, @code{l}, @code{p}. You can still write to the standard output by using the @code{w} @cindex @value{SSEDEXT}, @file{/dev/stdout} file or @code{W} commands together with the @file{/dev/stdout} special file}. This option implies @option{-s}. When the end of the file is reached, the temporary file is renamed to the output file's original name. The extension, if supplied, is used to modify the name of the old file before renaming the temporary file, thereby making a backup copy@footnote{Note that @value{SSED} creates the backup file whether or not any output is actually changed.}). @cindex In-place editing, Perl-style backup file names This rule is followed: if the extension doesn't contain a @code{*}, then it is appended to the end of the current filename as a suffix; if the extension does contain one or more @code{*} characters, then @emph{each} asterisk is replaced with the current filename. This allows you to add a prefix to the backup file, instead of (or in addition to) a suffix, or even to place backup copies of the original files into another directory (provided the directory already exists). If no extension is supplied, the original file is overwritten without making a backup. @item -l @var{N} @itemx --line-length=@var{N} @opindex -l @opindex --line-length @cindex Line length, setting Specify the default line-wrap length for the @code{l} command. A length of 0 (zero) means to never wrap long lines. If not specified, it is taken to be 70. @item --posix @cindex @value{SSEDEXT}, disabling @value{SSED} includes several extensions to @acronym{POSIX} sed. In order to simplify writing portable scripts, this option disables all the extensions that this manual documents, including additional commands. @cindex @code{POSIXLY_CORRECT} behavior, enabling Most of the extensions accept @command{sed} programs that are outside the syntax mandated by @acronym{POSIX}, but some of them (such as the behavior of the @command{N} command described in @pxref{Reporting Bugs}) actually violate the standard. If you want to disable only the latter kind of extension, you can set the @code{POSIXLY_CORRECT} variable to a non-empty value. @item -r @itemx --regexp-extended @opindex -r @opindex --regexp-extended @cindex Extended regular expressions, choosing @cindex @acronym{GNU} extensions, extended regular expressions Use extended regular expressions rather than basic regular expressions. Extended regexps are those that @command{egrep} accepts; they can be clearer because they usually have less backslashes, but are a @acronym{GNU} extension and hence scripts that use them are not portable. @xref{Extended regexps, , Extended regular expressions}. @ifset PERL @item -R @itemx --regexp-perl @opindex -R @opindex --regexp-perl @cindex Perl-style regular expressions, choosing @cindex @value{SSEDEXT}, Perl-style regular expressions Use Perl-style regular expressions rather than basic regular expressions. Perl-style regexps are extremely powerful but are a @value{SSED} extension and hence scripts that use it are not portable. @xref{Perl regexps, , Perl-style regular expressions}. @end ifset @item -s @itemx --separate @cindex Working on separate files By default, @command{sed} will consider the files specified on the command line as a single continuous long stream. This @value{SSED} extension allows the user to consider them as separate files: range addresses (such as @samp{/abc/,/def/}) are not allowed to span several files, line numbers are relative to the start of each file, @code{$} refers to the last line of each file, and files invoked from the @code{R} commands are rewound at the start of each file. @item -u @itemx --unbuffered @opindex -u @opindex --unbuffered @cindex Unbuffered I/O, choosing Buffer both input and output as minimally as practical. (This is particularly useful if the input is coming from the likes of @samp{tail -f}, and you wish to see the transformed output as soon as possible.) @item -e @var{script} @itemx --expression=@var{script} @opindex -e @opindex --expression @cindex Script, from command line Add the commands in @var{script} to the set of commands to be run while processing the input. @item -f @var{script-file} @itemx --file=@var{script-file} @opindex -f @opindex --file @cindex Script, from a file Add the commands contained in the file @var{script-file} to the set of commands to be run while processing the input. @end table If no @option{-e}, @option{-f}, @option{--expression}, or @option{--file} options are given on the command-line, then the first non-option argument on the command line is taken to be the @var{script} to be executed. @cindex Files to be processed as input If any command-line parameters remain after processing the above, these parameters are interpreted as the names of input files to be processed. @cindex Standard input, processing as input A file name of @samp{-} refers to the standard input stream. The standard input will be processed if no file names are specified. @node sed Programs @chapter @command{sed} Programs @cindex @command{sed} program structure @cindex Script structure A @command{sed} program consists of one or more @command{sed} commands, passed in by one or more of the @option{-e}, @option{-f}, @option{--expression}, and @option{--file} options, or the first non-option argument if zero of these options are used. This document will refer to ``the'' @command{sed} script; this is understood to mean the in-order catenation of all of the @var{script}s and @var{script-file}s passed in. Each @code{sed} command consists of an optional address or address range, followed by a one-character command name and any additional command-specific code. @menu * Execution Cycle:: How @command{sed} works * Addresses:: Selecting lines with @command{sed} * Regular Expressions:: Overview of regular expression syntax * Common Commands:: Often used commands * The "s" Command:: @command{sed}'s Swiss Army Knife * Other Commands:: Less frequently used commands * Programming Commands:: Commands for @command{sed} gurus * Extended Commands:: Commands specific of @value{SSED} * Escapes:: Specifying special characters @end menu @node Execution Cycle @section How @command{sed} Works @cindex Buffer spaces, pattern and hold @cindex Spaces, pattern and hold @cindex Pattern space, definition @cindex Hold space, definition @command{sed} maintains two data buffers: the active @emph{pattern} space, and the auxiliary @emph{hold} space. Both are initially empty. @command{sed} operates by performing the following cycle on each lines of input: first, @command{sed} reads one line from the input stream, removes any trailing newline, and places it in the pattern space. Then commands are executed; each command can have an address associated to it: addresses are a kind of condition code, and a command is only executed if the condition is verified before the command is to be executed. When the end of the script is reached, unless the @option{-n} option is in use, the contents of pattern space are printed out to the output stream, adding back the trailing newline if it was removed.@footnote{Actually, if @command{sed} prints a line without the terminating newline, it will nevertheless print the missing newline as soon as more text is sent to the same output stream, which gives the ``least expected surprise'' even though it does not make commands like @samp{sed -n p} exactly identical to @command{cat}.} Then the next cycle starts for the next input line. Unless special commands (like @samp{D}) are used, the pattern space is deleted between two cycles. The hold space, on the other hand, keeps its data between cycles (see commands @samp{h}, @samp{H}, @samp{x}, @samp{g}, @samp{G} to move data between both buffers). @node Addresses @section Selecting lines with @command{sed} @cindex Addresses, in @command{sed} scripts @cindex Line selection @cindex Selecting lines to process Addresses in a @command{sed} script can be in any of the following forms: @table @code @item @var{number} @cindex Address, numeric @cindex Line, selecting by number Specifying a line number will match only that line in the input. (Note that @command{sed} counts lines continuously across all input files unless @option{-i} or @option{-s} options are specified.) @item @var{first}~@var{step} @cindex @acronym{GNU} extensions, @samp{@var{n}~@var{m}} addresses This @acronym{GNU} extension matches every @var{step}th line starting with line @var{first}. In particular, lines will be selected when there exists a non-negative @var{n} such that the current line-number equals @var{first} + (@var{n} * @var{step}). Thus, to select the odd-numbered lines, one would use @code{1~2}; to pick every third line starting with the second, @samp{2~3} would be used; to pick every fifth line starting with the tenth, use @samp{10~5}; and @samp{50~0} is just an obscure way of saying @code{50}. @item $ @cindex Address, last line @cindex Last line, selecting @cindex Line, selecting last This address matches the last line of the last file of input, or the last line of each file when the @option{-i} or @option{-s} options are specified. @item /@var{regexp}/ @cindex Address, as a regular expression @cindex Line, selecting by regular expression match This will select any line which matches the regular expression @var{regexp}. If @var{regexp} itself includes any @code{/} characters, each must be escaped by a backslash (@code{\}). @cindex empty regular expression @cindex @value{SSEDEXT}, modifiers and the empty regular expression The empty regular expression @samp{//} repeats the last regular expression match (the same holds if the empty regular expression is passed to the @code{s} command). Note that modifiers to regular expressions are evaluated when the regular expression is compiled, thus it is invalid to specify them together with the empty regular expression. @item \%@var{regexp}% (The @code{%} may be replaced by any other single character.) @cindex Slash character, in regular expressions This also matches the regular expression @var{regexp}, but allows one to use a different delimiter than @code{/}. This is particularly useful if the @var{regexp} itself contains a lot of slashes, since it avoids the tedious escaping of every @code{/}. If @var{regexp} itself includes any delimiter characters, each must be escaped by a backslash (@code{\}). @item /@var{regexp}/I @itemx \%@var{regexp}%I @cindex @acronym{GNU} extensions, @code{I} modifier @ifset PERL @cindex Perl-style regular expressions, case-insensitive @end ifset The @code{I} modifier to regular-expression matching is a @acronym{GNU} extension which causes the @var{regexp} to be matched in a case-insensitive manner. @item /@var{regexp}/M @itemx \%@var{regexp}%M @ifset PERL @cindex @value{SSEDEXT}, @code{M} modifier @end ifset @cindex Perl-style regular expressions, multiline The @code{M} modifier to regular-expression matching is a @value{SSED} extension which causes @code{^} and @code{$} to match respectively (in addition to the normal behavior) the empty string after a newline, and the empty string before a newline. There are special character sequences @ifset PERL (@code{\A} and @code{\Z} in Perl mode, @code{\`} and @code{\'} in basic or extended regular expression modes) @end ifset @ifclear PERL (@code{\`} and @code{\'}) @end ifclear which always match the beginning or the end of the buffer. @code{M} stands for @cite{multi-line}. @ifset PERL @item /@var{regexp}/S @itemx \%@var{regexp}%S @cindex @value{SSEDEXT}, @code{S} modifier @cindex Perl-style regular expressions, single line The @code{S} modifier to regular-expression matching is only valid in Perl mode and specifies that the dot character (@code{.}) will match the newline character too. @code{S} stands for @cite{single-line}. @end ifset @ifset PERL @item /@var{regexp}/X @itemx \%@var{regexp}%X @cindex @value{SSEDEXT}, @code{X} modifier @cindex Perl-style regular expressions, extended The @code{X} modifier to regular-expression matching is also valid in Perl mode only. If it is used, whitespace in the pattern (other than in a character class) and characters between a @kbd{#} outside a character class and the next newline character are ignored. An escaping backslash can be used to include a whitespace or @kbd{#} character as part of the pattern. @end ifset @end table If no addresses are given, then all lines are matched; if one address is given, then only lines matching that address are matched. @cindex Range of lines @cindex Several lines, selecting An address range can be specified by specifying two addresses separated by a comma (@code{,}). An address range matches lines starting from where the first address matches, and continues until the second address matches (inclusively). If the second address is a @var{regexp}, then checking for the ending match will start with the line @emph{following} the line which matched the first address: a range will always span at least two lines (except of course if the input stream ends). If the second address is a @var{number} less than (or equal to) the line matching the first address, then only the one line is matched. @cindex Special addressing forms @cindex Range with start address of zero @cindex Zero, as range start address @cindex @var{addr1},+N @cindex @var{addr1},~N @cindex @acronym{GNU} extensions, special two-address forms @cindex @acronym{GNU} extensions, @code{0} address @cindex @acronym{GNU} extensions, 0,@var{addr2} addressing @cindex @acronym{GNU} extensions, @var{addr1},+@var{N} addressing @cindex @acronym{GNU} extensions, @var{addr1},~@var{N} addressing @value{SSED} also supports some special two-address forms; all these are @acronym{GNU} extensions: @table @code @item 0,/@var{regexp}/ A line number of @code{0} can be used in an address specification like @code{0,/@var{regexp}/} so that @command{sed} will try to match @var{regexp} in the first input line too. In other words, @code{0,/@var{regexp}/} is similar to @code{1,/@var{regexp}/}, except that if @var{addr2} matches the very first line of input the @code{0,/@var{regexp}/} form will consider it to end the range, whereas the @code{1,/@var{regexp}/} form will match the beginning of its range and hence make the range span up to the @emph{second} occurrence of the regular expression. Note that this is the only place where the @code{0} address makes sense; there is no 0-th line and commands which are given the @code{0} address in any other way will give an error. @item @var{addr1},+@var{N} Matches @var{addr1} and the @var{N} lines following @var{addr1}. @item @var{addr1},~@var{N} Matches @var{addr1} and the lines following @var{addr1} until the next line whose input line number is a multiple of @var{N}. @end table @cindex Excluding lines @cindex Selecting non-matching lines Appending the @code{!} character to the end of an address specification negates the sense of the match. That is, if the @code{!} character follows an address range, then only lines which do @emph{not} match the address range will be selected. This also works for singleton addresses, and, perhaps perversely, for the null address. @node Regular Expressions @section Overview of Regular Expression Syntax To know how to use @command{sed}, people should understand regular expressions (@dfn{regexp} for short). A regular expression is a pattern that is matched against a subject string from left to right. Most characters are @dfn{ordinary}: they stand for themselves in a pattern, and match the corresponding characters in the subject. As a trivial example, the pattern @example The quick brown fox @end example @noindent matches a portion of a subject string that is identical to itself. The power of regular expressions comes from the ability to include alternatives and repetitions in the pattern. These are encoded in the pattern by the use of @dfn{special characters}, which do not stand for themselves but instead are interpreted in some special way. Here is a brief description of regular expression syntax as used in @command{sed}. @table @code @item @var{char} A single ordinary character matches itself. @item * @cindex @acronym{GNU} extensions, to basic regular expressions Matches a sequence of zero or more instances of matches for the preceding regular expression, which must be an ordinary character, a special character preceded by @code{\}, a @code{.}, a grouped regexp (see below), or a bracket expression. As a @acronym{GNU} extension, a postfixed regular expression can also be followed by @code{*}; for example, @code{a**} is equivalent to @code{a*}. @acronym{POSIX} 1003.1-2001 says that @code{*} stands for itself when it appears at the start of a regular expression or subexpression, but many non@acronym{GNU} implementations do not support this and portable scripts should instead use @code{\*} in these contexts. @item \+ @cindex @acronym{GNU} extensions, to basic regular expressions As @code{*}, but matches one or more. It is a @acronym{GNU} extension. @item \? @cindex @acronym{GNU} extensions, to basic regular expressions As @code{*}, but only matches zero or one. It is a @acronym{GNU} extension. @item \@{@var{i}\@} As @code{*}, but matches exactly @var{i} sequences (@var{i} is a decimal integer; for portability, keep it between 0 and 255 inclusive). @item \@{@var{i},@var{j}\@} Matches between @var{i} and @var{j}, inclusive, sequences. @item \@{@var{i},\@} Matches more than or equal to @var{i} sequences. @item \(@var{regexp}\) Groups the inner @var{regexp} as a whole, this is used to: @itemize @bullet @item @cindex @acronym{GNU} extensions, to basic regular expressions Apply postfix operators, like @code{\(abcd\)*}: this will search for zero or more whole sequences of @samp{abcd}, while @code{abcd*} would search for @samp{abc} followed by zero or more occurrences of @samp{d}. Note that support for @code{\(abcd\)*} is required by @acronym{POSIX} 1003.1-2001, but many non-@acronym{GNU} implementations do not support it and hence it is not universally portable. @item Use back references (see below). @end itemize @item . Matches any character, including newline. @item ^ Matches the null string at beginning of line, i.e. what appears after the circumflex must appear at the beginning of line. @code{^#include} will match only lines where @samp{#include} is the first thing on line---if there are spaces before, for example, the match fails. @code{^} acts as a special character only at the beginning of the regular expression or subexpression (that is, after @code{\(} or @code{\|}). Portable scripts should avoid @code{^} at the beginning of a subexpression, though, as @acronym{POSIX} allows implementations that treat @code{^} as an ordinary character in that context. @item $ It is the same as @code{^}, but refers to end of line. @code{$} also acts as a special character only at the end of the regular expression or subexpression (that is, before @code{\)} or @code{\|}), and its use at the end of a subexpression is not portable. @item [@var{list}] @itemx [^@var{list}] Matches any single character in @var{list}: for example, @code{[aeiou]} matches all vowels. A list may include sequences like @code{@var{char1}-@var{char2}}, which matches any character between (inclusive) @var{char1} and @var{char2}. A leading @code{^} reverses the meaning of @var{list}, so that it matches any single character @emph{not} in @var{list}. To include @code{]} in the list, make it the first character (after the @code{^} if needed), to include @code{-} in the list, make it the first or last; to include @code{^} put it after the first character. @cindex @code{POSIXLY_CORRECT} behavior, bracket expressions The characters @code{$}, @code{*}, @code{.}, @code{[}, and @code{\} are normally not special within @var{list}. For example, @code{[\*]} matches either @samp{\} or @samp{*}, because the @code{\} is not special here. However, strings like @code{[.ch.]}, @code{[=a=]}, and @code{[:space:]} are special within @var{list} and represent collating symbols, equivalence classes, and character classes, respectively, and @code{[} is therefore special within @var{list} when it is followed by @code{.}, @code{=}, or @code{:}. Also, when not in @env{POSIXLY_CORRECT} mode, special escapes like @code{\n} and @code{\t} are recognized within @var{list}. @xref{Escapes}. @item @var{regexp1}\|@var{regexp2} @cindex @acronym{GNU} extensions, to basic regular expressions Matches either @var{regexp1} or @var{regexp2}. Use parentheses to use complex alternative regular expressions. The matching process tries each alternative in turn, from left to right, and the first one that succeeds is used. It is a @acronym{GNU} extension. @item @var{regexp1}@var{regexp2} Matches the concatenation of @var{regexp1} and @var{regexp2}. Concatenation binds more tightly than @code{\|}, @code{^}, and @code{$}, but less tightly than the other regular expression operators. @item \@var{digit} Matches the @var{digit}-th @code{\(@dots{}\)} parenthesized subexpression in the regular expression. This is called a @dfn{back reference}. Subexpressions are implicity numbered by counting occurrences of @code{\(} left-to-right. @item \n Matches the newline character. @item \@var{char} Matches @var{char}, where @var{char} is one of @code{$}, @code{*}, @code{.}, @code{[}, @code{\}, or @code{^}. Note that the only C-like backslash sequences that you can portably assume to be interpreted are @code{\n} and @code{\\}; in particular @code{\t} is not portable, and matches a @samp{t} under most implementations of @command{sed}, rather than a tab character. @end table @cindex Greedy regular expression matching Note that the regular expression matcher is greedy, i.e., matches are attempted from left to right and, if two or more matches are possible starting at the same character, it selects the longest. @noindent Examples: @table @samp @item abcdef Matches @samp{abcdef}. @item a*b Matches zero or more @samp{a}s followed by a single @samp{b}. For example, @samp{b} or @samp{aaaaab}. @item a\?b Matches @samp{b} or @samp{ab}. @item a\+b\+ Matches one or more @samp{a}s followed by one or more @samp{b}s: @samp{ab} is the shortest possible match, but other examples are @samp{aaaab} or @samp{abbbbb} or @samp{aaaaaabbbbbbb}. @item .* @itemx .\+ These two both match all the characters in a string; however, the first matches every string (including the empty string), while the second matches only strings containing at least one character. @item ^main.*(.*) his matches a string starting with @samp{main}, followed by an opening and closing parenthesis. The @samp{n}, @samp{(} and @samp{)} need not be adjacent. @item ^# This matches a string beginning with @samp{#}. @item \\$ This matches a string ending with a single backslash. The regexp contains two backslashes for escaping. @item \$ Instead, this matches a string consisting of a single dollar sign, because it is escaped. @item [a-zA-Z0-9] In the C locale, this matches any @acronym{ASCII} letters or digits. @item [^ @kbd{tab}]\+ (Here @kbd{tab} stands for a single tab character.) This matches a string of one or more characters, none of which is a space or a tab. Usually this means a word. @item ^\(.*\)\n\1$ This matches a string consisting of two equal substrings separated by a newline. @item .\@{9\@}A$ This matches nine characters followed by an @samp{A}. @item ^.\@{15\@}A This matches the start of a string that contains 16 characters, the last of which is an @samp{A}. @end table @node Common Commands @section Often-Used Commands If you use @command{sed} at all, you will quite likely want to know these commands. @table @code @item # [No addresses allowed.] @findex # (comments) @cindex Comments, in scripts The @code{#} character begins a comment; the comment continues until the next newline. @cindex Portability, comments If you are concerned about portability, be aware that some implementations of @command{sed} (which are not @sc{posix} conformant) may only support a single one-line comment, and then only when the very first character of the script is a @code{#}. @findex -n, forcing from within a script @cindex Caveat --- #n on first line Warning: if the first two characters of the @command{sed} script are @code{#n}, then the @option{-n} (no-autoprint) option is forced. If you want to put a comment in the first line of your script and that comment begins with the letter @samp{n} and you do not want this behavior, then be sure to either use a capital @samp{N}, or place at least one space before the @samp{n}. @item q [@var{exit-code}] This command only accepts a single address. @findex q (quit) command @cindex @value{SSEDEXT}, returning an exit code @cindex Quitting Exit @command{sed} without processing any more commands or input. Note that the current pattern space is printed if auto-print is not disabled with the @option{-n} options. The ability to return an exit code from the @command{sed} script is a @value{SSED} extension. @item d @findex d (delete) command @cindex Text, deleting Delete the pattern space; immediately start next cycle. @item p @findex p (print) command @cindex Text, printing Print out the pattern space (to the standard output). This command is usually only used in conjunction with the @option{-n} command-line option. @item n @findex n (next-line) command @cindex Next input line, replace pattern space with @cindex Read next input line If auto-print is not disabled, print the pattern space, then, regardless, replace the pattern space with the next line of input. If there is no more input then @command{sed} exits without processing any more commands. @item @{ @var{commands} @} @findex @{@} command grouping @cindex Grouping commands @cindex Command groups A group of commands may be enclosed between @code{@{} and @code{@}} characters. This is particularly useful when you want a group of commands to be triggered by a single address (or address-range) match. @end table @node The "s" Command @section The @code{s} Command The syntax of the @code{s} (as in substitute) command is @samp{s/@var{regexp}/@var{replacement}/@var{flags}}. The @code{/} characters may be uniformly replaced by any other single character within any given @code{s} command. The @code{/} character (or whatever other character is used in its stead) can appear in the @var{regexp} or @var{replacement} only if it is preceded by a @code{\} character. The @code{s} command is probably the most important in @command{sed} and has a lot of different options. Its basic concept is simple: the @code{s} command attempts to match the pattern space against the supplied @var{regexp}; if the match is successful, then that portion of the pattern space which was matched is replaced with @var{replacement}. @cindex Backreferences, in regular expressions @cindex Parenthesized substrings The @var{replacement} can contain @code{\@var{n}} (@var{n} being a number from 1 to 9, inclusive) references, which refer to the portion of the match which is contained between the @var{n}th @code{\(} and its matching @code{\)}. Also, the @var{replacement} can contain unescaped @code{&} characters which reference the whole matched portion of the pattern space. @cindex @value{SSEDEXT}, case modifiers in @code{s} commands Finally, as a @value{SSED} extension, you can include a special sequence made of a backslash and one of the letters @code{L}, @code{l}, @code{U}, @code{u}, or @code{E}. The meaning is as follows: @table @code @item \L Turn the replacement to lowercase until a @code{\U} or @code{\E} is found, @item \l Turn the next character to lowercase, @item \U Turn the replacement to uppercase until a @code{\L} or @code{\E} is found, @item \u Turn the next character to uppercase, @item \E Stop case conversion started by @code{\L} or @code{\U}. @end table To include a literal @code{\}, @code{&}, or newline in the final replacement, be sure to precede the desired @code{\}, @code{&}, or newline in the @var{replacement} with a @code{\}. @findex s command, option flags @cindex Substitution of text, options The @code{s} command can be followed by zero or more of the following @var{flags}: @table @code @item g @cindex Global substitution @cindex Replacing all text matching regexp in a line Apply the replacement to @emph{all} matches to the @var{regexp}, not just the first. @item @var{number} @cindex Replacing only @var{n}th match of regexp in a line Only replace the @var{number}th match of the @var{regexp}. @cindex @acronym{GNU} extensions, @code{g} and @var{number} modifier interaction in @code{s} command @cindex Mixing @code{g} and @var{number} modifiers in the @code{s} command Note: the @sc{posix} standard does not specify what should happen when you mix the @code{g} and @var{number} modifiers, and currently there is no widely agreed upon meaning across @command{sed} implementations. For @value{SSED}, the interaction is defined to be: ignore matches before the @var{number}th, and then match and replace all matches from the @var{number}th on. @item p @cindex Text, printing after substitution If the substitution was made, then print the new pattern space. Note: when both the @code{p} and @code{e} options are specified, the relative ordering of the two produces very different results. In general, @code{ep} (evaluate then print) is what you want, but operating the other way round can be useful for debugging. For this reason, the current version of @value{SSED} interprets specially the presence of @code{p} options both before and after @code{e}, printing the pattern space before and after evaluation, while in general flags for the @code{s} command show their effect just once. This behavior, although documented, might change in future versions. @item w @var{file-name} @cindex Text, writing to a file after substitution @cindex @value{SSEDEXT}, @file{/dev/stdout} file @cindex @value{SSEDEXT}, @file{/dev/stderr} file If the substitution was made, then write out the result to the named file. As a @value{SSED} extension, two special values of @var{file-name} are supported: @file{/dev/stderr}, which writes the result to the standard error, and @file{/dev/stdout}, which writes to the standard output.@footnote{This is equivalent to @code{p} unless the @option{-i} option is being used.} @item e @cindex Evaluate Bourne-shell commands, after substitution @cindex Subprocesses @cindex @value{SSEDEXT}, evaluating Bourne-shell commands @cindex @value{SSEDEXT}, subprocesses This command allows one to pipe input from a shell command into pattern space. If a substitution was made, the command that is found in pattern space is executed and pattern space is replaced with its output. A trailing newline is suppressed; results are undefined if the command to be executed contains a @sc{nul} character. This is a @value{SSED} extension. @item I @itemx i @cindex @acronym{GNU} extensions, @code{I} modifier @cindex Case-insensitive matching @ifset PERL @cindex Perl-style regular expressions, case-insensitive @end ifset The @code{I} modifier to regular-expression matching is a @acronym{GNU} extension which makes @command{sed} match @var{regexp} in a case-insensitive manner. @item M @itemx m @cindex @value{SSEDEXT}, @code{M} modifier @ifset PERL @cindex Perl-style regular expressions, multiline @end ifset The @code{M} modifier to regular-expression matching is a @value{SSED} extension which causes @code{^} and @code{$} to match respectively (in addition to the normal behavior) the empty string after a newline, and the empty string before a newline. There are special character sequences @ifset PERL (@code{\A} and @code{\Z} in Perl mode, @code{\`} and @code{\'} in basic or extended regular expression modes) @end ifset @ifclear PERL (@code{\`} and @code{\'}) @end ifclear which always match the beginning or the end of the buffer. @code{M} stands for @cite{multi-line}. @ifset PERL @item S @itemx s @cindex @value{SSEDEXT}, @code{S} modifier @cindex Perl-style regular expressions, single line The @code{S} modifier to regular-expression matching is only valid in Perl mode and specifies that the dot character (@code{.}) will match the newline character too. @code{S} stands for @cite{single-line}. @end ifset @ifset PERL @item X @itemx x @cindex @value{SSEDEXT}, @code{X} modifier @cindex Perl-style regular expressions, extended The @code{X} modifier to regular-expression matching is also valid in Perl mode only. If it is used, whitespace in the pattern (other than in a character class) and characters between a @kbd{#} outside a character class and the next newline character are ignored. An escaping backslash can be used to include a whitespace or @kbd{#} character as part of the pattern. @end ifset @end table @node Other Commands @section Less Frequently-Used Commands Though perhaps less frequently used than those in the previous section, some very small yet useful @command{sed} scripts can be built with these commands. @table @code @item y/@var{source-chars}/@var{dest-chars}/ (The @code{/} characters may be uniformly replaced by any other single character within any given @code{y} command.) @findex y (transliterate) command @cindex Transliteration Transliterate any characters in the pattern space which match any of the @var{source-chars} with the corresponding character in @var{dest-chars}. Instances of the @code{/} (or whatever other character is used in its stead), @code{\}, or newlines can appear in the @var{source-chars} or @var{dest-chars} lists, provide that each instance is escaped by a @code{\}. The @var{source-chars} and @var{dest-chars} lists @emph{must} contain the same number of characters (after de-escaping). @item a\ @itemx @var{text} @cindex @value{SSEDEXT}, two addresses supported by most commands As a @acronym{GNU} extension, this command accepts two addresses. @findex a (append text lines) command @cindex Appending text after a line @cindex Text, appending Queue the lines of text which follow this command (each but the last ending with a @code{\}, which are removed from the output) to be output at the end of the current cycle, or when the next input line is read. Escape sequences in @var{text} are processed, so you should use @code{\\} in @var{text} to print a single backslash. As a @acronym{GNU} extension, if between the @code{a} and the newline there is other than a whitespace-@code{\} sequence, then the text of this line, starting at the first non-whitespace character after the @code{a}, is taken as the first line of the @var{text} block. (This enables a simplification in scripting a one-line add.) This extension also works with the @code{i} and @code{c} commands. @item i\ @itemx @var{text} @cindex @value{SSEDEXT}, two addresses supported by most commands As a @acronym{GNU} extension, this command accepts two addresses. @findex i (insert text lines) command @cindex Inserting text before a line @cindex Text, insertion Immediately output the lines of text which follow this command (each but the last ending with a @code{\}, which are removed from the output). @item c\ @itemx @var{text} @findex c (change to text lines) command @cindex Replacing selected lines with other text Delete the lines matching the address or address-range, and output the lines of text which follow this command (each but the last ending with a @code{\}, which are removed from the output) in place of the last line (or in place of each line, if no addresses were specified). A new cycle is started after this command is done, since the pattern space will have been deleted. @item = @cindex @value{SSEDEXT}, two addresses supported by most commands As a @acronym{GNU} extension, this command accepts two addresses. @findex = (print line number) command @cindex Printing line number @cindex Line number, printing Print out the current input line number (with a trailing newline). @item l @var{n} @findex l (list unambiguously) command @cindex List pattern space @cindex Printing text unambiguously @cindex Line length, setting @cindex @value{SSEDEXT}, setting line length Print the pattern space in an unambiguous form: non-printable characters (and the @code{\} character) are printed in C-style escaped form; long lines are split, with a trailing @code{\} character to indicate the split; the end of each line is marked with a @code{$}. @var{n} specifies the desired line-wrap length; a length of 0 (zero) means to never wrap long lines. If omitted, the default as specified on the command line is used. The @var{n} parameter is a @value{SSED} extension. @item r @var{filename} @cindex @value{SSEDEXT}, two addresses supported by most commands As a @acronym{GNU} extension, this command accepts two addresses. @findex r (read file) command @cindex Read text from a file @cindex @value{SSEDEXT}, @file{/dev/stdin} file Queue the contents of @var{filename} to be read and inserted into the output stream at the end of the current cycle, or when the next input line is read. Note that if @var{filename} cannot be read, it is treated as if it were an empty file, without any error indication. As a @value{SSED} extension, the special value @file{/dev/stdin} is supported for the file name, which reads the contents of the standard input. @item w @var{filename} @findex w (write file) command @cindex Write to a file @cindex @value{SSEDEXT}, @file{/dev/stdout} file @cindex @value{SSEDEXT}, @file{/dev/stderr} file Write the pattern space to @var{filename}. As a @value{SSED} extension, two special values of @var{file-name} are supported: @file{/dev/stderr}, which writes the result to the standard error, and @file{/dev/stdout}, which writes to the standard output.@footnote{This is equivalent to @code{p} unless the @option{-i} option is being used.} The file will be created (or truncated) before the first input line is read; all @code{w} commands (including instances of @code{w} flag on successful @code{s} commands) which refer to the same @var{filename} are output without closing and reopening the file. @item D @findex D (delete first line) command @cindex Delete first line from pattern space Delete text in the pattern space up to the first newline. If any text is left, restart cycle with the resultant pattern space (without reading a new line of input), otherwise start a normal new cycle. @item N @findex N (append Next line) command @cindex Next input line, append to pattern space @cindex Append next input line to pattern space Add a newline to the pattern space, then append the next line of input to the pattern space. If there is no more input then @command{sed} exits without processing any more commands. @item P @findex P (print first line) command @cindex Print first line from pattern space Print out the portion of the pattern space up to the first newline. @item h @findex h (hold) command @cindex Copy pattern space into hold space @cindex Replace hold space with copy of pattern space @cindex Hold space, copying pattern space into Replace the contents of the hold space with the contents of the pattern space. @item H @findex H (append Hold) command @cindex Append pattern space to hold space @cindex Hold space, appending from pattern space Append a newline to the contents of the hold space, and then append the contents of the pattern space to that of the hold space. @item g @findex g (get) command @cindex Copy hold space into pattern space @cindex Replace pattern space with copy of hold space @cindex Hold space, copy into pattern space Replace the contents of the pattern space with the contents of the hold space. @item G @findex G (appending Get) command @cindex Append hold space to pattern space @cindex Hold space, appending to pattern space Append a newline to the contents of the pattern space, and then append the contents of the hold space to that of the pattern space. @item x @findex x (eXchange) command @cindex Exchange hold space with pattern space @cindex Hold space, exchange with pattern space Exchange the contents of the hold and pattern spaces. @end table @node Programming Commands @section Commands for @command{sed} gurus In most cases, use of these commands indicates that you are probably better off programming in something like @command{awk} or Perl. But occasionally one is committed to sticking with @command{sed}, and these commands can enable one to write quite convoluted scripts. @cindex Flow of control in scripts @table @code @item : @var{label} [No addresses allowed.] @findex : (label) command @cindex Labels, in scripts Specify the location of @var{label} for branch commands. In all other respects, a no-op. @item b @var{label} @findex b (branch) command @cindex Branch to a label, unconditionally @cindex Goto, in scripts Unconditionally branch to @var{label}. The @var{label} may be omitted, in which case the next cycle is started. @item t @var{label} @findex t (test and branch if successful) command @cindex Branch to a label, if @code{s///} succeeded @cindex Conditional branch Branch to @var{label} only if there has been a successful @code{s}ubstitution since the last input line was read or conditional branch was taken. The @var{label} may be omitted, in which case the next cycle is started. @end table @node Extended Commands @section Commands Specific to @value{SSED} These commands are specific to @value{SSED}, so you must use them with care and only when you are sure that hindering portability is not evil. They allow you to check for @value{SSED} extensions or to do tasks that are required quite often, yet are unsupported by standard @command{sed}s. @table @code @item e [@var{command}] @findex e (evaluate) command @cindex Evaluate Bourne-shell commands @cindex Subprocesses @cindex @value{SSEDEXT}, evaluating Bourne-shell commands @cindex @value{SSEDEXT}, subprocesses This command allows one to pipe input from a shell command into pattern space. Without parameters, the @code{e} command executes the command that is found in pattern space and replaces the pattern space with the output; a trailing newline is suppressed. If a parameter is specified, instead, the @code{e} command interprets it as a command and sends its output to the output stream (like @code{r} does). The command can run across multiple lines, all but the last ending with a back-slash. In both cases, the results are undefined if the command to be executed contains a @sc{nul} character. @item L @var{n} @findex L (fLow paragraphs) command @cindex Reformat pattern space @cindex Reformatting paragraphs @cindex @value{SSEDEXT}, reformatting paragraphs @cindex @value{SSEDEXT}, @code{L} command This @value{SSED} extension fills and joins lines in pattern space to produce output lines of (at most) @var{n} characters, like @code{fmt} does; if @var{n} is omitted, the default as specified on the command line is used. This command is considered a failed experiment and unless there is enough request (which seems unlikely) will be removed in future versions. @ignore Blank lines, spaces between words, and indentation are preserved in the output; successive input lines with different indentation are not joined; tabs are expanded to 8 columns. If the pattern space contains multiple lines, they are joined, but since the pattern space usually contains a single line, the behavior of a simple @code{L;d} script is the same as @samp{fmt -s} (i.e., it does not join short lines to form longer ones). @var{n} specifies the desired line-wrap length; if omitted, the default as specified on the command line is used. @end ignore @item Q [@var{exit-code}] This command only accepts a single address. @findex Q (silent Quit) command @cindex @value{SSEDEXT}, quitting silently @cindex @value{SSEDEXT}, returning an exit code @cindex Quitting This command is the same as @code{q}, but will not print the contents of pattern space. Like @code{q}, it provides the ability to return an exit code to the caller. This command can be useful because the only alternative ways to accomplish this apparently trivial function are to use the @option{-n} option (which can unnecessarily complicate your script) or resorting to the following snippet, which wastes time by reading the whole file without any visible effect: @example :eat $d @i{Quit silently on the last line} N @i{Read another line, silently} g @i{Overwrite pattern space each time to save memory} b eat @end example @item R @var{filename} @findex R (read line) command @cindex Read text from a file @cindex @value{SSEDEXT}, reading a file a line at a time @cindex @value{SSEDEXT}, @code{R} command @cindex @value{SSEDEXT}, @file{/dev/stdin} file Queue a line of @var{filename} to be read and inserted into the output stream at the end of the current cycle, or when the next input line is read. Note that if @var{filename} cannot be read, or if its end is reached, no line is appended, without any error indication. As with the @code{r} command, the special value @file{/dev/stdin} is supported for the file name, which reads a line from the standard input. @item T @var{label} @findex T (test and branch if failed) command @cindex @value{SSEDEXT}, branch if @code{s///} failed @cindex Branch to a label, if @code{s///} failed @cindex Conditional branch Branch to @var{label} only if there have been no successful @code{s}ubstitutions since the last input line was read or conditional branch was taken. The @var{label} may be omitted, in which case the next cycle is started. @item v @var{version} @findex v (version) command @cindex @value{SSEDEXT}, checking for their presence @cindex Requiring @value{SSED} This command does nothing, but makes @command{sed} fail if @value{SSED} extensions are not supported, simply because other versions of @command{sed} do not implement it. In addition, you can specify the version of @command{sed} that your script requires, such as @code{4.0.5}. The default is @code{4.0} because that is the first version that implemented this command. This command enables all @value{SSEDEXT} even if @env{POSIXLY_CORRECT} is set in the environment. @item W @var{filename} @findex W (write first line) command @cindex Write first line to a file @cindex @value{SSEDEXT}, writing first line to a file Write to the given filename the portion of the pattern space up to the first newline. Everything said under the @code{w} command about file handling holds here too. @end table @node Escapes @section @acronym{GNU} Extensions for Escapes in Regular Expressions @cindex @acronym{GNU} extensions, special escapes Until this chapter, we have only encountered escapes of the form @samp{\^}, which tell @command{sed} not to interpret the circumflex as a special character, but rather to take it literally. For example, @samp{\*} matches a single asterisk rather than zero or more backslashes. @cindex @code{POSIXLY_CORRECT} behavior, escapes This chapter introduces another kind of escape@footnote{All the escapes introduced here are @acronym{GNU} extensions, with the exception of @code{\n}. In basic regular expression mode, setting @code{POSIXLY_CORRECT} disables them inside bracket expressions.}---that is, escapes that are applied to a character or sequence of characters that ordinarily are taken literally, and that @command{sed} replaces with a special character. This provides a way of encoding non-printable characters in patterns in a visible manner. There is no restriction on the appearance of non-printing characters in a @command{sed} script but when a script is being prepared in the shell or by text editing, it is usually easier to use one of the following escape sequences than the binary character it represents: The list of these escapes is: @table @code @item \a Produces or matches a @sc{bel} character, that is an ``alert'' (@sc{ascii} 7). @item \f Produces or matches a form feed (@sc{ascii} 12). @item \n Produces or matches a newline (@sc{ascii} 10). @item \r Produces or matches a carriage return (@sc{ascii} 13). @item \t Produces or matches a horizontal tab (@sc{ascii} 9). @item \v Produces or matches a so called ``vertical tab'' (@sc{ascii} 11). @item \c@var{x} Produces or matches @kbd{@sc{Control}-@var{x}}, where @var{x} is any character. The precise effect of @samp{\c@var{x}} is as follows: if @var{x} is a lower case letter, it is converted to upper case. Then bit 6 of the character (hex 40) is inverted. Thus @samp{\cz} becomes hex 1A, but @samp{\c@{} becomes hex 3B, while @samp{\c;} becomes hex 7B. @item \d@var{xxx} Produces or matches a character whose decimal @sc{ascii} value is @var{xxx}. @item \o@var{xxx} @ifset PERL @item \@var{xxx} @end ifset Produces or matches a character whose octal @sc{ascii} value is @var{xxx}. @ifset PERL The syntax without the @code{o} is active in Perl mode, while the one with the @code{o} is active in the normal or extended @sc{posix} regular expression modes. @end ifset @item \x@var{xx} Produces or matches a character whose hexadecimal @sc{ascii} value is @var{xx}. @end table @samp{\b} (backspace) was omitted because of the conflict with the existing ``word boundary'' meaning. Other escapes match a particular character class and are valid only in regular expressions: @table @code @item \w Matches any ``word'' character. A ``word'' character is any letter or digit or the underscore character. @item \W Matches any ``non-word'' character. @item \b Matches a word boundary; that is it matches if the character to the left is a ``word'' character and the character to the right is a ``non-word'' character, or vice-versa. @item \B Matches everywhere but on a word boundary; that is it matches if the character to the left and the character to the right are either both ``word'' characters or both ``non-word'' characters. @item \` Matches only at the start of pattern space. This is different from @code{^} in multi-line mode. @item \' Matches only at the end of pattern space. This is different from @code{$} in multi-line mode. @ifset PERL @item \G Match only at the start of pattern space or, when doing a global substitution using the @code{s///g} command and option, at the end-of-match position of the prior match. For example, @samp{s/\Ga/Z/g} will change an initial run of @code{a}s to a run of @code{Z}s @end ifset @end table @node Examples @chapter Some Sample Scripts Here are some @command{sed} scripts to guide you in the art of mastering @command{sed}. @menu Some exotic examples: * Centering lines:: * Increment a number:: * Rename files to lower case:: * Print bash environment:: * Reverse chars of lines:: Emulating standard utilities: * tac:: Reverse lines of files * cat -n:: Numbering lines * cat -b:: Numbering non-blank lines * wc -c:: Counting chars * wc -w:: Counting words * wc -l:: Counting lines * head:: Printing the first lines * tail:: Printing the last lines * uniq:: Make duplicate lines unique * uniq -d:: Print duplicated lines of input * uniq -u:: Remove all duplicated lines * cat -s:: Squeezing blank lines @end menu @node Centering lines @section Centering Lines This script centers all lines of a file on a 80 columns width. To change that width, the number in @code{\@{@dots{}\@}} must be replaced, and the number of added spaces also must be changed. Note how the buffer commands are used to separate parts in the regular expressions to be matched---this is a common technique. @c start------------------------------------------- @example #!/usr/bin/sed -f # Put 80 spaces in the buffer 1 @{ x s/^$/ / s/^.*$/&&&&&&&&/ x @} # del leading and trailing spaces y/@kbd{tab}/ / s/^ *// s/ *$// # add a newline and 80 spaces to end of line G # keep first 81 chars (80 + a newline) s/^\(.\@{81\@}\).*$/\1/ # \2 matches half of the spaces, which are moved to the beginning s/^\(.*\)\n\(.*\)\2/\2\1/ @end example @c end--------------------------------------------- @node Increment a number @section Increment a Number This script is one of a few that demonstrate how to do arithmetic in @command{sed}. This is indeed possible,@footnote{@command{sed} guru Greg Ubben wrote an implementation of the @command{dc} @sc{rpn} calculator! It is distributed together with sed.} but must be done manually. To increment one number you just add 1 to last digit, replacing it by the following digit. There is one exception: when the digit is a nine the previous digits must be also incremented until you don't have a nine. This solution by Bruno Haible is very clever and smart because it uses a single buffer; if you don't have this limitation, the algorithm used in @ref{cat -n, Numbering lines}, is faster. It works by replacing trailing nines with an underscore, then using multiple @code{s} commands to increment the last digit, and then again substituting underscores with zeros. @c start------------------------------------------- @example #!/usr/bin/sed -f /[^0-9]/ d # replace all leading 9s by _ (any other character except digits, could # be used) :d s/9\(_*\)$/_\1/ td # incr last digit only. The first line adds a most-significant # digit of 1 if we have to add a digit. # # The @code{tn} commands are not necessary, but make the thing # faster s/^\(_*\)$/1\1/; tn s/8\(_*\)$/9\1/; tn s/7\(_*\)$/8\1/; tn s/6\(_*\)$/7\1/; tn s/5\(_*\)$/6\1/; tn s/4\(_*\)$/5\1/; tn s/3\(_*\)$/4\1/; tn s/2\(_*\)$/3\1/; tn s/1\(_*\)$/2\1/; tn s/0\(_*\)$/1\1/; tn :n y/_/0/ @end example @c end--------------------------------------------- @node Rename files to lower case @section Rename Files to Lower Case This is a pretty strange use of @command{sed}. We transform text, and transform it to be shell commands, then just feed them to shell. Don't worry, even worse hacks are done when using @command{sed}; I have seen a script converting the output of @command{date} into a @command{bc} program! The main body of this is the @command{sed} script, which remaps the name from lower to upper (or vice-versa) and even checks out if the remapped name is the same as the original name. Note how the script is parameterized using shell variables and proper quoting. @c start------------------------------------------- @example #! /bin/sh # rename files to lower/upper case... # # usage: # move-to-lower * # move-to-upper * # or # move-to-lower -R . # move-to-upper -R . # help() @{ cat << eof Usage: $0 [-n] [-r] [-h] files... -n do nothing, only see what would be done -R recursive (use find) -h this message files files to remap to lower case Examples: $0 -n * (see if everything is ok, then...) $0 * $0 -R . eof @} apply_cmd='sh' finder='echo "$@@" | tr " " "\n"' files_only= while : do case "$1" in -n) apply_cmd='cat' ;; -R) finder='find "$@@" -type f';; -h) help ; exit 1 ;; *) break ;; esac shift done if [ -z "$1" ]; then echo Usage: $0 [-h] [-n] [-r] files... exit 1 fi LOWER='abcdefghijklmnopqrstuvwxyz' UPPER='ABCDEFGHIJKLMNOPQRSTUVWXYZ' case `basename $0` in *upper*) TO=$UPPER; FROM=$LOWER ;; *) FROM=$UPPER; TO=$LOWER ;; esac eval $finder | sed -n ' # remove all trailing slashes s/\/*$// # add ./ if there is no path, only a filename /\//! s/^/.\// # save path+filename h # remove path s/.*\/// # do conversion only on filename y/'$FROM'/'$TO'/ # now line contains original path+file, while # hold space contains the new filename x # add converted file name to line, which now contains # path/file-name\nconverted-file-name G # check if converted file name is equal to original file name, # if it is, do not print nothing /^.*\/\(.*\)\n\1/b # now, transform path/fromfile\n, into # mv path/fromfile path/tofile and print it s/^\(.*\/\)\(.*\)\n\(.*\)$/mv "\1\2" "\1\3"/p ' | $apply_cmd @end example @c end--------------------------------------------- @node Print bash environment @section Print @command{bash} Environment This script strips the definition of the shell functions from the output of the @command{set} Bourne-shell command. @c start------------------------------------------- @example #!/bin/sh set | sed -n ' :x @ifinfo # if no occurrence of "=()" print and load next line @end ifinfo @ifnotinfo # if no occurrence of @samp{=()} print and load next line @end ifnotinfo /=()/! @{ p; b; @} / () $/! @{ p; b; @} # possible start of functions section # save the line in case this is a var like FOO="() " h # if the next line has a brace, we quit because # nothing comes after functions n /^@{/ q # print the old line x; p # work on the new line now x; bx ' @end example @c end--------------------------------------------- @node Reverse chars of lines @section Reverse Characters of Lines This script can be used to reverse the position of characters in lines. The technique moves two characters at a time, hence it is faster than more intuitive implementations. Note the @code{tx} command before the definition of the label. This is often needed to reset the flag that is tested by the @code{t} command. Imaginative readers will find uses for this script. An example is reversing the output of @command{banner}.@footnote{This requires another script to pad the output of banner; for example @example #! /bin/sh banner -w $1 $2 $3 $4 | sed -e :a -e '/^.\@{0,'$1'\@}$/ @{ s/$/ /; ba; @}' | ~/sedscripts/reverseline.sed @end example } @c start------------------------------------------- @example #!/usr/bin/sed -f /../! b # Reverse a line. Begin embedding the line between two newlines s/^.*$/\ &\ / # Move first character at the end. The regexp matches until # there are zero or one characters between the markers tx :x s/\(\n.\)\(.*\)\(.\n\)/\3\2\1/ tx # Remove the newline markers s/\n//g @end example @c end--------------------------------------------- @node tac @section Reverse Lines of Files This one begins a series of totally useless (yet interesting) scripts emulating various Unix commands. This, in particular, is a @command{tac} workalike. Note that on implementations other than @acronym{GNU} @command{sed} @ifset PERL and @value{SSED} @end ifset this script might easily overflow internal buffers. @c start------------------------------------------- @example #!/usr/bin/sed -nf # reverse all lines of input, i.e. first line became last, ... # from the second line, the buffer (which contains all previous lines) # is *appended* to current line, so, the order will be reversed 1! G # on the last line we're done -- print everything $ p # store everything on the buffer again h @end example @c end--------------------------------------------- @node cat -n @section Numbering Lines This script replaces @samp{cat -n}; in fact it formats its output exactly like @acronym{GNU} @command{cat} does. Of course this is completely useless and for two reasons: first, because somebody else did it in C, second, because the following Bourne-shell script could be used for the same purpose and would be much faster: @c start------------------------------------------- @example #! /bin/sh sed -e "=" $@@ | sed -e ' s/^/ / N s/^ *\(......\)\n/\1 / ' @end example @c end--------------------------------------------- It uses @command{sed} to print the line number, then groups lines two by two using @code{N}. Of course, this script does not teach as much as the one presented below. The algorithm used for incrementing uses both buffers, so the line is printed as soon as possible and then discarded. The number is split so that changing digits go in a buffer and unchanged ones go in the other; the changed digits are modified in a single step (using a @code{y} command). The line number for the next line is then composed and stored in the hold space, to be used in the next iteration. @c start------------------------------------------- @example #!/usr/bin/sed -nf # Prime the pump on the first line x /^$/ s/^.*$/1/ # Add the correct line number before the pattern G h # Format it and print it s/^/ / s/^ *\(......\)\n/\1 /p # Get the line number from hold space; add a zero # if we're going to add a digit on the next line g s/\n.*$// /^9*$/ s/^/0/ # separate changing/unchanged digits with an x s/.9*$/x&/ # keep changing digits in hold space h s/^.*x// y/0123456789/1234567890/ x # keep unchanged digits in pattern space s/x.*$// # compose the new number, remove the newline implicitly added by G G s/\n// h @end example @c end--------------------------------------------- @node cat -b @section Numbering Non-blank Lines Emulating @samp{cat -b} is almost the same as @samp{cat -n}---we only have to select which lines are to be numbered and which are not. The part that is common to this script and the previous one is not commented to show how important it is to comment @command{sed} scripts properly... @c start------------------------------------------- @example #!/usr/bin/sed -nf /^$/ @{ p b @} # Same as cat -n from now x /^$/ s/^.*$/1/ G h s/^/ / s/^ *\(......\)\n/\1 /p x s/\n.*$// /^9*$/ s/^/0/ s/.9*$/x&/ h s/^.*x// y/0123456789/1234567890/ x s/x.*$// G s/\n// h @end example @c end--------------------------------------------- @node wc -c @section Counting Characters This script shows another way to do arithmetic with @command{sed}. In this case we have to add possibly large numbers, so implementing this by successive increments would not be feasible (and possibly even more complicated to contrive than this script). The approach is to map numbers to letters, kind of an abacus implemented with @command{sed}. @samp{a}s are units, @samp{b}s are tens and so on: we simply add the number of characters on the current line as units, and then propagate the carry to tens, hundreds, and so on. As usual, running totals are kept in hold space. On the last line, we convert the abacus form back to decimal. For the sake of variety, this is done with a loop rather than with some 80 @code{s} commands@footnote{Some implementations have a limit of 199 commands per script}: first we convert units, removing @samp{a}s from the number; then we rotate letters so that tens become @samp{a}s, and so on until no more letters remain. @c start------------------------------------------- @example #!/usr/bin/sed -nf # Add n+1 a's to hold space (+1 is for the newline) s/./a/g H x s/\n/a/ # Do the carry. The t's and b's are not necessary, # but they do speed up the thing t a : a; s/aaaaaaaaaa/b/g; t b; b done : b; s/bbbbbbbbbb/c/g; t c; b done : c; s/cccccccccc/d/g; t d; b done : d; s/dddddddddd/e/g; t e; b done : e; s/eeeeeeeeee/f/g; t f; b done : f; s/ffffffffff/g/g; t g; b done : g; s/gggggggggg/h/g; t h; b done : h; s/hhhhhhhhhh//g : done $! @{ h b @} # On the last line, convert back to decimal : loop /a/! s/[b-h]*/&0/ s/aaaaaaaaa/9/ s/aaaaaaaa/8/ s/aaaaaaa/7/ s/aaaaaa/6/ s/aaaaa/5/ s/aaaa/4/ s/aaa/3/ s/aa/2/ s/a/1/ : next y/bcdefgh/abcdefg/ /[a-h]/ b loop p @end example @c end--------------------------------------------- @node wc -w @section Counting Words This script is almost the same as the previous one, once each of the words on the line is converted to a single @samp{a} (in the previous script each letter was changed to an @samp{a}). It is interesting that real @command{wc} programs have optimized loops for @samp{wc -c}, so they are much slower at counting words rather than characters. This script's bottleneck, instead, is arithmetic, and hence the word-counting one is faster (it has to manage smaller numbers). Again, the common parts are not commented to show the importance of commenting @command{sed} scripts. @c start------------------------------------------- @example #!/usr/bin/sed -nf # Convert words to a's s/[ @kbd{tab}][ @kbd{tab}]*/ /g s/^/ / s/ [^ ][^ ]*/a /g s/ //g # Append them to hold space H x s/\n// # From here on it is the same as in wc -c. /aaaaaaaaaa/! bx; s/aaaaaaaaaa/b/g /bbbbbbbbbb/! bx; s/bbbbbbbbbb/c/g /cccccccccc/! bx; s/cccccccccc/d/g /dddddddddd/! bx; s/dddddddddd/e/g /eeeeeeeeee/! bx; s/eeeeeeeeee/f/g /ffffffffff/! bx; s/ffffffffff/g/g /gggggggggg/! bx; s/gggggggggg/h/g s/hhhhhhhhhh//g :x $! @{ h; b; @} :y /a/! s/[b-h]*/&0/ s/aaaaaaaaa/9/ s/aaaaaaaa/8/ s/aaaaaaa/7/ s/aaaaaa/6/ s/aaaaa/5/ s/aaaa/4/ s/aaa/3/ s/aa/2/ s/a/1/ y/bcdefgh/abcdefg/ /[a-h]/ by p @end example @c end--------------------------------------------- @node wc -l @section Counting Lines No strange things are done now, because @command{sed} gives us @samp{wc -l} functionality for free!!! Look: @c start------------------------------------------- @example #!/usr/bin/sed -nf $= @end example @c end--------------------------------------------- @node head @section Printing the First Lines This script is probably the simplest useful @command{sed} script. It displays the first 10 lines of input; the number of displayed lines is right before the @code{q} command. @c start------------------------------------------- @example #!/usr/bin/sed -f 10q @end example @c end--------------------------------------------- @node tail @section Printing the Last Lines Printing the last @var{n} lines rather than the first is more complex but indeed possible. @var{n} is encoded in the second line, before the bang character. This script is similar to the @command{tac} script in that it keeps the final output in the hold space and prints it at the end: @c start------------------------------------------- @example #!/usr/bin/sed -nf 1! @{; H; g; @} 1,10 !s/[^\n]*\n// $p h @end example @c end--------------------------------------------- Mainly, the scripts keeps a window of 10 lines and slides it by adding a line and deleting the oldest (the substitution command on the second line works like a @code{D} command but does not restart the loop). The ``sliding window'' technique is a very powerful way to write efficient and complex @command{sed} scripts, because commands like @code{P} would require a lot of work if implemented manually. To introduce the technique, which is fully demonstrated in the rest of this chapter and is based on the @code{N}, @code{P} and @code{D} commands, here is an implementation of @command{tail} using a simple ``sliding window.'' This looks complicated but in fact the working is the same as the last script: after we have kicked in the appropriate number of lines, however, we stop using the hold space to keep inter-line state, and instead use @code{N} and @code{D} to slide pattern space by one line: @c start------------------------------------------- @example #!/usr/bin/sed -f 1h 2,10 @{; H; g; @} $q 1,9d N D @end example @c end--------------------------------------------- Note how the first, second and fourth line are inactive after the first ten lines of input. After that, all the script does is: exiting on the last line of input, appending the next input line to pattern space, and removing the first line. @node uniq @section Make Duplicate Lines Unique This is an example of the art of using the @code{N}, @code{P} and @code{D} commands, probably the most difficult to master. @c start------------------------------------------- @example #!/usr/bin/sed -f h :b # On the last line, print and exit $b N /^\(.*\)\n\1$/ @{ # The two lines are identical. Undo the effect of # the n command. g bb @} # If the @code{N} command had added the last line, print and exit $b # The lines are different; print the first and go # back working on the second. P D @end example @c end--------------------------------------------- As you can see, we mantain a 2-line window using @code{P} and @code{D}. This technique is often used in advanced @command{sed} scripts. @node uniq -d @section Print Duplicated Lines of Input This script prints only duplicated lines, like @samp{uniq -d}. @c start------------------------------------------- @example #!/usr/bin/sed -nf $b N /^\(.*\)\n\1$/ @{ # Print the first of the duplicated lines s/.*\n// p # Loop until we get a different line :b $b N /^\(.*\)\n\1$/ @{ s/.*\n// bb @} @} # The last line cannot be followed by duplicates $b # Found a different one. Leave it alone in the pattern space # and go back to the top, hunting its duplicates D @end example @c end--------------------------------------------- @node uniq -u @section Remove All Duplicated Lines This script prints only unique lines, like @samp{uniq -u}. @c start------------------------------------------- @example #!/usr/bin/sed -f # Search for a duplicate line --- until that, print what you find. $b N /^\(.*\)\n\1$/ ! @{ P D @} :c # Got two equal lines in pattern space. At the # end of the file we simply exit $d # Else, we keep reading lines with @code{N} until we # find a different one s/.*\n// N /^\(.*\)\n\1$/ @{ bc @} # Remove the last instance of the duplicate line # and go back to the top D @end example @c end--------------------------------------------- @node cat -s @section Squeezing Blank Lines As a final example, here are three scripts, of increasing complexity and speed, that implement the same function as @samp{cat -s}, that is squeezing blank lines. The first leaves a blank line at the beginning and end if there are some already. @c start------------------------------------------- @example #!/usr/bin/sed -f # on empty lines, join with next # Note there is a star in the regexp :x /^\n*$/ @{ N bx @} # now, squeeze all '\n', this can be also done by: # s/^\(\n\)*/\1/ s/\n*/\ / @end example @c end--------------------------------------------- This one is a bit more complex and removes all empty lines at the beginning. It does leave a single blank line at end if one was there. @c start------------------------------------------- @example #!/usr/bin/sed -f # delete all leading empty lines 1,/^./@{ /./!d @} # on an empty line we remove it and all the following # empty lines, but one :x /./!@{ N s/^\n$// tx @} @end example @c end--------------------------------------------- This removes leading and trailing blank lines. It is also the fastest. Note that loops are completely done with @code{n} and @code{b}, without relying on @command{sed} to restart the the script automatically at the end of a line. @c start------------------------------------------- @example #!/usr/bin/sed -nf # delete all (leading) blanks /./!d # get here: so there is a non empty :x # print it p # get next n # got chars? print it again, etc... /./bx # no, don't have chars: got an empty line :z # get next, if last line we finish here so no trailing # empty lines are written n # also empty? then ignore it, and get next... this will # remove ALL empty lines /./!bz # all empty lines were deleted/ignored, but we have a non empty. As # what we want to do is to squeeze, insert a blank line artificially i\ bx @end example @c end--------------------------------------------- @node Limitations @chapter @value{SSED}'s Limitations and Non-limitations @cindex @acronym{GNU} extensions, unlimited line length @cindex Portability, line length limitations For those who want to write portable @command{sed} scripts, be aware that some implementations have been known to limit line lengths (for the pattern and hold spaces) to be no more than 4000 bytes. The @sc{posix} standard specifies that conforming @command{sed} implementations shall support at least 8192 byte line lengths. @value{SSED} has no built-in limit on line length; as long as it can @code{malloc()} more (virtual) memory, you can feed or construct lines as long as you like. However, recursion is used to handle subpatterns and indefinite repetition. This means that the available stack space may limit the size of the buffer that can be processed by certain patterns. @ifset PERL There are some size limitations in the regular expression matcher but it is hoped that they will never in practice be relevant. The maximum length of a compiled pattern is 65539 (sic) bytes. All values in repeating quantifiers must be less than 65536. The maximum nesting depth of all parenthesized subpatterns, including capturing and non-capturing subpatterns@footnote{The distinction is meaningful when referring to Perl-style regular expressions.}, assertions, and other types of subpattern, is 200. Also, @value{SSED} recognizes the @sc{posix} syntax @code{[.@var{ch}.]} and @code{[=@var{ch}=]} where @var{ch} is a ``collating element'', but these are not supported, and an error is given if they are encountered. Here are a few distinctions between the real Perl-style regular expressions and those that @option{-R} recognizes. @enumerate @item Lookahead assertions do not allow repeat quantifiers after them Perl permits them, but they do not mean what you might think. For example, @samp{(?!a)@{3@}} does not assert that the next three characters are not @samp{a}. It just asserts three times that the next character is not @samp{a} --- a waste of time and nothing else. @item Capturing subpatterns that occur inside negative lookahead head assertions are counted, but their entries are counted as empty in the second half of an @code{s} command. Perl sets its numerical variables from any such patterns that are matched before the assertion fails to match something (thereby succeeding), but only if the negative lookahead assertion contains just one branch. @item The following Perl escape sequences are not supported: @samp{\l}, @samp{\u}, @samp{\L}, @samp{\U}, @samp{\E}, @samp{\Q}. In fact these are implemented by Perl's general string-handling and are not part of its pattern matching engine. @item The Perl @samp{\G} assertion is not supported as it is not relevant to single pattern matches. @item Fairly obviously, @value{SSED} does not support the @samp{(?@{code@})} and @samp{(?p@{code@})} constructions. However, there is some experimental support for recursive patterns using the non-Perl item @samp{(?R)}. @item There are at the time of writing some oddities in Perl 5.005_02 concerned with the settings of captured strings when part of a pattern is repeated. For example, matching @samp{aba} against the pattern @samp{/^(a(b)?)+$/} sets @samp{$2}@footnote{@samp{$2} would be @samp{\2} in @value{SSED}.} to the value @samp{b}, but matching @samp{aabbaa} against @samp{/^(aa(bb)?)+$/} leaves @samp{$2} unset. However, if the pattern is changed to @samp{/^(aa(b(b))?)+$/} then @samp{$2} (and @samp{$3}) are set. In Perl 5.004 @samp{$2} is set in both cases, and that is also true of @value{SSED}. @item Another as yet unresolved discrepancy is that in Perl 5.005_02 the pattern @samp{/^(a)?(?(1)a|b)+$/} matches the string @samp{a}, whereas in @value{SSED} it does not. However, in both Perl and @value{SSED} @samp{/^(a)?a/} matched against @samp{a} leaves $1 unset. @end enumerate @end ifset @node Other Resources @chapter Other Resources for Learning About @command{sed} @cindex Additional reading about @command{sed} In addition to several books that have been written about @command{sed} (either specifically or as chapters in books which discuss shell programming), one can find out more about @command{sed} (including suggestions of a few books) from the FAQ for the @code{sed-users} mailing list, available from any of: @display @uref{http://www.student.northpark.edu/pemente/sed/sedfaq.html} @uref{http://sed.sf.net/grabbag/tutorials/sedfaq.html} @end display Also of interest are @uref{http://www.student.northpark.edu/pemente/sed/index.htm} and @uref{http://sed.sf.net/grabbag}, which include @command{sed} tutorials and other @command{sed}-related goodies. The @code{sed-users} mailing list itself maintained by Sven Guckes. To subscribe, visit @uref{http://groups.yahoo.com} and search for the @code{sed-users} mailing list. @node Reporting Bugs @chapter Reporting Bugs @cindex Bugs, reporting Email bug reports to @email{bonzini@@gnu.org}. Be sure to include the word ``sed'' somewhere in the @code{Subject:} field. Also, please include the output of @samp{sed --version} in the body of your report if at all possible. Please do not send a bug report like this: @example @i{while building frobme-1.3.4} $ configure @error{} sed: file sedscr line 1: Unknown option to 's' @end example If @value{SSED} doesn't configure your favorite package, take a few extra minutes to identify the specific problem and make a stand-alone test case. Unlike other programs such as C compilers, making such test cases for @command{sed} is quite simple. A stand-alone test case includes all the data necessary to perform the test, and the specific invocation of @command{sed} that causes the problem. The smaller a stand-alone test case is, the better. A test case should not involve something as far removed from @command{sed} as ``try to configure frobme-1.3.4''. Yes, that is in principle enough information to look for the bug, but that is not a very practical prospect. Here are a few commonly reported bugs that are not bugs. @table @asis @item @code{N} command on the last line @cindex Portability, @code{N} command on the last line @cindex Non-bugs, @code{N} command on the last line Most versions of @command{sed} exit without printing anything when the @command{N} command is issued on the last line of a file. @value{SSED} prints pattern space before exiting unless of course the @command{-n} command switch has been specified. This choice is by design. For example, the behavior of @example sed N foo bar @end example @noindent would depend on whether foo has an even or an odd number of lines@footnote{which is the actual ``bug'' that prompted the change in behavior}. Or, when writing a script to read the next few lines following a pattern match, traditional implementations of @code{sed} would force you to write something like @example /foo/@{ $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N @} @end example @noindent instead of just @example /foo/@{ N;N;N;N;N;N;N;N;N; @} @end example @cindex @code{POSIXLY_CORRECT} behavior, @code{N} command In any case, the simplest workaround is to use @code{$d;N} in scripts that rely on the traditional behavior, or to set the @code{POSIXLY_CORRECT} variable to a non-empty value. @item Regex syntax clashes (problems with backslashes) @cindex @acronym{GNU} extensions, to basic regular expressions @cindex Non-bugs, regex syntax clashes @command{sed} uses the @sc{posix} basic regular expression syntax. According to the standard, the meaning of some escape sequences is undefined in this syntax; notable in the case of @command{sed} are @code{\|}, @code{\+}, @code{\?}, @code{\`}, @code{\'}, @code{\<}, @code{\>}, @code{\b}, @code{\B}, @code{\w}, and @code{\W}. As in all @acronym{GNU} programs that use @sc{posix} basic regular expressions, @command{sed} interprets these escape sequences as special characters. So, @code{x\+} matches one or more occurrences of @samp{x}. @code{abc\|def} matches either @samp{abc} or @samp{def}. This syntax may cause problems when running scripts written for other @command{sed}s. Some @command{sed} programs have been written with the assumption that @code{\|} and @code{\+} match the literal characters @code{|} and @code{+}. Such scripts must be modified by removing the spurious backslashes if they are to be used with modern implementations of @command{sed}, like @ifset PERL @value{SSED} or @end ifset @acronym{GNU} @command{sed}. On the other hand, some scripts use s|abc\|def||g to remove occurrences of @emph{either} @code{abc} or @code{def}. While this worked until @command{sed} 4.0.x, newer versions interpret this as removing the string @code{abc|def}. This is again undefined behavior according to @acronym{POSIX}, and this interpretation is arguably more robust: older @command{sed}s, for example, required that the regex matcher parsed @code{\/} as @code{/} in the common case of escaping a slash, which is again undefined behavior; the new behavior avoids this, and this is good because the regex matcher is only partially under our control. @cindex @acronym{GNU} extensions, special escapes In addition, this version of @command{sed} supports several escape characters (some of which are multi-character) to insert non-printable characters in scripts (@code{\a}, @code{\c}, @code{\d}, @code{\o}, @code{\r}, @code{\t}, @code{\v}, @code{\x}). These can cause similar problems with scripts written for other @command{sed}s. @item @option{-i} clobbers read-only files @cindex In-place editing @cindex @value{SSEDEXT}, in-place editing @cindex Non-bugs, in-place editing In short, @samp{sed -i} will let you delete the contents of a read-only file, and in general the @option{-i} option (@pxref{Invoking sed, , Invocation}) lets you clobber protected files. This is not a bug, but rather a consequence of how the Unix filesystem works. The permissions on a file say what can happen to the data in that file, while the permissions on a directory say what can happen to the list of files in that directory. @samp{sed -i} will not ever open for writing a file that is already on disk. Rather, it will work on a temporary file that is finally renamed to the original name: if you rename or delete files, you're actually modifying the contents of the directory, so the operation depends on the permissions of the directory, not of the file. For this same reason, @command{sed} does not let you use @option{-i} on a writeable file in a read-only directory (but unbelievably nobody reports that as a bug@dots{}). @item @code{0a} does not work (gives an error) There is no line 0. 0 is a special address that is only used to treat addresses like @code{0,/@var{RE}/} as active when the script starts: if you write @code{1,/abc/d} and the first line includes the word @samp{abc}, then that match would be ignored because address ranges must span at least two lines (barring the end of the file); but what you probably wanted is to delete every line up to the first one including @samp{abc}, and this is obtained with @code{0,/abc/d}. @ifclear PERL @item @code{[a-z]} is case insensitive You are encountering problems with locales. POSIX mandates that @code{[a-z]} uses the current locale's collation order -- in C parlance, that means using @code{strcoll(3)} instead of @code{strcmp(3)}. Some locales have a case-insensitive collation order, others don't: one of those that have problems is Estonian. Another problem is that @code{[a-z]} tries to use collation symbols. This only happens if you are on the @acronym{GNU} system, using @acronym{GNU} libc's regular expression matcher instead of compiling the one supplied with @acronym{GNU} sed. In a Danish locale, for example, the regular expression @code{^[a-z]$} matches the string @samp{aa}, because this is a single collating symbol that comes after @samp{a} and before @samp{b}; @samp{ll} behaves similarly in Spanish locales, or @samp{ij} in Dutch locales. To work around these problems, which may cause bugs in shell scripts, set the @env{LC_COLLATE} and @env{LC_CTYPE} environment variables to @samp{C}. @end ifclear @end table @node Extended regexps @appendix Extended regular expressions @cindex Extended regular expressions, syntax The only difference between basic and extended regular expressions is in the behavior of a few characters: @samp{?}, @samp{+}, parentheses, and braces (@samp{@{@}}). While basic regular expressions require these to be escaped if you want them to behave as special characters, when using extended regular expressions you must escape them if you want them @emph{to match a literal character}. @noindent Examples: @table @code @item abc? becomes @samp{abc\?} when using extended regular expressions. It matches the literal string @samp{abc?}. @item c\+ becomes @samp{c+} when using extended regular expressions. It matches one or more @samp{c}s. @item a\@{3,\@} becomes @samp{a@{3,@}} when using extended regular expressions. It matches three or more @samp{a}s. @item \(abc\)\@{2,3\@} becomes @samp{(abc)@{2,3@}} when using extended regular expressions. It matches either @samp{abcabc} or @samp{abcabcabc}. @item \(abc*\)\1 becomes @samp{(abc*)\1} when using extended regular expressions. Backreferences must still be escaped when using extended regular expressions. @end table @ifset PERL @node Perl regexps @appendix Perl-style regular expressions @cindex Perl-style regular expressions, syntax @emph{This part is taken from the @file{pcre.txt} file distributed together with the free @sc{pcre} regular expression matcher; it was written by Philip Hazel.} Perl introduced several extensions to regular expressions, some of them incompatible with the syntax of regular expressions accepted by Emacs and other @acronym{GNU} tools (whose matcher was based on the Emacs matcher). @value{SSED} implements both kinds of extensions. @iftex Summarizing, we have: @itemize @bullet @item A backslash can introduce several special sequences @item The circumflex, dollar sign, and period characters behave specially with regard to new lines @item Strange uses of square brackets are parsed differently @item You can toggle modifiers in the middle of a regular expression @item You can specify that a subpattern does not count when numbering backreferences @item @cindex Greedy regular expression matching You can specify greedy or non-greedy matching @item You can have more than ten back references @item You can do complex look aheads and look behinds (in the spirit of @code{\b}, but with subpatterns). @item You can often improve performance by avoiding that @command{sed} wastes time with backtracking @item You can have if/then/else branches @item You can do recursive matches, for example to look for unbalanced parentheses @item You can have comments and non-significant whitespace, because things can get complex... @end itemize Most of these extensions are introduced by the special @code{(?} sequence, which gives special meanings to parenthesized groups. @end iftex @menu Other extensions can be roughly subdivided in two categories On one hand Perl introduces several more escaped sequences (that is, sequences introduced by a backslash). On the other hand, it specifies that if a question mark follows an open parentheses it should give a special meaning to the parenthesized group. * Backslash:: Introduces special sequences * Circumflex/dollar sign/period:: Behave specially with regard to new lines * Square brackets:: Are a bit different in strange cases * Options setting:: Toggle modifiers in the middle of a regexp * Non-capturing subpatterns:: Are not counted when backreferencing * Repetition:: Allows for non-greedy matching * Backreferences:: Allows for more than 10 back references * Assertions:: Allows for complex look ahead matches * Non-backtracking subpatterns:: Often gives more performance * Conditional subpatterns:: Allows if/then/else branches * Recursive patterns:: For example to match parentheses * Comments:: Because things can get complex... @end menu @node Backslash @appendixsec Backslash @cindex Perl-style regular expressions, escaped sequences There are a few difference in the handling of backslashed sequences in Perl mode. First of all, there are no @code{\o} and @code{\d} sequences. @sc{ascii} values for characters can be specified in octal with a @code{\@var{xxx}} sequence, where @var{xxx} is a sequence of up to three octal digits. If the first digit is a zero, the treatment of the sequence is straightforward; just note that if the character that follows the escaped digit is itself an octal digit, you have to supply three octal digits for @var{xxx}. For example @code{\07} is a @sc{bel} character rather than a @sc{nul} and a literal @code{7} (this sequence is instead represented by @code{\0007}). @cindex Perl-style regular expressions, backreferences The handling of a backslash followed by a digit other than 0 is complicated. Outside a character class, @command{sed} reads it and any following digits as a decimal number. If the number is less than 10, or if there have been at least that many previous capturing left parentheses in the expression, the entire sequence is taken as a back reference. A description of how this works is given later, following the discussion of parenthesized subpatterns. Inside a character class, or if the decimal number is greater than 9 and there have not been that many capturing subpatterns, @command{sed} re-reads up to three octal digits following the backslash, and generates a single byte from the least significant 8 bits of the value. Any subsequent digits stand for themselves. For example: @example \040 @i{is another way of writing a space} \40 @i{is the same, provided there are fewer than 40} @i{previous capturing subpatterns} \7 @i{is always a back reference} \011 @i{is always a tab} \11 @i{might be a back reference, or another way of} @i{writing a tab} \0113 @i{is a tab followed by the character @samp{3}} \113 @i{is the character with octal code 113 (since there} @i{can be no more than 99 back references)} \377 @i{is a byte consisting entirely of 1 bits (@sc{ascii} 255)} \81 @i{is either a back reference, or a binary zero} @i{followed by the two characters @samp{81}} @end example Note that octal values of 100 or greater must not be introduced duced by a leading zero, because no more than three octal digits are ever read. All the sequences that define a single byte value can be used both inside and outside character classes. In addition, inside a character class, the sequence @code{\b} is interpreted as the backspace character (hex 08). Outside a character class it has a different meaning (see below). In addition, there are four additional escapes specifying generic character classes (like @code{\w} and @code{\W} do): @cindex Perl-style regular expressions, character classes @table @samp @item \d Matches any decimal digit @item \D Matches any character that is not a decimal digit @end table In Perl mode, these character type sequences can appear both inside and outside character classes. Instead, in @sc{posix} mode these sequences (as well as @code{\w} and @code{\W}) are treated as two literal characters (a backslash and a letter) inside square brackets. Escaped sequences specifying assertions are also different in Perl mode. An assertion specifies a condition that has to be met at a particular point in a match, without consuming any characters from the subject string. The use of subpatterns for more complicated assertions is described below. The backslashed assertions are @cindex Perl-style regular expressions, assertions @table @samp @item \b Asserts that the point is at a word boundary. A word boundary is a position in the subject string where the current character and the previous character do not both match @code{\w} or @code{\W} (i.e. one matches @code{\w} and the other matches @code{\W}), or the start or end of the string if the first or last character matches @code{\w}, respectively. @item \B Asserts that the point is not at a word boundary. @item \A Asserts the matcher is at the start of pattern space (independent of multiline mode). @item \Z Asserts the matcher is at the end of pattern space, or at a newline before the end of pattern space (independent of multiline mode) @item \z Asserts the matcher is at the end of pattern space (independent of multiline mode) @end table These assertions may not appear in character classes (but note that @code{\b} has a different meaning, namely the backspace character, inside a character class). Note that Perl mode does not support directly assertions for the beginning and the end of word; the @acronym{GNU} extensions @code{\<} and @code{\>} achieve this purpose in @sc{posix} mode instead. The @code{\A}, @code{\Z}, and @code{\z} assertions differ from the traditional circumflex and dollar sign (described below) in that they only ever match at the very start and end of the subject string, whatever options are set; in particular @code{\A} and @code{\z} are the same as the @acronym{GNU} extensions @code{\`} and @code{\'} that are active in @sc{posix} mode. @node Circumflex/dollar sign/period @appendixsec Circumflex, dollar sign, period @cindex Perl-style regular expressions, newlines Outside a character class, in the default matching mode, the circumflex character is an assertion which is true only if the current matching point is at the start of the subject string. Inside a character class, the circumflex has an entirely different meaning (see below). The circumflex need not be the first character of the pattern if a number of alternatives are involved, but it should be the first thing in each alternative in which it appears if the pattern is ever to match that branch. If all possible alternatives, start with a circumflex, that is, if the pattern is constrained to match only at the start of the subject, it is said to be an @dfn{anchored} pattern. (There are also other constructs structs that can cause a pattern to be anchored.) A dollar sign is an assertion which is true only if the current matching point is at the end of the subject string, or immediately before a newline character that is the last character in the string (by default). A dollar sign need not be the last character of the pattern if a number of alternatives are involved, but it should be the last item in any branch in which it appears. A dollar sign has no special meaning in a character class. @cindex Perl-style regular expressions, multiline The meanings of the circumflex and dollar sign characters are changed if the @code{M} modifier option is used. When this is the case, they match immediately after and immediately before an internal @code{\n} character, respectively, in addition to matching at the start and end of the subject string. For example, the pattern @code{/^abc$/} matches the subject string @samp{def\nabc} in multiline mode, but not otherwise. Consequently, patterns that are anchored in single line mode because all branches start with @code{^} are not anchored in multiline mode. @cindex Perl-style regular expressions, multiline Note that the sequences @code{\A}, @code{\Z}, and @code{\z} can be used to match the start and end of the subject in both modes, and if all branches of a pattern start with @code{\A} is it always anchored, whether the @code{M} modifier is set or not. @cindex Perl-style regular expressions, single line Outside a character class, a dot in the pattern matches any one character in the subject, including a non-printing character, but not (by default) newline. If the @code{S} modifier is used, dots match newlines as well. Actually, the handling of dot is entirely independent of the handling of circumflex and dollar sign, the only relationship being that they both involve newline characters. Dot has no special meaning in a character class. @node Square brackets @appendixsec Square brackets @cindex Perl-style regular expressions, character classes An opening square bracket introduces a character class, terminated by a closing square bracket. A closing square bracket on its own is not special. If a closing square bracket is required as a member of the class, it should be the first data character in the class (after an initial circumflex, if present) or escaped with a backslash. A character class matches a single character in the subject; the character must be in the set of characters defined by the class, unless the first character in the class is a circumflex, in which case the subject character must not be in the set defined by the class. If a circumflex is actually required as a member of the class, ensure it is not the first character, or escape it with a backslash. For example, the character class [aeiou] matches any lower case vowel, while [^aeiou] matches any character that is not a lower case vowel. Note that a circumflex is just a convenient venient notation for specifying the characters which are in the class by enumerating those that are not. It is not an assertion: it still consumes a character from the subject string, and fails if the current pointer is at the end of the string. @cindex Perl-style regular expressions, case-insensitive When caseless matching is set, any letters in a class represent both their upper case and lower case versions, so for example, a caseless @code{[aeiou]} matches uppercase and lowercase @samp{A}s, and a caseless @code{[^aeiou]} does not match @samp{A}, whereas a case-sensitive version would. @cindex Perl-style regular expressions, single line @cindex Perl-style regular expressions, multiline The newline character is never treated in any special way in character classes, whatever the setting of the @code{S} and @code{M} options (modifiers) is. A class such as @code{[^a]} will always match a newline. The minus (hyphen) character can be used to specify a range of characters in a character class. For example, @code{[d-m]} matches any letter between d and m, inclusive. If a minus character is required in a class, it must be escaped with a backslash or appear in a position where it cannot be interpreted as indicating a range, typically as the first or last character in the class. It is not possible to have the literal character @code{]} as the end character of a range. A pattern such as @code{[W-]46]} is interpreted as a class of two characters (@code{W} and @code{-}) followed by a literal string @code{46]}, so it would match @samp{W46]} or @samp{-46]}. However, if the @code{]} is escaped with a backslash it is interpreted as the end of range, so @code{[W-\]46]} is interpreted as a single class containing a range followed by two separate characters. The octal or hexadecimal representation of @code{]} can also be used to end a range. Ranges operate in @sc{ascii} collating sequence. They can also be used for characters specified numerically, for example @code{[\000-\037]}. If a range that includes letters is used when caseless matching is set, it matches the letters in either case. For example, a caseless @code{[W-c]} is equivalent to @code{[][\^_`wxyzabc]}, matched caselessly, and if character tables for the French locale are in use, @code{[\xc8-\xcb]} matches accented E characters in both cases. Unlike in @sc{posix} mode, the character types @code{\d}, @code{\D}, @code{\s}, @code{\S}, @code{\w}, and @code{\W} may also appear in a character class, and add the characters that they match to the class. For example, @code{[\dABCDEF]} matches any hexadecimal digit. A circumflex can conveniently be used with the upper case character types to specify a more restricted set of characters than the matching lower case type. For example, the class @code{[^\W_]} matches any letter or digit, but not underscore. All non-alphameric characters other than @code{\}, @code{-}, @code{^} (at the start) and the terminating @code{]} are non-special in character classes, but it does no harm if they are escaped. Perl 5.6 supports the @sc{posix} notation for character classes, which uses names enclosed by @code{[:} and @code{:]} within the enclosing square brackets, and @value{SSED} supports this notation as well. For example, @example [01[:alpha:]%] @end example @noindent matches @samp{0}, @samp{1}, any alphabetic character, or @samp{%}. The supported class names are @table @code @item alnum Matches letters and digits @item alpha Matches letters @item ascii Matches character codes 0 - 127 @item cntrl Matches control characters @item digit Matches decimal digits (same as \d) @item graph Matches printing characters, excluding space @item lower Matches lower case letters @item print Matches printing characters, including space @item punct Matches printing characters, excluding letters and digits @item space Matches white space (same as \s) @item upper Matches upper case letters @item word Matches ``word'' characters (same as \w) @item xdigit Matches hexadecimal digits @end table The names @code{ascii} and @code{word} are extensions valid only in Perl mode. Another Perl extension is negation, which is indicated by a circumflex character after the colon. For example, @example [12[:^digit:]] @end example @noindent matches @samp{1}, @samp{2}, or any non-digit. @node Options setting @appendixsec Options setting @cindex Perl-style regular expressions, toggling options @cindex Perl-style regular expressions, case-insensitive @cindex Perl-style regular expressions, multiline @cindex Perl-style regular expressions, single line @cindex Perl-style regular expressions, extended The settings of the @code{I}, @code{M}, @code{S}, @code{X} modifiers can be changed from within the pattern by a sequence of Perl option letters enclosed between @code{(?} and @code{)}. The option letters must be lowercase. For example, @code{(?im)} sets caseless, multiline matching. It is also possible to unset these options by preceding the letter with a hyphen; you can also have combined settings and unsettings: @code{(?im-sx)} sets caseless and multiline matching, while unsets single line matching (for dots) and extended whitespace interpretation. If a letter appears both before and after the hyphen, the option is unset. The scope of these option changes depends on where in the pattern the setting occurs. For settings that are outside any subpattern (defined below), the effect is the same as if the options were set or unset at the start of matching. The following patterns all behave in exactly the same way: @example (?i)abc a(?i)bc ab(?i)c abc(?i) @end example which in turn is the same as specifying the pattern abc with the @code{I} modifier. In other words, ``top level'' settings apply to the whole pattern (unless there are other changes inside subpatterns). If there is more than one setting of the same option at top level, the rightmost setting is used. If an option change occurs inside a subpattern, the effect is different. This is a change of behaviour in Perl 5.005. An option change inside a subpattern affects only that part of the subpattern @emph{that follows} it, so @example (a(?i)b)c @end example @noindent matches abc and aBc and no other strings (assuming case-sensitive matching is used). By this means, options can be made to have different settings in different parts of the pattern. Any changes made in one alternative do carry on into subsequent branches within the same subpattern. For example, @example (a(?i)b|c) @end example @noindent matches @samp{ab}, @samp{aB}, @samp{c}, and @samp{C}, even though when matching @samp{C} the first branch is abandoned before the option setting. This is because the effects of option settings happen at compile time. There would be some very weird behaviour otherwise. @ignore There are two PCRE-specific options PCRE_UNGREEDY and PCRE_EXTRA that can be changed in the same way as the Perl-compatible options by using the characters U and X respectively. The (?X) flag setting is special in that it must always occur earlier in the pattern than any of the additional features it turns on, even when it is at top level. It is best put at the start. @end ignore @node Non-capturing subpatterns @appendixsec Non-capturing subpatterns @cindex Perl-style regular expressions, non-capturing subpatterns Marking part of a pattern as a subpattern does two things. On one hand, it localizes a set of alternatives; on the other hand, it sets up the subpattern as a capturing subpattern (as defined above). The subpattern can be backreferenced and referenced in the right side of @code{s} commands. For example, if the string @samp{the red king} is matched against the pattern @example the ((red|white) (king|queen)) @end example @noindent the captured substrings are @samp{red king}, @samp{red}, and @samp{king}, and are numbered 1, 2, and 3. The fact that plain parentheses fulfil two functions is not always helpful. There are often times when a grouping subpattern is required without a capturing requirement. If an opening parenthesis is followed by @code{?:}, the subpattern does not do any capturing, and is not counted when computing the number of any subsequent capturing subpatterns. For example, if the string @samp{the white queen} is matched against the pattern @example the ((?:red|white) (king|queen)) @end example @noindent the captured substrings are @samp{white queen} and @samp{queen}, and are numbered 1 and 2. The maximum number of captured substrings is 99, while the maximum number of all subpatterns, both capturing and non-capturing, is 200. As a convenient shorthand, if any option settings are equired at the start of a non-capturing subpattern, the option letters may appear between the @code{?} and the @code{:}. Thus the two patterns @example (?i:saturday|sunday) (?:(?i)saturday|sunday) @end example @noindent match exactly the same set of strings. Because alternative branches are tried from left to right, and options are not reset until the end of the subpattern is reached, an option setting in one branch does affect subsequent branches, so the above patterns match @samp{SUNDAY} as well as @samp{Saturday}. @node Repetition @appendixsec Repetition @cindex Perl-style regular expressions, repetitions Repetition is specified by quantifiers, which can follow any of the following items: @itemize @bullet @item a single character, possibly escaped @item the @code{.} special character @item a character class @item a back reference (see next section) @item a parenthesized subpattern (unless it is an assertion; @pxref{Assertions}) @end itemize The general repetition quantifier specifies a minimum and maximum number of permitted matches, by giving the two numbers in curly brackets (braces), separated by a comma. The numbers must be less than 65536, and the first must be less than or equal to the second. For example: @example z@{2,4@} @end example @noindent matches @samp{zz}, @samp{zzz}, or @samp{zzzz}. A closing brace on its own is not a special character. If the second number is omitted, but the comma is present, there is no upper limit; if the second number and the comma are both omitted, the quantifier specifies an exact number of required matches. Thus @example [aeiou]@{3,@} @end example @noindent matches at least 3 successive vowels, but may match many more, while @example \d@{8@} @end example @noindent matches exactly 8 digits. An opening curly bracket that appears in a position where a quantifier is not allowed, or one that does not match the syntax of a quantifier, is taken as a literal character. For example, @{,6@} is not a quantifier, but a literal string of four characters.@footnote{It raises an error if @option{-R} is not used.} The quantifier @samp{@{0@}} is permitted, causing the expression to behave as if the previous item and the quantifier were not present. For convenience (and historical compatibility) the three most common quantifiers have single-character abbreviations: @table @code @item * is equivalent to @{0,@} @item + is equivalent to @{1,@} @item ? is equivalent to @{0,1@} @end table It is possible to construct infinite loops by following a subpattern that can match no characters with a quantifier that has no upper limit, for example: @example (a?)* @end example Earlier versions of Perl used to give an error at compile time for such patterns. However, because there are cases where this can be useful, such patterns are now accepted, but if any repetition of the subpattern does in fact match no characters, the loop is forcibly broken. @cindex Greedy regular expression matching @cindex Perl-style regular expressions, stingy repetitions By default, the quantifiers are @dfn{greedy} like in @sc{posix} mode, that is, they match as much as possible (up to the maximum number of permitted times), without causing the rest of the pattern to fail. The classic example of where this gives problems is in trying to match comments in C programs. These appear between the sequences @code{/*} and @code{*/} and within the sequence, individual @code{*} and @code{/} characters may appear. An attempt to match C comments by applying the pattern @example /\*.*\*/ @end example @noindent to the string @example /* first command */ not comment /* second comment */ @end example @noindent fails, because it matches the entire string owing to the greediness of the @code{.*} item. However, if a quantifier is followed by a question mark, it ceases to be greedy, and instead matches the minimum number of times possible, so the pattern @code{/\*.*?\*/} does the right thing with the C comments. The meaning of the various quantifiers is not otherwise changed, just the preferred number of matches. Do not confuse this use of question mark with its use as a quantifier in its own right. Because it has two uses, it can sometimes appear doubled, as in @example \d??\d @end example which matches one digit by preference, but can match two if that is the only way the rest of the pattern matches. Note that greediness does not matter when specifying addresses, but can be nevertheless used to improve performance. @ignore If the PCRE_UNGREEDY option is set (an option which is not available in Perl), the quantifiers are not greedy by default, but individual ones can be made greedy by following them with a question mark. In other words, it inverts the default behaviour. @end ignore When a parenthesized subpattern is quantified with a minimum repeat count that is greater than 1 or with a limited maximum, more store is required for the compiled pattern, in proportion to the size of the minimum or maximum. @cindex Perl-style regular expressions, single line If a pattern starts with @code{.*} or @code{.@{0,@}} and the @code{S} modifier is used, the pattern is implicitly anchored, because whatever follows will be tried against every character position in the subject string, so there is no point in retrying the overall match at any position after the first. PCRE treats such a pattern as though it were preceded by \A. When a capturing subpattern is repeated, the value captured is the substring that matched the final iteration. For example, after @example (tweedle[dume]@{3@}\s*)+ @end example @noindent has matched @samp{tweedledum tweedledee} the value of the captured substring is @samp{tweedledee}. However, if there are nested capturing subpatterns, the corresponding captured values may have been set in previous iterations. For example, after @example /(a|(b))+/ @end example matches @samp{aba}, the value of the second captured substring is @samp{b}. @node Backreferences @appendixsec Backreferences @cindex Perl-style regular expressions, backreferences Outside a character class, a backslash followed by a digit greater than 0 (and possibly further digits) is a back reference to a capturing subpattern earlier (i.e. to its left) in the pattern, provided there have been that many previous capturing left parentheses. However, if the decimal number following the backslash is less than 10, it is always taken as a back reference, and causes an error only if there are not that many capturing left parentheses in the entire pattern. In other words, the parentheses that are referenced need not be to the left of the reference for numbers less than 10. @ref{Backslash} for further details of the handling of digits following a backslash. A back reference matches whatever actually matched the capturing subpattern in the current subject string, rather than anything matching the subpattern itself. So the pattern @example (sens|respons)e and \1ibility @end example @noindent matches @samp{sense and sensibility} and @samp{response and responsibility}, but not @samp{sense and responsibility}. If caseful matching is in force at the time of the back reference, the case of letters is relevant. For example, @example ((?i)blah)\s+\1 @end example @noindent matches @samp{blah blah} and @samp{Blah Blah}, but not @samp{BLAH blah}, even though the original capturing subpattern is matched caselessly. There may be more than one back reference to the same subpattern. Also, if a subpattern has not actually been used in a particular match, any back references to it always fail. For example, the pattern @example (a|(bc))\2 @end example @noindent always fails if it starts to match @samp{a} rather than @samp{bc}. Because there may be up to 99 back references, all digits following the backslash are taken as part of a potential back reference number; this is different from what happens in @sc{posix} mode. If the pattern continues with a digit character, some delimiter must be used to terminate the back reference. If the @code{X} modifier option is set, this can be whitespace. Otherwise an empty comment can be used, or the following character can be expressed in hexadecimal or octal. A back reference that occurs inside the parentheses to which it refers fails when the subpattern is first used, so, for example, @code{(a\1)} never matches. However, such references can be useful inside repeated subpatterns. For example, the pattern @example (a|b\1)+ @end example @noindent matches any number of @samp{a}s and also @samp{aba}, @samp{ababbaa}, etc. At each iteration of the subpattern, the back reference matches the character string corresponding to the previous iteration. In order for this to work, the pattern must be such that the first iteration does not need to match the back reference. This can be done using alternation, as in the example above, or by a quantifier with a minimum of zero. @node Assertions @appendixsec Assertions @cindex Perl-style regular expressions, assertions @cindex Perl-style regular expressions, asserting subpatterns An assertion is a test on the characters following or preceding the current matching point that does not actually consume any characters. The simple assertions coded as @code{\b}, @code{\B}, @code{\A}, @code{\Z}, @code{\z}, @code{^} and @code{$} are described above. More complicated assertions are coded as subpatterns. There are two kinds: those that look ahead of the current position in the subject string, and those that look behind it. @cindex Perl-style regular expressions, lookahead subpatterns An assertion subpattern is matched in the normal way, except that it does not cause the current matching position to be changed. Lookahead assertions start with @code{(?=} for positive assertions and @code{(?!} for negative assertions. For example, @example \w+(?=;) @end example @noindent matches a word followed by a semicolon, but does not include the semicolon in the match, and @example foo(?!bar) @end example @noindent matches any occurrence of @samp{foo} that is not followed by @samp{bar}. Note that the apparently similar pattern @example (?!foo)bar @end example @noindent @cindex Perl-style regular expressions, lookbehind subpatterns finds any occurrence of @samp{bar} even if it is preceded by @samp{foo}, because the assertion @code{(?!foo)} is always true when the next three characters are @samp{bar}. A lookbehind assertion is needed to achieve this effect. Lookbehind assertions start with @code{(?<=} for positive assertions and @code{(?} as in this example: @example (?>\d+)bar @end example This kind of parenthesis ``locks up'' the part of the pattern it contains once it has matched, and a failure further into the pattern is prevented from backtracking into it. Backtracking past it to previous items, however, works as normal. Non-backtracking subpatterns are not capturing subpatterns. Simple cases such as the above example can be thought of as a maximizing repeat that must swallow everything it can. So, while both @code{\d+} and @code{\d+?} are prepared to adjust the number of digits they match in order to make the rest of the pattern match, @code{(?>\d+)} can only match an entire sequence of digits. This construction can of course contain arbitrarily complicated subpatterns, and it can be nested. @cindex Perl-style regular expressions, lookbehind subpatterns Non-backtracking subpatterns can be used in conjunction with look-behind assertions to specify efficient matching at the end of the subject string. Consider a simple pattern such as @example abcd$ @end example @noindent when applied to a long string which does not match. Because matching proceeds from left to right, @command{sed} will look for each @samp{a} in the subject and then see if what follows matches the rest of the pattern. If the pattern is specified as @example ^.*abcd$ @end example @noindent the initial @code{.*} matches the entire string at first, but when this fails (because there is no following @samp{a}), it backtracks to match all but the last character, then all but the last two characters, and so on. Once again the search for @samp{a} covers the entire string, from right to left, so we are no better off. However, if the pattern is written as @example ^(?>.*)(?<=abcd) @end example there can be no backtracking for the .* item; it can match only the entire string. The subsequent lookbehind assertion does a single test on the last four characters. If it fails, the match fails immediately. For long strings, this approach makes a significant difference to the processing time. When a pattern contains an unlimited repeat inside a subpattern that can itself be repeated an unlimited number of times, the use of a once-only subpattern is the only way to avoid some failing matches taking a very long time indeed.@footnote{Actually, the matcher embedded in @value{SSED} tries to do something for this in the simplest cases, like @code{([^b]*b)*}. These cases are actually quite common: they happen for example in a regular expression like @code{\/\*([^*]*\*)*\/} which matches C comments.} The pattern @example (\D+|<\d+>)*[!?] @end example ([^0-9<]+<(\d+>)?)*[!?] @noindent matches an unlimited number of substrings that either consist of non-digits, or digits enclosed in angular brackets, followed by an exclamation or question mark. When it matches, it runs quickly. However, if it is applied to @example aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @end example @noindent it takes a long time before reporting failure. This is because the string can be divided between the two repeats in a large number of ways, and all have to be tried.@footnote{The example used @code{[!?]} rather than a single character at the end, because both @value{SSED} and Perl have an optimization that allows for fast failure when a single character is used. They remember the last single character that is required for a match, and fail early if it is not present in the string.} If the pattern is changed to @example ((?>\D+)|<\d+>)*[!?] @end example sequences of non-digits cannot be broken, and failure happens quickly. @node Conditional subpatterns @appendixsec Conditional subpatterns @cindex Perl-style regular expressions, conditional subpatterns It is possible to cause the matching process to obey a subpattern conditionally or to choose between two alternative subpatterns, depending on the result of an assertion, or whether a previous capturing subpattern matched or not. The two possible forms of conditional subpattern are @example (?(@var{condition})@var{yes-pattern}) (?(@var{condition})@var{yes-pattern}|@var{no-pattern}) @end example If the condition is satisfied, the yes-pattern is used; otherwise the no-pattern (if present) is used. If there are more than two alternatives in the subpattern, a compile-time error occurs. There are two kinds of condition. If the text between the parentheses consists of a sequence of digits, the condition is satisfied if the capturing subpattern of that number has previously matched. The number must be greater than zero. Consider the following pattern, which contains non-significant white space to make it more readable (assume the @code{X} modifier) and to divide it into three parts for ease of discussion: @example ( \( )? [^()]+ (?(1) \) ) @end example The first part matches an optional opening parenthesis, and if that character is present, sets it as the first captured substring. The second part matches one or more characters that are not parentheses. The third part is a conditional subpattern that tests whether the first set of parentheses matched or not. If they did, that is, if subject started with an opening parenthesis, the condition is true, and so the yes-pattern is executed and a closing parenthesis is required. Otherwise, since no-pattern is not present, the subpattern matches nothing. In other words, this pattern matches a sequence of non-parentheses, optionally enclosed in parentheses. @cindex Perl-style regular expressions, lookahead subpatterns If the condition is not a sequence of digits, it must be an assertion. This may be a positive or negative lookahead or lookbehind assertion. Consider this pattern, again containing non-significant white space, and with the two alternatives on the second line: @example (?(?=...[a-z]) \d\d-[a-z]@{3@}-\d\d | \d\d-\d\d-\d\d ) @end example The condition is a positive lookahead assertion that matches a letter that is three characters away from the current point. If a letter is found, the subject is matched against the first alternative @samp{@var{dd}-@var{aaa}-@var{dd}} (where @var{aaa} are letters and @var{dd} are digits); otherwise it is matched against the second alternative, @samp{@var{dd}-@var{dd}-@var{dd}}. @node Recursive patterns @appendixsec Recursive patterns @cindex Perl-style regular expressions, recursive patterns @cindex Perl-style regular expressions, recursion Consider the problem of matching a string in parentheses, allowing for unlimited nested parentheses. Without the use of recursion, the best that can be done is to use a pattern that matches up to some fixed depth of nesting. It is not possible to handle an arbitrary nesting depth. Perl 5.6 has provided an experimental facility that allows regular expressions to recurse (amongst other things). It does this by interpolating Perl code in the expression at run time, and the code can refer to the expression itself. A Perl pattern tern to solve the parentheses problem can be created like this: @example $re = qr@{\( (?: (?>[^()]+) | (?p@{$re@}) )* \)@}x; @end example The @code{(?p@{...@})} item interpolates Perl code at run time, and in this case refers recursively to the pattern in which it appears. Obviously, @command{sed} cannot support the interpolation of Perl code. Instead, the special item @code{(?R)} is provided for the specific case of recursion. This pattern solves the parentheses problem (assume the @code{X} modifier option is used so that white space is ignored): @example \( ( (?>[^()]+) | (?R) )* \) @end example First it matches an opening parenthesis. Then it matches any number of substrings which can either be a sequence of non-parentheses, or a recursive match of the pattern itself (i.e. a correctly parenthesized substring). Finally there is a closing parenthesis. This particular example pattern contains nested unlimited repeats, and so the use of a non-backtracking subpattern for matching strings of non-parentheses is important when applying the pattern to strings that do not match. For example, when it is applied to @example (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa() @end example it yields a ``no match'' response quickly. However, if a standard backtracking subpattern is not used, the match runs for a very long time indeed because there are so many different ways the @code{+} and @code{*} repeats can carve up the subject, and all have to be tested before failure can be reported. The values set for any capturing subpatterns are those from the outermost level of the recursion at which the subpattern value is set. If the pattern above is matched against @example (ab(cd)ef) @end example @noindent the value for the capturing parentheses is @samp{ef}, which is the last value taken on at the top level. @node Comments @appendixsec Comments @cindex Perl-style regular expressions, comments The sequence (?# marks the start of a comment which continues ues up to the next closing parenthesis. Nested parentheses are not permitted. The characters that make up a comment play no part in the pattern matching at all. @cindex Perl-style regular expressions, extended If the @code{X} modifier option is used, an unescaped @code{#} character outside a character class introduces a comment that continues up to the next newline character in the pattern. @end ifset @page @node Concept Index @unnumbered Concept Index This is a general index of all issues discussed in this manual, with the exception of the @command{sed} commands and command-line options. @printindex cp @page @node Command and Option Index @unnumbered Command and Option Index This is an alphabetical list of all @command{sed} commands and command-line options. @printindex fn @contents @bye @c XXX FIXME: the term "cycle" is never defined... kbuild-3686/src/oldsed/doc/sed.x0000664000175000017500000001510315053010105016454 0ustar locutuslocutus.SH NAME sed \- a Stream EDitor .SH SYNOPSIS .nf sed [-V] [--version] [--help] [-n] [--quiet] [--silent] [-l N] [--line-length=N] [-u] [--unbuffered] [-r] [--regexp-extended] [-e script] [--expression=script] [-f script-file] [--file=script-file] [script-if-no-other-script] [file...] .fi [DESCRIPTION] .ds sd \fIsed\fP .ds Sd \fISed\fP \*(Sd is a stream editor. A stream editor is used to perform basic text transformations on an input stream (a file or input from a pipeline). While in some ways similar to an editor which permits scripted edits (such as \fIed\fP), \*(sd works by making only one pass over the input(s), and is consequently more efficient. But it is \*(sd's ability to filter text in a pipeline which particularly distinguishes it from other types of editors. [COMMAND SYNOPSIS] This is just a brief synopsis of \*(sd commands to serve as a reminder to those who already know \*(sd; other documentation (such as the texinfo document) must be consulted for fuller descriptions. .SS Zero-address ``commands'' .TP .RI :\ label Label for .B b and .B t commands. .TP .RI # comment The comment extends until the next newline (or the end of a .B -e script fragment). .TP } The closing bracket of a { } block. .SS Zero- or One- address commands .TP = Print the current line number. .TP a \e .TP .I text Append .IR text , which has each embedded newline preceded by a backslash. .TP i \e .TP .I text Insert .IR text , which has each embedded newline preceded by a backslash. .TP q Immediately quit the \*(sd script without processing any more input, except that if auto-print is not disabled the current pattern space will be printed. .TP Q Immediately quit the \*(sd script without processing any more input. .TP .RI r\ filename Append text read from .IR filename . .TP .RI R\ filename Append a line read from .IR filename . .SS Commands which accept address ranges .TP { Begin a block of commands (end with a }). .TP .RI b\ label Branch to .IR label ; if .I label is omitted, branch to end of script. .TP .RI t\ label If a s/// has done a successful substitution since the last input line was read and since the last t or T command, then branch to .IR label ; if .I label is omitted, branch to end of script. .TP .RI T\ label If no s/// has done a successful substitution since the last input line was read and since the last t or T command, then branch to .IR label ; if .I label is omitted, branch to end of script. .TP c \e .TP .I text Replace the selected lines with .IR text , which has each embedded newline preceded by a backslash. .TP d Delete pattern space. Start next cycle. .TP D Delete up to the first embedded newline in the pattern space. Start next cycle, but skip reading from the input if there is still data in the pattern space. .TP h H Copy/append pattern space to hold space. .TP g G Copy/append hold space to pattern space. .TP x Exchange the contents of the hold and pattern spaces. .TP l List out the current line in a ``visually unambiguous'' form. .TP n N Read/append the next line of input into the pattern space. .TP p Print the current pattern space. .TP P Print up to the first embedded newline of the current pattern space. .TP .RI s/ regexp / replacement / Attempt to match .I regexp against the pattern space. If successful, replace that portion matched with .IR replacement . The .I replacement may contain the special character .B & to refer to that portion of the pattern space which matched, and the special escapes \e1 through \e9 to refer to the corresponding matching sub-expressions in the .IR regexp . .TP .RI w\ filename Write the current pattern space to .IR filename . .TP .RI W\ filename Write the first line of the current pattern space to .IR filename . .TP .RI y/ source / dest / Transliterate the characters in the pattern space which appear in .I source to the corresponding character in .IR dest . .SH Addresses \*(Sd commands can be given with no addresses, in which case the command will be executed for all input lines; with one address, in which case the command will only be executed for input lines which match that address; or with two addresses, in which case the command will be executed for all input lines which match the inclusive range of lines starting from the first address and continuing to the second address. Three things to note about address ranges: the syntax is .IR addr1 , addr2 (i.e., the addresses are separated by a comma); the line which .I addr1 matched will always be accepted, even if .I addr2 selects an earlier line; and if .I addr2 is a .IR regexp , it will not be tested against the line that .I addr1 matched. .PP After the address (or address-range), and before the command, a .B ! may be inserted, which specifies that the command shall only be executed if the address (or address-range) does .B not match. .PP The following address types are supported: .TP .I number Match only the specified line .IR number . .TP .IR first ~ step Match every .IR step 'th line starting with line .IR first . For example, ``sed -n 1~2p'' will print all the odd-numbered lines in the input stream, and the address 2~5 will match every fifth line, starting with the second. (This is an extension.) .TP $ Match the last line. .TP .RI / regexp / Match lines matching the regular expression .IR regexp . .TP .BI \fR\e\fPc regexp c Match lines matching the regular expression .IR regexp . The .B c may be any character. .PP GNU \*(sd also supports some special 2-address forms: .TP .RI 0, addr2 Start out in "matched first address" state, until .I addr2 is found. This is similar to .RI 1, addr2 , except that if .I addr2 matches the very first line of input the .RI 0, addr2 form will be at the end of its range, whereas the .RI 1, addr2 form will still be at the beginning of its range. .TP .IR addr1 ,+ N Will match .I addr1 and the .I N lines following .IR addr1 . .TP .IR addr1 ,~ N Will match .I addr1 and the lines following .I addr1 until the next line whose input line number is a multiple of .IR N . [REGULAR EXPRESSIONS] POSIX.2 BREs .I should be supported, but they aren't completely because of performance problems. The .B \en sequence in a regular expression matches the newline character, and similarly for .BR \ea , .BR \et , and other sequences. [SEE ALSO] .BR awk (1), .BR ed (1), .BR grep (1), .BR tr (1), .BR perlre (1), sed.info, any of various books on \*(sd, .na the \*(sd FAQ (http://sed.sf.net/grabbag/tutorials/sedfaq.txt), http://sed.sf.net/grabbag/. [BUGS] .PP E-mail bug reports to .BR bonzini@gnu.org . Be sure to include the word ``sed'' somewhere in the ``Subject:'' field. Also, please include the output of ``sed --version'' in the body of your report if at all possible. kbuild-3686/src/oldsed/doc/sed.texi0000664000175000017500000042040415053010105017162 0ustar locutuslocutus\input texinfo @c -*-texinfo-*- @c Do not edit this file!! It is automatically generated from sed-in.texi. @c @c -- Stuff that needs adding: ---------------------------------------------- @c (document the `;' command-separator) @c -------------------------------------------------------------------------- @c Check for consistency: regexps in @code, text that they match in @samp. @c @c Tips: @c @command for command @c @samp for command fragments: @samp{cat -s} @c @code for sed commands and flags @c Use ``quote'' not `quote' or "quote". @c @c %**start of header @setfilename sed.info @settitle sed, a stream editor @c %**end of header @c @smallbook @include version.texi @c Combine indices. @syncodeindex ky cp @syncodeindex pg cp @syncodeindex tp cp @defcodeindex op @syncodeindex op fn @include config.texi @copying This file documents version @value{VERSION} of @value{SSED}, a stream editor. Copyright @copyright{} 1998, 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This document is released under the terms of the @acronym{GNU} Free Documentation License as published by the Free Software Foundation; either version 1.1, or (at your option) any later version. You should have received a copy of the @acronym{GNU} Free Documentation License along with @value{SSED}; see the file @file{COPYING.DOC}. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02110-1301, USA. There are no Cover Texts and no Invariant Sections; this text, along with its equivalent in the printed manual, constitutes the Title Page. @end copying @setchapternewpage off @titlepage @title @command{sed}, a stream editor @subtitle version @value{VERSION}, @value{UPDATED} @author by Ken Pizzini, Paolo Bonzini @page @vskip 0pt plus 1filll Copyright @copyright{} 1998, 1999 Free Software Foundation, Inc. @insertcopying Published by the Free Software Foundation, @* 51 Franklin Street, Fifth Floor @* Boston, MA 02110-1301, USA @end titlepage @node Top @top @ifnottex @insertcopying @end ifnottex @menu * Introduction:: Introduction * Invoking sed:: Invocation * sed Programs:: @command{sed} programs * Examples:: Some sample scripts * Limitations:: Limitations and (non-)limitations of @value{SSED} * Other Resources:: Other resources for learning about @command{sed} * Reporting Bugs:: Reporting bugs * Extended regexps:: @command{egrep}-style regular expressions @ifset PERL * Perl regexps:: Perl-style regular expressions @end ifset * Concept Index:: A menu with all the topics in this manual. * Command and Option Index:: A menu with all @command{sed} commands and command-line options. @detailmenu --- The detailed node listing --- sed Programs: * Execution Cycle:: How @command{sed} works * Addresses:: Selecting lines with @command{sed} * Regular Expressions:: Overview of regular expression syntax * Common Commands:: Often used commands * The "s" Command:: @command{sed}'s Swiss Army Knife * Other Commands:: Less frequently used commands * Programming Commands:: Commands for @command{sed} gurus * Extended Commands:: Commands specific of @value{SSED} * Escapes:: Specifying special characters Examples: * Centering lines:: * Increment a number:: * Rename files to lower case:: * Print bash environment:: * Reverse chars of lines:: * tac:: Reverse lines of files * cat -n:: Numbering lines * cat -b:: Numbering non-blank lines * wc -c:: Counting chars * wc -w:: Counting words * wc -l:: Counting lines * head:: Printing the first lines * tail:: Printing the last lines * uniq:: Make duplicate lines unique * uniq -d:: Print duplicated lines of input * uniq -u:: Remove all duplicated lines * cat -s:: Squeezing blank lines @ifset PERL Perl regexps:: Perl-style regular expressions * Backslash:: Introduces special sequences * Circumflex/dollar sign/period:: Behave specially with regard to new lines * Square brackets:: Are a bit different in strange cases * Options setting:: Toggle modifiers in the middle of a regexp * Non-capturing subpatterns:: Are not counted when backreferencing * Repetition:: Allows for non-greedy matching * Backreferences:: Allows for more than 10 back references * Assertions:: Allows for complex look ahead matches * Non-backtracking subpatterns:: Often gives more performance * Conditional subpatterns:: Allows if/then/else branches * Recursive patterns:: For example to match parentheses * Comments:: Because things can get complex... @end ifset @end detailmenu @end menu @node Introduction @chapter Introduction @cindex Stream editor @command{sed} is a stream editor. A stream editor is used to perform basic text transformations on an input stream (a file or input from a pipeline). While in some ways similar to an editor which permits scripted edits (such as @command{ed}), @command{sed} works by making only one pass over the input(s), and is consequently more efficient. But it is @command{sed}'s ability to filter text in a pipeline which particularly distinguishes it from other types of editors. @node Invoking sed @chapter Invocation Normally @command{sed} is invoked like this: @example sed SCRIPT INPUTFILE... @end example The full format for invoking @command{sed} is: @example sed OPTIONS... [SCRIPT] [INPUTFILE...] @end example If you do not specify @var{INPUTFILE}, or if @var{INPUTFILE} is @file{-}, @command{sed} filters the contents of the standard input. The @var{script} is actually the first non-option parameter, which @command{sed} specially considers a script and not an input file if (and only if) none of the other @var{options} specifies a script to be executed, that is if neither of the @option{-e} and @option{-f} options is specified. @command{sed} may be invoked with the following command-line options: @table @code @item --version @opindex --version @cindex Version, printing Print out the version of @command{sed} that is being run and a copyright notice, then exit. @item --help @opindex --help @cindex Usage summary, printing Print a usage message briefly summarizing these command-line options and the bug-reporting address, then exit. @item -n @itemx --quiet @itemx --silent @opindex -n @opindex --quiet @opindex --silent @cindex Disabling autoprint, from command line By default, @command{sed} prints out the pattern space at the end of each cycle through the script. These options disable this automatic printing, and @command{sed} only produces output when explicitly told to via the @code{p} command. @item -i[@var{SUFFIX}] @itemx --in-place[=@var{SUFFIX}] @opindex -i @opindex --in-place @cindex In-place editing, activating @cindex @value{SSEDEXT}, in-place editing This option specifies that files are to be edited in-place. @value{SSED} does this by creating a temporary file and sending output to this file rather than to the standard output.@footnote{This applies to commands such as @code{=}, @code{a}, @code{c}, @code{i}, @code{l}, @code{p}. You can still write to the standard output by using the @code{w} @cindex @value{SSEDEXT}, @file{/dev/stdout} file or @code{W} commands together with the @file{/dev/stdout} special file}. This option implies @option{-s}. When the end of the file is reached, the temporary file is renamed to the output file's original name. The extension, if supplied, is used to modify the name of the old file before renaming the temporary file, thereby making a backup copy@footnote{Note that @value{SSED} creates the backup file whether or not any output is actually changed.}). @cindex In-place editing, Perl-style backup file names This rule is followed: if the extension doesn't contain a @code{*}, then it is appended to the end of the current filename as a suffix; if the extension does contain one or more @code{*} characters, then @emph{each} asterisk is replaced with the current filename. This allows you to add a prefix to the backup file, instead of (or in addition to) a suffix, or even to place backup copies of the original files into another directory (provided the directory already exists). If no extension is supplied, the original file is overwritten without making a backup. @item -l @var{N} @itemx --line-length=@var{N} @opindex -l @opindex --line-length @cindex Line length, setting Specify the default line-wrap length for the @code{l} command. A length of 0 (zero) means to never wrap long lines. If not specified, it is taken to be 70. @item --posix @cindex @value{SSEDEXT}, disabling @value{SSED} includes several extensions to @acronym{POSIX} sed. In order to simplify writing portable scripts, this option disables all the extensions that this manual documents, including additional commands. @cindex @code{POSIXLY_CORRECT} behavior, enabling Most of the extensions accept @command{sed} programs that are outside the syntax mandated by @acronym{POSIX}, but some of them (such as the behavior of the @command{N} command described in @pxref{Reporting Bugs}) actually violate the standard. If you want to disable only the latter kind of extension, you can set the @code{POSIXLY_CORRECT} variable to a non-empty value. @item -r @itemx --regexp-extended @opindex -r @opindex --regexp-extended @cindex Extended regular expressions, choosing @cindex @acronym{GNU} extensions, extended regular expressions Use extended regular expressions rather than basic regular expressions. Extended regexps are those that @command{egrep} accepts; they can be clearer because they usually have less backslashes, but are a @acronym{GNU} extension and hence scripts that use them are not portable. @xref{Extended regexps, , Extended regular expressions}. @ifset PERL @item -R @itemx --regexp-perl @opindex -R @opindex --regexp-perl @cindex Perl-style regular expressions, choosing @cindex @value{SSEDEXT}, Perl-style regular expressions Use Perl-style regular expressions rather than basic regular expressions. Perl-style regexps are extremely powerful but are a @value{SSED} extension and hence scripts that use it are not portable. @xref{Perl regexps, , Perl-style regular expressions}. @end ifset @item -s @itemx --separate @cindex Working on separate files By default, @command{sed} will consider the files specified on the command line as a single continuous long stream. This @value{SSED} extension allows the user to consider them as separate files: range addresses (such as @samp{/abc/,/def/}) are not allowed to span several files, line numbers are relative to the start of each file, @code{$} refers to the last line of each file, and files invoked from the @code{R} commands are rewound at the start of each file. @item -u @itemx --unbuffered @opindex -u @opindex --unbuffered @cindex Unbuffered I/O, choosing Buffer both input and output as minimally as practical. (This is particularly useful if the input is coming from the likes of @samp{tail -f}, and you wish to see the transformed output as soon as possible.) @item -e @var{script} @itemx --expression=@var{script} @opindex -e @opindex --expression @cindex Script, from command line Add the commands in @var{script} to the set of commands to be run while processing the input. @item -f @var{script-file} @itemx --file=@var{script-file} @opindex -f @opindex --file @cindex Script, from a file Add the commands contained in the file @var{script-file} to the set of commands to be run while processing the input. @end table If no @option{-e}, @option{-f}, @option{--expression}, or @option{--file} options are given on the command-line, then the first non-option argument on the command line is taken to be the @var{script} to be executed. @cindex Files to be processed as input If any command-line parameters remain after processing the above, these parameters are interpreted as the names of input files to be processed. @cindex Standard input, processing as input A file name of @samp{-} refers to the standard input stream. The standard input will be processed if no file names are specified. @node sed Programs @chapter @command{sed} Programs @cindex @command{sed} program structure @cindex Script structure A @command{sed} program consists of one or more @command{sed} commands, passed in by one or more of the @option{-e}, @option{-f}, @option{--expression}, and @option{--file} options, or the first non-option argument if zero of these options are used. This document will refer to ``the'' @command{sed} script; this is understood to mean the in-order catenation of all of the @var{script}s and @var{script-file}s passed in. Each @code{sed} command consists of an optional address or address range, followed by a one-character command name and any additional command-specific code. @menu * Execution Cycle:: How @command{sed} works * Addresses:: Selecting lines with @command{sed} * Regular Expressions:: Overview of regular expression syntax * Common Commands:: Often used commands * The "s" Command:: @command{sed}'s Swiss Army Knife * Other Commands:: Less frequently used commands * Programming Commands:: Commands for @command{sed} gurus * Extended Commands:: Commands specific of @value{SSED} * Escapes:: Specifying special characters @end menu @node Execution Cycle @section How @command{sed} Works @cindex Buffer spaces, pattern and hold @cindex Spaces, pattern and hold @cindex Pattern space, definition @cindex Hold space, definition @command{sed} maintains two data buffers: the active @emph{pattern} space, and the auxiliary @emph{hold} space. Both are initially empty. @command{sed} operates by performing the following cycle on each lines of input: first, @command{sed} reads one line from the input stream, removes any trailing newline, and places it in the pattern space. Then commands are executed; each command can have an address associated to it: addresses are a kind of condition code, and a command is only executed if the condition is verified before the command is to be executed. When the end of the script is reached, unless the @option{-n} option is in use, the contents of pattern space are printed out to the output stream, adding back the trailing newline if it was removed.@footnote{Actually, if @command{sed} prints a line without the terminating newline, it will nevertheless print the missing newline as soon as more text is sent to the same output stream, which gives the ``least expected surprise'' even though it does not make commands like @samp{sed -n p} exactly identical to @command{cat}.} Then the next cycle starts for the next input line. Unless special commands (like @samp{D}) are used, the pattern space is deleted between two cycles. The hold space, on the other hand, keeps its data between cycles (see commands @samp{h}, @samp{H}, @samp{x}, @samp{g}, @samp{G} to move data between both buffers). @node Addresses @section Selecting lines with @command{sed} @cindex Addresses, in @command{sed} scripts @cindex Line selection @cindex Selecting lines to process Addresses in a @command{sed} script can be in any of the following forms: @table @code @item @var{number} @cindex Address, numeric @cindex Line, selecting by number Specifying a line number will match only that line in the input. (Note that @command{sed} counts lines continuously across all input files unless @option{-i} or @option{-s} options are specified.) @item @var{first}~@var{step} @cindex @acronym{GNU} extensions, @samp{@var{n}~@var{m}} addresses This @acronym{GNU} extension matches every @var{step}th line starting with line @var{first}. In particular, lines will be selected when there exists a non-negative @var{n} such that the current line-number equals @var{first} + (@var{n} * @var{step}). Thus, to select the odd-numbered lines, one would use @code{1~2}; to pick every third line starting with the second, @samp{2~3} would be used; to pick every fifth line starting with the tenth, use @samp{10~5}; and @samp{50~0} is just an obscure way of saying @code{50}. @item $ @cindex Address, last line @cindex Last line, selecting @cindex Line, selecting last This address matches the last line of the last file of input, or the last line of each file when the @option{-i} or @option{-s} options are specified. @item /@var{regexp}/ @cindex Address, as a regular expression @cindex Line, selecting by regular expression match This will select any line which matches the regular expression @var{regexp}. If @var{regexp} itself includes any @code{/} characters, each must be escaped by a backslash (@code{\}). @cindex empty regular expression @cindex @value{SSEDEXT}, modifiers and the empty regular expression The empty regular expression @samp{//} repeats the last regular expression match (the same holds if the empty regular expression is passed to the @code{s} command). Note that modifiers to regular expressions are evaluated when the regular expression is compiled, thus it is invalid to specify them together with the empty regular expression. @item \%@var{regexp}% (The @code{%} may be replaced by any other single character.) @cindex Slash character, in regular expressions This also matches the regular expression @var{regexp}, but allows one to use a different delimiter than @code{/}. This is particularly useful if the @var{regexp} itself contains a lot of slashes, since it avoids the tedious escaping of every @code{/}. If @var{regexp} itself includes any delimiter characters, each must be escaped by a backslash (@code{\}). @item /@var{regexp}/I @itemx \%@var{regexp}%I @cindex @acronym{GNU} extensions, @code{I} modifier @ifset PERL @cindex Perl-style regular expressions, case-insensitive @end ifset The @code{I} modifier to regular-expression matching is a @acronym{GNU} extension which causes the @var{regexp} to be matched in a case-insensitive manner. @item /@var{regexp}/M @itemx \%@var{regexp}%M @ifset PERL @cindex @value{SSEDEXT}, @code{M} modifier @end ifset @cindex Perl-style regular expressions, multiline The @code{M} modifier to regular-expression matching is a @value{SSED} extension which causes @code{^} and @code{$} to match respectively (in addition to the normal behavior) the empty string after a newline, and the empty string before a newline. There are special character sequences @ifset PERL (@code{\A} and @code{\Z} in Perl mode, @code{\`} and @code{\'} in basic or extended regular expression modes) @end ifset @ifclear PERL (@code{\`} and @code{\'}) @end ifclear which always match the beginning or the end of the buffer. @code{M} stands for @cite{multi-line}. @ifset PERL @item /@var{regexp}/S @itemx \%@var{regexp}%S @cindex @value{SSEDEXT}, @code{S} modifier @cindex Perl-style regular expressions, single line The @code{S} modifier to regular-expression matching is only valid in Perl mode and specifies that the dot character (@code{.}) will match the newline character too. @code{S} stands for @cite{single-line}. @end ifset @ifset PERL @item /@var{regexp}/X @itemx \%@var{regexp}%X @cindex @value{SSEDEXT}, @code{X} modifier @cindex Perl-style regular expressions, extended The @code{X} modifier to regular-expression matching is also valid in Perl mode only. If it is used, whitespace in the pattern (other than in a character class) and characters between a @kbd{#} outside a character class and the next newline character are ignored. An escaping backslash can be used to include a whitespace or @kbd{#} character as part of the pattern. @end ifset @end table If no addresses are given, then all lines are matched; if one address is given, then only lines matching that address are matched. @cindex Range of lines @cindex Several lines, selecting An address range can be specified by specifying two addresses separated by a comma (@code{,}). An address range matches lines starting from where the first address matches, and continues until the second address matches (inclusively). If the second address is a @var{regexp}, then checking for the ending match will start with the line @emph{following} the line which matched the first address: a range will always span at least two lines (except of course if the input stream ends). If the second address is a @var{number} less than (or equal to) the line matching the first address, then only the one line is matched. @cindex Special addressing forms @cindex Range with start address of zero @cindex Zero, as range start address @cindex @var{addr1},+N @cindex @var{addr1},~N @cindex @acronym{GNU} extensions, special two-address forms @cindex @acronym{GNU} extensions, @code{0} address @cindex @acronym{GNU} extensions, 0,@var{addr2} addressing @cindex @acronym{GNU} extensions, @var{addr1},+@var{N} addressing @cindex @acronym{GNU} extensions, @var{addr1},~@var{N} addressing @value{SSED} also supports some special two-address forms; all these are @acronym{GNU} extensions: @table @code @item 0,/@var{regexp}/ A line number of @code{0} can be used in an address specification like @code{0,/@var{regexp}/} so that @command{sed} will try to match @var{regexp} in the first input line too. In other words, @code{0,/@var{regexp}/} is similar to @code{1,/@var{regexp}/}, except that if @var{addr2} matches the very first line of input the @code{0,/@var{regexp}/} form will consider it to end the range, whereas the @code{1,/@var{regexp}/} form will match the beginning of its range and hence make the range span up to the @emph{second} occurrence of the regular expression. Note that this is the only place where the @code{0} address makes sense; there is no 0-th line and commands which are given the @code{0} address in any other way will give an error. @item @var{addr1},+@var{N} Matches @var{addr1} and the @var{N} lines following @var{addr1}. @item @var{addr1},~@var{N} Matches @var{addr1} and the lines following @var{addr1} until the next line whose input line number is a multiple of @var{N}. @end table @cindex Excluding lines @cindex Selecting non-matching lines Appending the @code{!} character to the end of an address specification negates the sense of the match. That is, if the @code{!} character follows an address range, then only lines which do @emph{not} match the address range will be selected. This also works for singleton addresses, and, perhaps perversely, for the null address. @node Regular Expressions @section Overview of Regular Expression Syntax To know how to use @command{sed}, people should understand regular expressions (@dfn{regexp} for short). A regular expression is a pattern that is matched against a subject string from left to right. Most characters are @dfn{ordinary}: they stand for themselves in a pattern, and match the corresponding characters in the subject. As a trivial example, the pattern @example The quick brown fox @end example @noindent matches a portion of a subject string that is identical to itself. The power of regular expressions comes from the ability to include alternatives and repetitions in the pattern. These are encoded in the pattern by the use of @dfn{special characters}, which do not stand for themselves but instead are interpreted in some special way. Here is a brief description of regular expression syntax as used in @command{sed}. @table @code @item @var{char} A single ordinary character matches itself. @item * @cindex @acronym{GNU} extensions, to basic regular expressions Matches a sequence of zero or more instances of matches for the preceding regular expression, which must be an ordinary character, a special character preceded by @code{\}, a @code{.}, a grouped regexp (see below), or a bracket expression. As a @acronym{GNU} extension, a postfixed regular expression can also be followed by @code{*}; for example, @code{a**} is equivalent to @code{a*}. @acronym{POSIX} 1003.1-2001 says that @code{*} stands for itself when it appears at the start of a regular expression or subexpression, but many non@acronym{GNU} implementations do not support this and portable scripts should instead use @code{\*} in these contexts. @item \+ @cindex @acronym{GNU} extensions, to basic regular expressions As @code{*}, but matches one or more. It is a @acronym{GNU} extension. @item \? @cindex @acronym{GNU} extensions, to basic regular expressions As @code{*}, but only matches zero or one. It is a @acronym{GNU} extension. @item \@{@var{i}\@} As @code{*}, but matches exactly @var{i} sequences (@var{i} is a decimal integer; for portability, keep it between 0 and 255 inclusive). @item \@{@var{i},@var{j}\@} Matches between @var{i} and @var{j}, inclusive, sequences. @item \@{@var{i},\@} Matches more than or equal to @var{i} sequences. @item \(@var{regexp}\) Groups the inner @var{regexp} as a whole, this is used to: @itemize @bullet @item @cindex @acronym{GNU} extensions, to basic regular expressions Apply postfix operators, like @code{\(abcd\)*}: this will search for zero or more whole sequences of @samp{abcd}, while @code{abcd*} would search for @samp{abc} followed by zero or more occurrences of @samp{d}. Note that support for @code{\(abcd\)*} is required by @acronym{POSIX} 1003.1-2001, but many non-@acronym{GNU} implementations do not support it and hence it is not universally portable. @item Use back references (see below). @end itemize @item . Matches any character, including newline. @item ^ Matches the null string at beginning of line, i.e. what appears after the circumflex must appear at the beginning of line. @code{^#include} will match only lines where @samp{#include} is the first thing on line---if there are spaces before, for example, the match fails. @code{^} acts as a special character only at the beginning of the regular expression or subexpression (that is, after @code{\(} or @code{\|}). Portable scripts should avoid @code{^} at the beginning of a subexpression, though, as @acronym{POSIX} allows implementations that treat @code{^} as an ordinary character in that context. @item $ It is the same as @code{^}, but refers to end of line. @code{$} also acts as a special character only at the end of the regular expression or subexpression (that is, before @code{\)} or @code{\|}), and its use at the end of a subexpression is not portable. @item [@var{list}] @itemx [^@var{list}] Matches any single character in @var{list}: for example, @code{[aeiou]} matches all vowels. A list may include sequences like @code{@var{char1}-@var{char2}}, which matches any character between (inclusive) @var{char1} and @var{char2}. A leading @code{^} reverses the meaning of @var{list}, so that it matches any single character @emph{not} in @var{list}. To include @code{]} in the list, make it the first character (after the @code{^} if needed), to include @code{-} in the list, make it the first or last; to include @code{^} put it after the first character. @cindex @code{POSIXLY_CORRECT} behavior, bracket expressions The characters @code{$}, @code{*}, @code{.}, @code{[}, and @code{\} are normally not special within @var{list}. For example, @code{[\*]} matches either @samp{\} or @samp{*}, because the @code{\} is not special here. However, strings like @code{[.ch.]}, @code{[=a=]}, and @code{[:space:]} are special within @var{list} and represent collating symbols, equivalence classes, and character classes, respectively, and @code{[} is therefore special within @var{list} when it is followed by @code{.}, @code{=}, or @code{:}. Also, when not in @env{POSIXLY_CORRECT} mode, special escapes like @code{\n} and @code{\t} are recognized within @var{list}. @xref{Escapes}. @item @var{regexp1}\|@var{regexp2} @cindex @acronym{GNU} extensions, to basic regular expressions Matches either @var{regexp1} or @var{regexp2}. Use parentheses to use complex alternative regular expressions. The matching process tries each alternative in turn, from left to right, and the first one that succeeds is used. It is a @acronym{GNU} extension. @item @var{regexp1}@var{regexp2} Matches the concatenation of @var{regexp1} and @var{regexp2}. Concatenation binds more tightly than @code{\|}, @code{^}, and @code{$}, but less tightly than the other regular expression operators. @item \@var{digit} Matches the @var{digit}-th @code{\(@dots{}\)} parenthesized subexpression in the regular expression. This is called a @dfn{back reference}. Subexpressions are implicity numbered by counting occurrences of @code{\(} left-to-right. @item \n Matches the newline character. @item \@var{char} Matches @var{char}, where @var{char} is one of @code{$}, @code{*}, @code{.}, @code{[}, @code{\}, or @code{^}. Note that the only C-like backslash sequences that you can portably assume to be interpreted are @code{\n} and @code{\\}; in particular @code{\t} is not portable, and matches a @samp{t} under most implementations of @command{sed}, rather than a tab character. @end table @cindex Greedy regular expression matching Note that the regular expression matcher is greedy, i.e., matches are attempted from left to right and, if two or more matches are possible starting at the same character, it selects the longest. @noindent Examples: @table @samp @item abcdef Matches @samp{abcdef}. @item a*b Matches zero or more @samp{a}s followed by a single @samp{b}. For example, @samp{b} or @samp{aaaaab}. @item a\?b Matches @samp{b} or @samp{ab}. @item a\+b\+ Matches one or more @samp{a}s followed by one or more @samp{b}s: @samp{ab} is the shortest possible match, but other examples are @samp{aaaab} or @samp{abbbbb} or @samp{aaaaaabbbbbbb}. @item .* @itemx .\+ These two both match all the characters in a string; however, the first matches every string (including the empty string), while the second matches only strings containing at least one character. @item ^main.*(.*) his matches a string starting with @samp{main}, followed by an opening and closing parenthesis. The @samp{n}, @samp{(} and @samp{)} need not be adjacent. @item ^# This matches a string beginning with @samp{#}. @item \\$ This matches a string ending with a single backslash. The regexp contains two backslashes for escaping. @item \$ Instead, this matches a string consisting of a single dollar sign, because it is escaped. @item [a-zA-Z0-9] In the C locale, this matches any @acronym{ASCII} letters or digits. @item [^ @kbd{tab}]\+ (Here @kbd{tab} stands for a single tab character.) This matches a string of one or more characters, none of which is a space or a tab. Usually this means a word. @item ^\(.*\)\n\1$ This matches a string consisting of two equal substrings separated by a newline. @item .\@{9\@}A$ This matches nine characters followed by an @samp{A}. @item ^.\@{15\@}A This matches the start of a string that contains 16 characters, the last of which is an @samp{A}. @end table @node Common Commands @section Often-Used Commands If you use @command{sed} at all, you will quite likely want to know these commands. @table @code @item # [No addresses allowed.] @findex # (comments) @cindex Comments, in scripts The @code{#} character begins a comment; the comment continues until the next newline. @cindex Portability, comments If you are concerned about portability, be aware that some implementations of @command{sed} (which are not @sc{posix} conformant) may only support a single one-line comment, and then only when the very first character of the script is a @code{#}. @findex -n, forcing from within a script @cindex Caveat --- #n on first line Warning: if the first two characters of the @command{sed} script are @code{#n}, then the @option{-n} (no-autoprint) option is forced. If you want to put a comment in the first line of your script and that comment begins with the letter @samp{n} and you do not want this behavior, then be sure to either use a capital @samp{N}, or place at least one space before the @samp{n}. @item q [@var{exit-code}] This command only accepts a single address. @findex q (quit) command @cindex @value{SSEDEXT}, returning an exit code @cindex Quitting Exit @command{sed} without processing any more commands or input. Note that the current pattern space is printed if auto-print is not disabled with the @option{-n} options. The ability to return an exit code from the @command{sed} script is a @value{SSED} extension. @item d @findex d (delete) command @cindex Text, deleting Delete the pattern space; immediately start next cycle. @item p @findex p (print) command @cindex Text, printing Print out the pattern space (to the standard output). This command is usually only used in conjunction with the @option{-n} command-line option. @item n @findex n (next-line) command @cindex Next input line, replace pattern space with @cindex Read next input line If auto-print is not disabled, print the pattern space, then, regardless, replace the pattern space with the next line of input. If there is no more input then @command{sed} exits without processing any more commands. @item @{ @var{commands} @} @findex @{@} command grouping @cindex Grouping commands @cindex Command groups A group of commands may be enclosed between @code{@{} and @code{@}} characters. This is particularly useful when you want a group of commands to be triggered by a single address (or address-range) match. @end table @node The "s" Command @section The @code{s} Command The syntax of the @code{s} (as in substitute) command is @samp{s/@var{regexp}/@var{replacement}/@var{flags}}. The @code{/} characters may be uniformly replaced by any other single character within any given @code{s} command. The @code{/} character (or whatever other character is used in its stead) can appear in the @var{regexp} or @var{replacement} only if it is preceded by a @code{\} character. The @code{s} command is probably the most important in @command{sed} and has a lot of different options. Its basic concept is simple: the @code{s} command attempts to match the pattern space against the supplied @var{regexp}; if the match is successful, then that portion of the pattern space which was matched is replaced with @var{replacement}. @cindex Backreferences, in regular expressions @cindex Parenthesized substrings The @var{replacement} can contain @code{\@var{n}} (@var{n} being a number from 1 to 9, inclusive) references, which refer to the portion of the match which is contained between the @var{n}th @code{\(} and its matching @code{\)}. Also, the @var{replacement} can contain unescaped @code{&} characters which reference the whole matched portion of the pattern space. @cindex @value{SSEDEXT}, case modifiers in @code{s} commands Finally, as a @value{SSED} extension, you can include a special sequence made of a backslash and one of the letters @code{L}, @code{l}, @code{U}, @code{u}, or @code{E}. The meaning is as follows: @table @code @item \L Turn the replacement to lowercase until a @code{\U} or @code{\E} is found, @item \l Turn the next character to lowercase, @item \U Turn the replacement to uppercase until a @code{\L} or @code{\E} is found, @item \u Turn the next character to uppercase, @item \E Stop case conversion started by @code{\L} or @code{\U}. @end table To include a literal @code{\}, @code{&}, or newline in the final replacement, be sure to precede the desired @code{\}, @code{&}, or newline in the @var{replacement} with a @code{\}. @findex s command, option flags @cindex Substitution of text, options The @code{s} command can be followed by zero or more of the following @var{flags}: @table @code @item g @cindex Global substitution @cindex Replacing all text matching regexp in a line Apply the replacement to @emph{all} matches to the @var{regexp}, not just the first. @item @var{number} @cindex Replacing only @var{n}th match of regexp in a line Only replace the @var{number}th match of the @var{regexp}. @cindex @acronym{GNU} extensions, @code{g} and @var{number} modifier interaction in @code{s} command @cindex Mixing @code{g} and @var{number} modifiers in the @code{s} command Note: the @sc{posix} standard does not specify what should happen when you mix the @code{g} and @var{number} modifiers, and currently there is no widely agreed upon meaning across @command{sed} implementations. For @value{SSED}, the interaction is defined to be: ignore matches before the @var{number}th, and then match and replace all matches from the @var{number}th on. @item p @cindex Text, printing after substitution If the substitution was made, then print the new pattern space. Note: when both the @code{p} and @code{e} options are specified, the relative ordering of the two produces very different results. In general, @code{ep} (evaluate then print) is what you want, but operating the other way round can be useful for debugging. For this reason, the current version of @value{SSED} interprets specially the presence of @code{p} options both before and after @code{e}, printing the pattern space before and after evaluation, while in general flags for the @code{s} command show their effect just once. This behavior, although documented, might change in future versions. @item w @var{file-name} @cindex Text, writing to a file after substitution @cindex @value{SSEDEXT}, @file{/dev/stdout} file @cindex @value{SSEDEXT}, @file{/dev/stderr} file If the substitution was made, then write out the result to the named file. As a @value{SSED} extension, two special values of @var{file-name} are supported: @file{/dev/stderr}, which writes the result to the standard error, and @file{/dev/stdout}, which writes to the standard output.@footnote{This is equivalent to @code{p} unless the @option{-i} option is being used.} @item e @cindex Evaluate Bourne-shell commands, after substitution @cindex Subprocesses @cindex @value{SSEDEXT}, evaluating Bourne-shell commands @cindex @value{SSEDEXT}, subprocesses This command allows one to pipe input from a shell command into pattern space. If a substitution was made, the command that is found in pattern space is executed and pattern space is replaced with its output. A trailing newline is suppressed; results are undefined if the command to be executed contains a @sc{nul} character. This is a @value{SSED} extension. @item I @itemx i @cindex @acronym{GNU} extensions, @code{I} modifier @cindex Case-insensitive matching @ifset PERL @cindex Perl-style regular expressions, case-insensitive @end ifset The @code{I} modifier to regular-expression matching is a @acronym{GNU} extension which makes @command{sed} match @var{regexp} in a case-insensitive manner. @item M @itemx m @cindex @value{SSEDEXT}, @code{M} modifier @ifset PERL @cindex Perl-style regular expressions, multiline @end ifset The @code{M} modifier to regular-expression matching is a @value{SSED} extension which causes @code{^} and @code{$} to match respectively (in addition to the normal behavior) the empty string after a newline, and the empty string before a newline. There are special character sequences @ifset PERL (@code{\A} and @code{\Z} in Perl mode, @code{\`} and @code{\'} in basic or extended regular expression modes) @end ifset @ifclear PERL (@code{\`} and @code{\'}) @end ifclear which always match the beginning or the end of the buffer. @code{M} stands for @cite{multi-line}. @ifset PERL @item S @itemx s @cindex @value{SSEDEXT}, @code{S} modifier @cindex Perl-style regular expressions, single line The @code{S} modifier to regular-expression matching is only valid in Perl mode and specifies that the dot character (@code{.}) will match the newline character too. @code{S} stands for @cite{single-line}. @end ifset @ifset PERL @item X @itemx x @cindex @value{SSEDEXT}, @code{X} modifier @cindex Perl-style regular expressions, extended The @code{X} modifier to regular-expression matching is also valid in Perl mode only. If it is used, whitespace in the pattern (other than in a character class) and characters between a @kbd{#} outside a character class and the next newline character are ignored. An escaping backslash can be used to include a whitespace or @kbd{#} character as part of the pattern. @end ifset @end table @node Other Commands @section Less Frequently-Used Commands Though perhaps less frequently used than those in the previous section, some very small yet useful @command{sed} scripts can be built with these commands. @table @code @item y/@var{source-chars}/@var{dest-chars}/ (The @code{/} characters may be uniformly replaced by any other single character within any given @code{y} command.) @findex y (transliterate) command @cindex Transliteration Transliterate any characters in the pattern space which match any of the @var{source-chars} with the corresponding character in @var{dest-chars}. Instances of the @code{/} (or whatever other character is used in its stead), @code{\}, or newlines can appear in the @var{source-chars} or @var{dest-chars} lists, provide that each instance is escaped by a @code{\}. The @var{source-chars} and @var{dest-chars} lists @emph{must} contain the same number of characters (after de-escaping). @item a\ @itemx @var{text} @cindex @value{SSEDEXT}, two addresses supported by most commands As a @acronym{GNU} extension, this command accepts two addresses. @findex a (append text lines) command @cindex Appending text after a line @cindex Text, appending Queue the lines of text which follow this command (each but the last ending with a @code{\}, which are removed from the output) to be output at the end of the current cycle, or when the next input line is read. Escape sequences in @var{text} are processed, so you should use @code{\\} in @var{text} to print a single backslash. As a @acronym{GNU} extension, if between the @code{a} and the newline there is other than a whitespace-@code{\} sequence, then the text of this line, starting at the first non-whitespace character after the @code{a}, is taken as the first line of the @var{text} block. (This enables a simplification in scripting a one-line add.) This extension also works with the @code{i} and @code{c} commands. @item i\ @itemx @var{text} @cindex @value{SSEDEXT}, two addresses supported by most commands As a @acronym{GNU} extension, this command accepts two addresses. @findex i (insert text lines) command @cindex Inserting text before a line @cindex Text, insertion Immediately output the lines of text which follow this command (each but the last ending with a @code{\}, which are removed from the output). @item c\ @itemx @var{text} @findex c (change to text lines) command @cindex Replacing selected lines with other text Delete the lines matching the address or address-range, and output the lines of text which follow this command (each but the last ending with a @code{\}, which are removed from the output) in place of the last line (or in place of each line, if no addresses were specified). A new cycle is started after this command is done, since the pattern space will have been deleted. @item = @cindex @value{SSEDEXT}, two addresses supported by most commands As a @acronym{GNU} extension, this command accepts two addresses. @findex = (print line number) command @cindex Printing line number @cindex Line number, printing Print out the current input line number (with a trailing newline). @item l @var{n} @findex l (list unambiguously) command @cindex List pattern space @cindex Printing text unambiguously @cindex Line length, setting @cindex @value{SSEDEXT}, setting line length Print the pattern space in an unambiguous form: non-printable characters (and the @code{\} character) are printed in C-style escaped form; long lines are split, with a trailing @code{\} character to indicate the split; the end of each line is marked with a @code{$}. @var{n} specifies the desired line-wrap length; a length of 0 (zero) means to never wrap long lines. If omitted, the default as specified on the command line is used. The @var{n} parameter is a @value{SSED} extension. @item r @var{filename} @cindex @value{SSEDEXT}, two addresses supported by most commands As a @acronym{GNU} extension, this command accepts two addresses. @findex r (read file) command @cindex Read text from a file @cindex @value{SSEDEXT}, @file{/dev/stdin} file Queue the contents of @var{filename} to be read and inserted into the output stream at the end of the current cycle, or when the next input line is read. Note that if @var{filename} cannot be read, it is treated as if it were an empty file, without any error indication. As a @value{SSED} extension, the special value @file{/dev/stdin} is supported for the file name, which reads the contents of the standard input. @item w @var{filename} @findex w (write file) command @cindex Write to a file @cindex @value{SSEDEXT}, @file{/dev/stdout} file @cindex @value{SSEDEXT}, @file{/dev/stderr} file Write the pattern space to @var{filename}. As a @value{SSED} extension, two special values of @var{file-name} are supported: @file{/dev/stderr}, which writes the result to the standard error, and @file{/dev/stdout}, which writes to the standard output.@footnote{This is equivalent to @code{p} unless the @option{-i} option is being used.} The file will be created (or truncated) before the first input line is read; all @code{w} commands (including instances of @code{w} flag on successful @code{s} commands) which refer to the same @var{filename} are output without closing and reopening the file. @item D @findex D (delete first line) command @cindex Delete first line from pattern space Delete text in the pattern space up to the first newline. If any text is left, restart cycle with the resultant pattern space (without reading a new line of input), otherwise start a normal new cycle. @item N @findex N (append Next line) command @cindex Next input line, append to pattern space @cindex Append next input line to pattern space Add a newline to the pattern space, then append the next line of input to the pattern space. If there is no more input then @command{sed} exits without processing any more commands. @item P @findex P (print first line) command @cindex Print first line from pattern space Print out the portion of the pattern space up to the first newline. @item h @findex h (hold) command @cindex Copy pattern space into hold space @cindex Replace hold space with copy of pattern space @cindex Hold space, copying pattern space into Replace the contents of the hold space with the contents of the pattern space. @item H @findex H (append Hold) command @cindex Append pattern space to hold space @cindex Hold space, appending from pattern space Append a newline to the contents of the hold space, and then append the contents of the pattern space to that of the hold space. @item g @findex g (get) command @cindex Copy hold space into pattern space @cindex Replace pattern space with copy of hold space @cindex Hold space, copy into pattern space Replace the contents of the pattern space with the contents of the hold space. @item G @findex G (appending Get) command @cindex Append hold space to pattern space @cindex Hold space, appending to pattern space Append a newline to the contents of the pattern space, and then append the contents of the hold space to that of the pattern space. @item x @findex x (eXchange) command @cindex Exchange hold space with pattern space @cindex Hold space, exchange with pattern space Exchange the contents of the hold and pattern spaces. @end table @node Programming Commands @section Commands for @command{sed} gurus In most cases, use of these commands indicates that you are probably better off programming in something like @command{awk} or Perl. But occasionally one is committed to sticking with @command{sed}, and these commands can enable one to write quite convoluted scripts. @cindex Flow of control in scripts @table @code @item : @var{label} [No addresses allowed.] @findex : (label) command @cindex Labels, in scripts Specify the location of @var{label} for branch commands. In all other respects, a no-op. @item b @var{label} @findex b (branch) command @cindex Branch to a label, unconditionally @cindex Goto, in scripts Unconditionally branch to @var{label}. The @var{label} may be omitted, in which case the next cycle is started. @item t @var{label} @findex t (test and branch if successful) command @cindex Branch to a label, if @code{s///} succeeded @cindex Conditional branch Branch to @var{label} only if there has been a successful @code{s}ubstitution since the last input line was read or conditional branch was taken. The @var{label} may be omitted, in which case the next cycle is started. @end table @node Extended Commands @section Commands Specific to @value{SSED} These commands are specific to @value{SSED}, so you must use them with care and only when you are sure that hindering portability is not evil. They allow you to check for @value{SSED} extensions or to do tasks that are required quite often, yet are unsupported by standard @command{sed}s. @table @code @item e [@var{command}] @findex e (evaluate) command @cindex Evaluate Bourne-shell commands @cindex Subprocesses @cindex @value{SSEDEXT}, evaluating Bourne-shell commands @cindex @value{SSEDEXT}, subprocesses This command allows one to pipe input from a shell command into pattern space. Without parameters, the @code{e} command executes the command that is found in pattern space and replaces the pattern space with the output; a trailing newline is suppressed. If a parameter is specified, instead, the @code{e} command interprets it as a command and sends its output to the output stream (like @code{r} does). The command can run across multiple lines, all but the last ending with a back-slash. In both cases, the results are undefined if the command to be executed contains a @sc{nul} character. @item L @var{n} @findex L (fLow paragraphs) command @cindex Reformat pattern space @cindex Reformatting paragraphs @cindex @value{SSEDEXT}, reformatting paragraphs @cindex @value{SSEDEXT}, @code{L} command This @value{SSED} extension fills and joins lines in pattern space to produce output lines of (at most) @var{n} characters, like @code{fmt} does; if @var{n} is omitted, the default as specified on the command line is used. This command is considered a failed experiment and unless there is enough request (which seems unlikely) will be removed in future versions. @ignore Blank lines, spaces between words, and indentation are preserved in the output; successive input lines with different indentation are not joined; tabs are expanded to 8 columns. If the pattern space contains multiple lines, they are joined, but since the pattern space usually contains a single line, the behavior of a simple @code{L;d} script is the same as @samp{fmt -s} (i.e., it does not join short lines to form longer ones). @var{n} specifies the desired line-wrap length; if omitted, the default as specified on the command line is used. @end ignore @item Q [@var{exit-code}] This command only accepts a single address. @findex Q (silent Quit) command @cindex @value{SSEDEXT}, quitting silently @cindex @value{SSEDEXT}, returning an exit code @cindex Quitting This command is the same as @code{q}, but will not print the contents of pattern space. Like @code{q}, it provides the ability to return an exit code to the caller. This command can be useful because the only alternative ways to accomplish this apparently trivial function are to use the @option{-n} option (which can unnecessarily complicate your script) or resorting to the following snippet, which wastes time by reading the whole file without any visible effect: @example :eat $d @i{Quit silently on the last line} N @i{Read another line, silently} g @i{Overwrite pattern space each time to save memory} b eat @end example @item R @var{filename} @findex R (read line) command @cindex Read text from a file @cindex @value{SSEDEXT}, reading a file a line at a time @cindex @value{SSEDEXT}, @code{R} command @cindex @value{SSEDEXT}, @file{/dev/stdin} file Queue a line of @var{filename} to be read and inserted into the output stream at the end of the current cycle, or when the next input line is read. Note that if @var{filename} cannot be read, or if its end is reached, no line is appended, without any error indication. As with the @code{r} command, the special value @file{/dev/stdin} is supported for the file name, which reads a line from the standard input. @item T @var{label} @findex T (test and branch if failed) command @cindex @value{SSEDEXT}, branch if @code{s///} failed @cindex Branch to a label, if @code{s///} failed @cindex Conditional branch Branch to @var{label} only if there have been no successful @code{s}ubstitutions since the last input line was read or conditional branch was taken. The @var{label} may be omitted, in which case the next cycle is started. @item v @var{version} @findex v (version) command @cindex @value{SSEDEXT}, checking for their presence @cindex Requiring @value{SSED} This command does nothing, but makes @command{sed} fail if @value{SSED} extensions are not supported, simply because other versions of @command{sed} do not implement it. In addition, you can specify the version of @command{sed} that your script requires, such as @code{4.0.5}. The default is @code{4.0} because that is the first version that implemented this command. This command enables all @value{SSEDEXT} even if @env{POSIXLY_CORRECT} is set in the environment. @item W @var{filename} @findex W (write first line) command @cindex Write first line to a file @cindex @value{SSEDEXT}, writing first line to a file Write to the given filename the portion of the pattern space up to the first newline. Everything said under the @code{w} command about file handling holds here too. @end table @node Escapes @section @acronym{GNU} Extensions for Escapes in Regular Expressions @cindex @acronym{GNU} extensions, special escapes Until this chapter, we have only encountered escapes of the form @samp{\^}, which tell @command{sed} not to interpret the circumflex as a special character, but rather to take it literally. For example, @samp{\*} matches a single asterisk rather than zero or more backslashes. @cindex @code{POSIXLY_CORRECT} behavior, escapes This chapter introduces another kind of escape@footnote{All the escapes introduced here are @acronym{GNU} extensions, with the exception of @code{\n}. In basic regular expression mode, setting @code{POSIXLY_CORRECT} disables them inside bracket expressions.}---that is, escapes that are applied to a character or sequence of characters that ordinarily are taken literally, and that @command{sed} replaces with a special character. This provides a way of encoding non-printable characters in patterns in a visible manner. There is no restriction on the appearance of non-printing characters in a @command{sed} script but when a script is being prepared in the shell or by text editing, it is usually easier to use one of the following escape sequences than the binary character it represents: The list of these escapes is: @table @code @item \a Produces or matches a @sc{bel} character, that is an ``alert'' (@sc{ascii} 7). @item \f Produces or matches a form feed (@sc{ascii} 12). @item \n Produces or matches a newline (@sc{ascii} 10). @item \r Produces or matches a carriage return (@sc{ascii} 13). @item \t Produces or matches a horizontal tab (@sc{ascii} 9). @item \v Produces or matches a so called ``vertical tab'' (@sc{ascii} 11). @item \c@var{x} Produces or matches @kbd{@sc{Control}-@var{x}}, where @var{x} is any character. The precise effect of @samp{\c@var{x}} is as follows: if @var{x} is a lower case letter, it is converted to upper case. Then bit 6 of the character (hex 40) is inverted. Thus @samp{\cz} becomes hex 1A, but @samp{\c@{} becomes hex 3B, while @samp{\c;} becomes hex 7B. @item \d@var{xxx} Produces or matches a character whose decimal @sc{ascii} value is @var{xxx}. @item \o@var{xxx} @ifset PERL @item \@var{xxx} @end ifset Produces or matches a character whose octal @sc{ascii} value is @var{xxx}. @ifset PERL The syntax without the @code{o} is active in Perl mode, while the one with the @code{o} is active in the normal or extended @sc{posix} regular expression modes. @end ifset @item \x@var{xx} Produces or matches a character whose hexadecimal @sc{ascii} value is @var{xx}. @end table @samp{\b} (backspace) was omitted because of the conflict with the existing ``word boundary'' meaning. Other escapes match a particular character class and are valid only in regular expressions: @table @code @item \w Matches any ``word'' character. A ``word'' character is any letter or digit or the underscore character. @item \W Matches any ``non-word'' character. @item \b Matches a word boundary; that is it matches if the character to the left is a ``word'' character and the character to the right is a ``non-word'' character, or vice-versa. @item \B Matches everywhere but on a word boundary; that is it matches if the character to the left and the character to the right are either both ``word'' characters or both ``non-word'' characters. @item \` Matches only at the start of pattern space. This is different from @code{^} in multi-line mode. @item \' Matches only at the end of pattern space. This is different from @code{$} in multi-line mode. @ifset PERL @item \G Match only at the start of pattern space or, when doing a global substitution using the @code{s///g} command and option, at the end-of-match position of the prior match. For example, @samp{s/\Ga/Z/g} will change an initial run of @code{a}s to a run of @code{Z}s @end ifset @end table @node Examples @chapter Some Sample Scripts Here are some @command{sed} scripts to guide you in the art of mastering @command{sed}. @menu Some exotic examples: * Centering lines:: * Increment a number:: * Rename files to lower case:: * Print bash environment:: * Reverse chars of lines:: Emulating standard utilities: * tac:: Reverse lines of files * cat -n:: Numbering lines * cat -b:: Numbering non-blank lines * wc -c:: Counting chars * wc -w:: Counting words * wc -l:: Counting lines * head:: Printing the first lines * tail:: Printing the last lines * uniq:: Make duplicate lines unique * uniq -d:: Print duplicated lines of input * uniq -u:: Remove all duplicated lines * cat -s:: Squeezing blank lines @end menu @node Centering lines @section Centering Lines This script centers all lines of a file on a 80 columns width. To change that width, the number in @code{\@{@dots{}\@}} must be replaced, and the number of added spaces also must be changed. Note how the buffer commands are used to separate parts in the regular expressions to be matched---this is a common technique. @c start------------------------------------------- @example #!/usr/bin/sed -f @group # Put 80 spaces in the buffer 1 @{ x s/^$/ / s/^.*$/&&&&&&&&/ x @} @end group @group # del leading and trailing spaces y/@kbd{tab}/ / s/^ *// s/ *$// @end group @group # add a newline and 80 spaces to end of line G @end group @group # keep first 81 chars (80 + a newline) s/^\(.\@{81\@}\).*$/\1/ @end group @group # \2 matches half of the spaces, which are moved to the beginning s/^\(.*\)\n\(.*\)\2/\2\1/ @end group @end example @c end--------------------------------------------- @node Increment a number @section Increment a Number This script is one of a few that demonstrate how to do arithmetic in @command{sed}. This is indeed possible,@footnote{@command{sed} guru Greg Ubben wrote an implementation of the @command{dc} @sc{rpn} calculator! It is distributed together with sed.} but must be done manually. To increment one number you just add 1 to last digit, replacing it by the following digit. There is one exception: when the digit is a nine the previous digits must be also incremented until you don't have a nine. This solution by Bruno Haible is very clever and smart because it uses a single buffer; if you don't have this limitation, the algorithm used in @ref{cat -n, Numbering lines}, is faster. It works by replacing trailing nines with an underscore, then using multiple @code{s} commands to increment the last digit, and then again substituting underscores with zeros. @c start------------------------------------------- @example #!/usr/bin/sed -f /[^0-9]/ d @group # replace all leading 9s by _ (any other character except digits, could # be used) :d s/9\(_*\)$/_\1/ td @end group @group # incr last digit only. The first line adds a most-significant # digit of 1 if we have to add a digit. # # The @code{tn} commands are not necessary, but make the thing # faster @end group @group s/^\(_*\)$/1\1/; tn s/8\(_*\)$/9\1/; tn s/7\(_*\)$/8\1/; tn s/6\(_*\)$/7\1/; tn s/5\(_*\)$/6\1/; tn s/4\(_*\)$/5\1/; tn s/3\(_*\)$/4\1/; tn s/2\(_*\)$/3\1/; tn s/1\(_*\)$/2\1/; tn s/0\(_*\)$/1\1/; tn @end group @group :n y/_/0/ @end group @end example @c end--------------------------------------------- @node Rename files to lower case @section Rename Files to Lower Case This is a pretty strange use of @command{sed}. We transform text, and transform it to be shell commands, then just feed them to shell. Don't worry, even worse hacks are done when using @command{sed}; I have seen a script converting the output of @command{date} into a @command{bc} program! The main body of this is the @command{sed} script, which remaps the name from lower to upper (or vice-versa) and even checks out if the remapped name is the same as the original name. Note how the script is parameterized using shell variables and proper quoting. @c start------------------------------------------- @example @group #! /bin/sh # rename files to lower/upper case... # # usage: # move-to-lower * # move-to-upper * # or # move-to-lower -R . # move-to-upper -R . # @end group @group help() @{ cat << eof Usage: $0 [-n] [-r] [-h] files... @end group @group -n do nothing, only see what would be done -R recursive (use find) -h this message files files to remap to lower case @end group @group Examples: $0 -n * (see if everything is ok, then...) $0 * @end group $0 -R . @group eof @} @end group @group apply_cmd='sh' finder='echo "$@@" | tr " " "\n"' files_only= @end group @group while : do case "$1" in -n) apply_cmd='cat' ;; -R) finder='find "$@@" -type f';; -h) help ; exit 1 ;; *) break ;; esac shift done @end group @group if [ -z "$1" ]; then echo Usage: $0 [-h] [-n] [-r] files... exit 1 fi @end group @group LOWER='abcdefghijklmnopqrstuvwxyz' UPPER='ABCDEFGHIJKLMNOPQRSTUVWXYZ' @end group @group case `basename $0` in *upper*) TO=$UPPER; FROM=$LOWER ;; *) FROM=$UPPER; TO=$LOWER ;; esac @end group eval $finder | sed -n ' @group # remove all trailing slashes s/\/*$// @end group @group # add ./ if there is no path, only a filename /\//! s/^/.\// @end group @group # save path+filename h @end group @group # remove path s/.*\/// @end group @group # do conversion only on filename y/'$FROM'/'$TO'/ @end group @group # now line contains original path+file, while # hold space contains the new filename x @end group @group # add converted file name to line, which now contains # path/file-name\nconverted-file-name G @end group @group # check if converted file name is equal to original file name, # if it is, do not print nothing /^.*\/\(.*\)\n\1/b @end group @group # now, transform path/fromfile\n, into # mv path/fromfile path/tofile and print it s/^\(.*\/\)\(.*\)\n\(.*\)$/mv "\1\2" "\1\3"/p @end group ' | $apply_cmd @end example @c end--------------------------------------------- @node Print bash environment @section Print @command{bash} Environment This script strips the definition of the shell functions from the output of the @command{set} Bourne-shell command. @c start------------------------------------------- @example #!/bin/sh @group set | sed -n ' :x @end group @group @ifinfo # if no occurrence of "=()" print and load next line @end ifinfo @ifnotinfo # if no occurrence of @samp{=()} print and load next line @end ifnotinfo /=()/! @{ p; b; @} / () $/! @{ p; b; @} @end group @group # possible start of functions section # save the line in case this is a var like FOO="() " h @end group @group # if the next line has a brace, we quit because # nothing comes after functions n /^@{/ q @end group @group # print the old line x; p @end group @group # work on the new line now x; bx ' @end group @end example @c end--------------------------------------------- @node Reverse chars of lines @section Reverse Characters of Lines This script can be used to reverse the position of characters in lines. The technique moves two characters at a time, hence it is faster than more intuitive implementations. Note the @code{tx} command before the definition of the label. This is often needed to reset the flag that is tested by the @code{t} command. Imaginative readers will find uses for this script. An example is reversing the output of @command{banner}.@footnote{This requires another script to pad the output of banner; for example @example #! /bin/sh banner -w $1 $2 $3 $4 | sed -e :a -e '/^.\@{0,'$1'\@}$/ @{ s/$/ /; ba; @}' | ~/sedscripts/reverseline.sed @end example } @c start------------------------------------------- @example #!/usr/bin/sed -f /../! b @group # Reverse a line. Begin embedding the line between two newlines s/^.*$/\ &\ / @end group @group # Move first character at the end. The regexp matches until # there are zero or one characters between the markers tx :x s/\(\n.\)\(.*\)\(.\n\)/\3\2\1/ tx @end group @group # Remove the newline markers s/\n//g @end group @end example @c end--------------------------------------------- @node tac @section Reverse Lines of Files This one begins a series of totally useless (yet interesting) scripts emulating various Unix commands. This, in particular, is a @command{tac} workalike. Note that on implementations other than @acronym{GNU} @command{sed} @ifset PERL and @value{SSED} @end ifset this script might easily overflow internal buffers. @c start------------------------------------------- @example #!/usr/bin/sed -nf # reverse all lines of input, i.e. first line became last, ... @group # from the second line, the buffer (which contains all previous lines) # is *appended* to current line, so, the order will be reversed 1! G @end group @group # on the last line we're done -- print everything $ p @end group @group # store everything on the buffer again h @end group @end example @c end--------------------------------------------- @node cat -n @section Numbering Lines This script replaces @samp{cat -n}; in fact it formats its output exactly like @acronym{GNU} @command{cat} does. Of course this is completely useless and for two reasons: first, because somebody else did it in C, second, because the following Bourne-shell script could be used for the same purpose and would be much faster: @c start------------------------------------------- @example @group #! /bin/sh sed -e "=" $@@ | sed -e ' s/^/ / N s/^ *\(......\)\n/\1 / ' @end group @end example @c end--------------------------------------------- It uses @command{sed} to print the line number, then groups lines two by two using @code{N}. Of course, this script does not teach as much as the one presented below. The algorithm used for incrementing uses both buffers, so the line is printed as soon as possible and then discarded. The number is split so that changing digits go in a buffer and unchanged ones go in the other; the changed digits are modified in a single step (using a @code{y} command). The line number for the next line is then composed and stored in the hold space, to be used in the next iteration. @c start------------------------------------------- @example #!/usr/bin/sed -nf @group # Prime the pump on the first line x /^$/ s/^.*$/1/ @end group @group # Add the correct line number before the pattern G h @end group @group # Format it and print it s/^/ / s/^ *\(......\)\n/\1 /p @end group @group # Get the line number from hold space; add a zero # if we're going to add a digit on the next line g s/\n.*$// /^9*$/ s/^/0/ @end group @group # separate changing/unchanged digits with an x s/.9*$/x&/ @end group @group # keep changing digits in hold space h s/^.*x// y/0123456789/1234567890/ x @end group @group # keep unchanged digits in pattern space s/x.*$// @end group @group # compose the new number, remove the newline implicitly added by G G s/\n// h @end group @end example @c end--------------------------------------------- @node cat -b @section Numbering Non-blank Lines Emulating @samp{cat -b} is almost the same as @samp{cat -n}---we only have to select which lines are to be numbered and which are not. The part that is common to this script and the previous one is not commented to show how important it is to comment @command{sed} scripts properly... @c start------------------------------------------- @example #!/usr/bin/sed -nf @group /^$/ @{ p b @} @end group @group # Same as cat -n from now x /^$/ s/^.*$/1/ G h s/^/ / s/^ *\(......\)\n/\1 /p x s/\n.*$// /^9*$/ s/^/0/ s/.9*$/x&/ h s/^.*x// y/0123456789/1234567890/ x s/x.*$// G s/\n// h @end group @end example @c end--------------------------------------------- @node wc -c @section Counting Characters This script shows another way to do arithmetic with @command{sed}. In this case we have to add possibly large numbers, so implementing this by successive increments would not be feasible (and possibly even more complicated to contrive than this script). The approach is to map numbers to letters, kind of an abacus implemented with @command{sed}. @samp{a}s are units, @samp{b}s are tens and so on: we simply add the number of characters on the current line as units, and then propagate the carry to tens, hundreds, and so on. As usual, running totals are kept in hold space. On the last line, we convert the abacus form back to decimal. For the sake of variety, this is done with a loop rather than with some 80 @code{s} commands@footnote{Some implementations have a limit of 199 commands per script}: first we convert units, removing @samp{a}s from the number; then we rotate letters so that tens become @samp{a}s, and so on until no more letters remain. @c start------------------------------------------- @example #!/usr/bin/sed -nf @group # Add n+1 a's to hold space (+1 is for the newline) s/./a/g H x s/\n/a/ @end group @group # Do the carry. The t's and b's are not necessary, # but they do speed up the thing t a : a; s/aaaaaaaaaa/b/g; t b; b done : b; s/bbbbbbbbbb/c/g; t c; b done : c; s/cccccccccc/d/g; t d; b done : d; s/dddddddddd/e/g; t e; b done : e; s/eeeeeeeeee/f/g; t f; b done : f; s/ffffffffff/g/g; t g; b done : g; s/gggggggggg/h/g; t h; b done : h; s/hhhhhhhhhh//g @end group @group : done $! @{ h b @} @end group # On the last line, convert back to decimal @group : loop /a/! s/[b-h]*/&0/ s/aaaaaaaaa/9/ s/aaaaaaaa/8/ s/aaaaaaa/7/ s/aaaaaa/6/ s/aaaaa/5/ s/aaaa/4/ s/aaa/3/ s/aa/2/ s/a/1/ @end group @group : next y/bcdefgh/abcdefg/ /[a-h]/ b loop p @end group @end example @c end--------------------------------------------- @node wc -w @section Counting Words This script is almost the same as the previous one, once each of the words on the line is converted to a single @samp{a} (in the previous script each letter was changed to an @samp{a}). It is interesting that real @command{wc} programs have optimized loops for @samp{wc -c}, so they are much slower at counting words rather than characters. This script's bottleneck, instead, is arithmetic, and hence the word-counting one is faster (it has to manage smaller numbers). Again, the common parts are not commented to show the importance of commenting @command{sed} scripts. @c start------------------------------------------- @example #!/usr/bin/sed -nf @group # Convert words to a's s/[ @kbd{tab}][ @kbd{tab}]*/ /g s/^/ / s/ [^ ][^ ]*/a /g s/ //g @end group @group # Append them to hold space H x s/\n// @end group @group # From here on it is the same as in wc -c. /aaaaaaaaaa/! bx; s/aaaaaaaaaa/b/g /bbbbbbbbbb/! bx; s/bbbbbbbbbb/c/g /cccccccccc/! bx; s/cccccccccc/d/g /dddddddddd/! bx; s/dddddddddd/e/g /eeeeeeeeee/! bx; s/eeeeeeeeee/f/g /ffffffffff/! bx; s/ffffffffff/g/g /gggggggggg/! bx; s/gggggggggg/h/g s/hhhhhhhhhh//g :x $! @{ h; b; @} :y /a/! s/[b-h]*/&0/ s/aaaaaaaaa/9/ s/aaaaaaaa/8/ s/aaaaaaa/7/ s/aaaaaa/6/ s/aaaaa/5/ s/aaaa/4/ s/aaa/3/ s/aa/2/ s/a/1/ y/bcdefgh/abcdefg/ /[a-h]/ by p @end group @end example @c end--------------------------------------------- @node wc -l @section Counting Lines No strange things are done now, because @command{sed} gives us @samp{wc -l} functionality for free!!! Look: @c start------------------------------------------- @example @group #!/usr/bin/sed -nf $= @end group @end example @c end--------------------------------------------- @node head @section Printing the First Lines This script is probably the simplest useful @command{sed} script. It displays the first 10 lines of input; the number of displayed lines is right before the @code{q} command. @c start------------------------------------------- @example @group #!/usr/bin/sed -f 10q @end group @end example @c end--------------------------------------------- @node tail @section Printing the Last Lines Printing the last @var{n} lines rather than the first is more complex but indeed possible. @var{n} is encoded in the second line, before the bang character. This script is similar to the @command{tac} script in that it keeps the final output in the hold space and prints it at the end: @c start------------------------------------------- @example #!/usr/bin/sed -nf @group 1! @{; H; g; @} 1,10 !s/[^\n]*\n// $p h @end group @end example @c end--------------------------------------------- Mainly, the scripts keeps a window of 10 lines and slides it by adding a line and deleting the oldest (the substitution command on the second line works like a @code{D} command but does not restart the loop). The ``sliding window'' technique is a very powerful way to write efficient and complex @command{sed} scripts, because commands like @code{P} would require a lot of work if implemented manually. To introduce the technique, which is fully demonstrated in the rest of this chapter and is based on the @code{N}, @code{P} and @code{D} commands, here is an implementation of @command{tail} using a simple ``sliding window.'' This looks complicated but in fact the working is the same as the last script: after we have kicked in the appropriate number of lines, however, we stop using the hold space to keep inter-line state, and instead use @code{N} and @code{D} to slide pattern space by one line: @c start------------------------------------------- @example #!/usr/bin/sed -f @group 1h 2,10 @{; H; g; @} $q 1,9d N D @end group @end example @c end--------------------------------------------- Note how the first, second and fourth line are inactive after the first ten lines of input. After that, all the script does is: exiting on the last line of input, appending the next input line to pattern space, and removing the first line. @node uniq @section Make Duplicate Lines Unique This is an example of the art of using the @code{N}, @code{P} and @code{D} commands, probably the most difficult to master. @c start------------------------------------------- @example @group #!/usr/bin/sed -f h @end group @group :b # On the last line, print and exit $b N /^\(.*\)\n\1$/ @{ # The two lines are identical. Undo the effect of # the n command. g bb @} @end group @group # If the @code{N} command had added the last line, print and exit $b @end group @group # The lines are different; print the first and go # back working on the second. P D @end group @end example @c end--------------------------------------------- As you can see, we mantain a 2-line window using @code{P} and @code{D}. This technique is often used in advanced @command{sed} scripts. @node uniq -d @section Print Duplicated Lines of Input This script prints only duplicated lines, like @samp{uniq -d}. @c start------------------------------------------- @example #!/usr/bin/sed -nf @group $b N /^\(.*\)\n\1$/ @{ # Print the first of the duplicated lines s/.*\n// p @end group @group # Loop until we get a different line :b $b N /^\(.*\)\n\1$/ @{ s/.*\n// bb @} @} @end group @group # The last line cannot be followed by duplicates $b @end group @group # Found a different one. Leave it alone in the pattern space # and go back to the top, hunting its duplicates D @end group @end example @c end--------------------------------------------- @node uniq -u @section Remove All Duplicated Lines This script prints only unique lines, like @samp{uniq -u}. @c start------------------------------------------- @example #!/usr/bin/sed -f @group # Search for a duplicate line --- until that, print what you find. $b N /^\(.*\)\n\1$/ ! @{ P D @} @end group @group :c # Got two equal lines in pattern space. At the # end of the file we simply exit $d @end group @group # Else, we keep reading lines with @code{N} until we # find a different one s/.*\n// N /^\(.*\)\n\1$/ @{ bc @} @end group @group # Remove the last instance of the duplicate line # and go back to the top D @end group @end example @c end--------------------------------------------- @node cat -s @section Squeezing Blank Lines As a final example, here are three scripts, of increasing complexity and speed, that implement the same function as @samp{cat -s}, that is squeezing blank lines. The first leaves a blank line at the beginning and end if there are some already. @c start------------------------------------------- @example #!/usr/bin/sed -f @group # on empty lines, join with next # Note there is a star in the regexp :x /^\n*$/ @{ N bx @} @end group @group # now, squeeze all '\n', this can be also done by: # s/^\(\n\)*/\1/ s/\n*/\ / @end group @end example @c end--------------------------------------------- This one is a bit more complex and removes all empty lines at the beginning. It does leave a single blank line at end if one was there. @c start------------------------------------------- @example #!/usr/bin/sed -f @group # delete all leading empty lines 1,/^./@{ /./!d @} @end group @group # on an empty line we remove it and all the following # empty lines, but one :x /./!@{ N s/^\n$// tx @} @end group @end example @c end--------------------------------------------- This removes leading and trailing blank lines. It is also the fastest. Note that loops are completely done with @code{n} and @code{b}, without relying on @command{sed} to restart the the script automatically at the end of a line. @c start------------------------------------------- @example #!/usr/bin/sed -nf @group # delete all (leading) blanks /./!d @end group @group # get here: so there is a non empty :x # print it p # get next n # got chars? print it again, etc... /./bx @end group @group # no, don't have chars: got an empty line :z # get next, if last line we finish here so no trailing # empty lines are written n # also empty? then ignore it, and get next... this will # remove ALL empty lines /./!bz @end group @group # all empty lines were deleted/ignored, but we have a non empty. As # what we want to do is to squeeze, insert a blank line artificially i\ @end group bx @end example @c end--------------------------------------------- @node Limitations @chapter @value{SSED}'s Limitations and Non-limitations @cindex @acronym{GNU} extensions, unlimited line length @cindex Portability, line length limitations For those who want to write portable @command{sed} scripts, be aware that some implementations have been known to limit line lengths (for the pattern and hold spaces) to be no more than 4000 bytes. The @sc{posix} standard specifies that conforming @command{sed} implementations shall support at least 8192 byte line lengths. @value{SSED} has no built-in limit on line length; as long as it can @code{malloc()} more (virtual) memory, you can feed or construct lines as long as you like. However, recursion is used to handle subpatterns and indefinite repetition. This means that the available stack space may limit the size of the buffer that can be processed by certain patterns. @ifset PERL There are some size limitations in the regular expression matcher but it is hoped that they will never in practice be relevant. The maximum length of a compiled pattern is 65539 (sic) bytes. All values in repeating quantifiers must be less than 65536. The maximum nesting depth of all parenthesized subpatterns, including capturing and non-capturing subpatterns@footnote{The distinction is meaningful when referring to Perl-style regular expressions.}, assertions, and other types of subpattern, is 200. Also, @value{SSED} recognizes the @sc{posix} syntax @code{[.@var{ch}.]} and @code{[=@var{ch}=]} where @var{ch} is a ``collating element'', but these are not supported, and an error is given if they are encountered. Here are a few distinctions between the real Perl-style regular expressions and those that @option{-R} recognizes. @enumerate @item Lookahead assertions do not allow repeat quantifiers after them Perl permits them, but they do not mean what you might think. For example, @samp{(?!a)@{3@}} does not assert that the next three characters are not @samp{a}. It just asserts three times that the next character is not @samp{a} --- a waste of time and nothing else. @item Capturing subpatterns that occur inside negative lookahead head assertions are counted, but their entries are counted as empty in the second half of an @code{s} command. Perl sets its numerical variables from any such patterns that are matched before the assertion fails to match something (thereby succeeding), but only if the negative lookahead assertion contains just one branch. @item The following Perl escape sequences are not supported: @samp{\l}, @samp{\u}, @samp{\L}, @samp{\U}, @samp{\E}, @samp{\Q}. In fact these are implemented by Perl's general string-handling and are not part of its pattern matching engine. @item The Perl @samp{\G} assertion is not supported as it is not relevant to single pattern matches. @item Fairly obviously, @value{SSED} does not support the @samp{(?@{code@})} and @samp{(?p@{code@})} constructions. However, there is some experimental support for recursive patterns using the non-Perl item @samp{(?R)}. @item There are at the time of writing some oddities in Perl 5.005_02 concerned with the settings of captured strings when part of a pattern is repeated. For example, matching @samp{aba} against the pattern @samp{/^(a(b)?)+$/} sets @samp{$2}@footnote{@samp{$2} would be @samp{\2} in @value{SSED}.} to the value @samp{b}, but matching @samp{aabbaa} against @samp{/^(aa(bb)?)+$/} leaves @samp{$2} unset. However, if the pattern is changed to @samp{/^(aa(b(b))?)+$/} then @samp{$2} (and @samp{$3}) are set. In Perl 5.004 @samp{$2} is set in both cases, and that is also true of @value{SSED}. @item Another as yet unresolved discrepancy is that in Perl 5.005_02 the pattern @samp{/^(a)?(?(1)a|b)+$/} matches the string @samp{a}, whereas in @value{SSED} it does not. However, in both Perl and @value{SSED} @samp{/^(a)?a/} matched against @samp{a} leaves $1 unset. @end enumerate @end ifset @node Other Resources @chapter Other Resources for Learning About @command{sed} @cindex Additional reading about @command{sed} In addition to several books that have been written about @command{sed} (either specifically or as chapters in books which discuss shell programming), one can find out more about @command{sed} (including suggestions of a few books) from the FAQ for the @code{sed-users} mailing list, available from any of: @display @uref{http://www.student.northpark.edu/pemente/sed/sedfaq.html} @uref{http://sed.sf.net/grabbag/tutorials/sedfaq.html} @end display Also of interest are @uref{http://www.student.northpark.edu/pemente/sed/index.htm} and @uref{http://sed.sf.net/grabbag}, which include @command{sed} tutorials and other @command{sed}-related goodies. The @code{sed-users} mailing list itself maintained by Sven Guckes. To subscribe, visit @uref{http://groups.yahoo.com} and search for the @code{sed-users} mailing list. @node Reporting Bugs @chapter Reporting Bugs @cindex Bugs, reporting Email bug reports to @email{bonzini@@gnu.org}. Be sure to include the word ``sed'' somewhere in the @code{Subject:} field. Also, please include the output of @samp{sed --version} in the body of your report if at all possible. Please do not send a bug report like this: @example @i{while building frobme-1.3.4} $ configure @error{} sed: file sedscr line 1: Unknown option to 's' @end example If @value{SSED} doesn't configure your favorite package, take a few extra minutes to identify the specific problem and make a stand-alone test case. Unlike other programs such as C compilers, making such test cases for @command{sed} is quite simple. A stand-alone test case includes all the data necessary to perform the test, and the specific invocation of @command{sed} that causes the problem. The smaller a stand-alone test case is, the better. A test case should not involve something as far removed from @command{sed} as ``try to configure frobme-1.3.4''. Yes, that is in principle enough information to look for the bug, but that is not a very practical prospect. Here are a few commonly reported bugs that are not bugs. @table @asis @item @code{N} command on the last line @cindex Portability, @code{N} command on the last line @cindex Non-bugs, @code{N} command on the last line Most versions of @command{sed} exit without printing anything when the @command{N} command is issued on the last line of a file. @value{SSED} prints pattern space before exiting unless of course the @command{-n} command switch has been specified. This choice is by design. For example, the behavior of @example sed N foo bar @end example @noindent would depend on whether foo has an even or an odd number of lines@footnote{which is the actual ``bug'' that prompted the change in behavior}. Or, when writing a script to read the next few lines following a pattern match, traditional implementations of @code{sed} would force you to write something like @example /foo/@{ $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N @} @end example @noindent instead of just @example /foo/@{ N;N;N;N;N;N;N;N;N; @} @end example @cindex @code{POSIXLY_CORRECT} behavior, @code{N} command In any case, the simplest workaround is to use @code{$d;N} in scripts that rely on the traditional behavior, or to set the @code{POSIXLY_CORRECT} variable to a non-empty value. @item Regex syntax clashes (problems with backslashes) @cindex @acronym{GNU} extensions, to basic regular expressions @cindex Non-bugs, regex syntax clashes @command{sed} uses the @sc{posix} basic regular expression syntax. According to the standard, the meaning of some escape sequences is undefined in this syntax; notable in the case of @command{sed} are @code{\|}, @code{\+}, @code{\?}, @code{\`}, @code{\'}, @code{\<}, @code{\>}, @code{\b}, @code{\B}, @code{\w}, and @code{\W}. As in all @acronym{GNU} programs that use @sc{posix} basic regular expressions, @command{sed} interprets these escape sequences as special characters. So, @code{x\+} matches one or more occurrences of @samp{x}. @code{abc\|def} matches either @samp{abc} or @samp{def}. This syntax may cause problems when running scripts written for other @command{sed}s. Some @command{sed} programs have been written with the assumption that @code{\|} and @code{\+} match the literal characters @code{|} and @code{+}. Such scripts must be modified by removing the spurious backslashes if they are to be used with modern implementations of @command{sed}, like @ifset PERL @value{SSED} or @end ifset @acronym{GNU} @command{sed}. On the other hand, some scripts use s|abc\|def||g to remove occurrences of @emph{either} @code{abc} or @code{def}. While this worked until @command{sed} 4.0.x, newer versions interpret this as removing the string @code{abc|def}. This is again undefined behavior according to @acronym{POSIX}, and this interpretation is arguably more robust: older @command{sed}s, for example, required that the regex matcher parsed @code{\/} as @code{/} in the common case of escaping a slash, which is again undefined behavior; the new behavior avoids this, and this is good because the regex matcher is only partially under our control. @cindex @acronym{GNU} extensions, special escapes In addition, this version of @command{sed} supports several escape characters (some of which are multi-character) to insert non-printable characters in scripts (@code{\a}, @code{\c}, @code{\d}, @code{\o}, @code{\r}, @code{\t}, @code{\v}, @code{\x}). These can cause similar problems with scripts written for other @command{sed}s. @item @option{-i} clobbers read-only files @cindex In-place editing @cindex @value{SSEDEXT}, in-place editing @cindex Non-bugs, in-place editing In short, @samp{sed -i} will let you delete the contents of a read-only file, and in general the @option{-i} option (@pxref{Invoking sed, , Invocation}) lets you clobber protected files. This is not a bug, but rather a consequence of how the Unix filesystem works. The permissions on a file say what can happen to the data in that file, while the permissions on a directory say what can happen to the list of files in that directory. @samp{sed -i} will not ever open for writing a file that is already on disk. Rather, it will work on a temporary file that is finally renamed to the original name: if you rename or delete files, you're actually modifying the contents of the directory, so the operation depends on the permissions of the directory, not of the file. For this same reason, @command{sed} does not let you use @option{-i} on a writeable file in a read-only directory (but unbelievably nobody reports that as a bug@dots{}). @item @code{0a} does not work (gives an error) There is no line 0. 0 is a special address that is only used to treat addresses like @code{0,/@var{RE}/} as active when the script starts: if you write @code{1,/abc/d} and the first line includes the word @samp{abc}, then that match would be ignored because address ranges must span at least two lines (barring the end of the file); but what you probably wanted is to delete every line up to the first one including @samp{abc}, and this is obtained with @code{0,/abc/d}. @ifclear PERL @item @code{[a-z]} is case insensitive You are encountering problems with locales. POSIX mandates that @code{[a-z]} uses the current locale's collation order -- in C parlance, that means using @code{strcoll(3)} instead of @code{strcmp(3)}. Some locales have a case-insensitive collation order, others don't: one of those that have problems is Estonian. Another problem is that @code{[a-z]} tries to use collation symbols. This only happens if you are on the @acronym{GNU} system, using @acronym{GNU} libc's regular expression matcher instead of compiling the one supplied with @acronym{GNU} sed. In a Danish locale, for example, the regular expression @code{^[a-z]$} matches the string @samp{aa}, because this is a single collating symbol that comes after @samp{a} and before @samp{b}; @samp{ll} behaves similarly in Spanish locales, or @samp{ij} in Dutch locales. To work around these problems, which may cause bugs in shell scripts, set the @env{LC_COLLATE} and @env{LC_CTYPE} environment variables to @samp{C}. @end ifclear @end table @node Extended regexps @appendix Extended regular expressions @cindex Extended regular expressions, syntax The only difference between basic and extended regular expressions is in the behavior of a few characters: @samp{?}, @samp{+}, parentheses, and braces (@samp{@{@}}). While basic regular expressions require these to be escaped if you want them to behave as special characters, when using extended regular expressions you must escape them if you want them @emph{to match a literal character}. @noindent Examples: @table @code @item abc? becomes @samp{abc\?} when using extended regular expressions. It matches the literal string @samp{abc?}. @item c\+ becomes @samp{c+} when using extended regular expressions. It matches one or more @samp{c}s. @item a\@{3,\@} becomes @samp{a@{3,@}} when using extended regular expressions. It matches three or more @samp{a}s. @item \(abc\)\@{2,3\@} becomes @samp{(abc)@{2,3@}} when using extended regular expressions. It matches either @samp{abcabc} or @samp{abcabcabc}. @item \(abc*\)\1 becomes @samp{(abc*)\1} when using extended regular expressions. Backreferences must still be escaped when using extended regular expressions. @end table @ifset PERL @node Perl regexps @appendix Perl-style regular expressions @cindex Perl-style regular expressions, syntax @emph{This part is taken from the @file{pcre.txt} file distributed together with the free @sc{pcre} regular expression matcher; it was written by Philip Hazel.} Perl introduced several extensions to regular expressions, some of them incompatible with the syntax of regular expressions accepted by Emacs and other @acronym{GNU} tools (whose matcher was based on the Emacs matcher). @value{SSED} implements both kinds of extensions. @iftex Summarizing, we have: @itemize @bullet @item A backslash can introduce several special sequences @item The circumflex, dollar sign, and period characters behave specially with regard to new lines @item Strange uses of square brackets are parsed differently @item You can toggle modifiers in the middle of a regular expression @item You can specify that a subpattern does not count when numbering backreferences @item @cindex Greedy regular expression matching You can specify greedy or non-greedy matching @item You can have more than ten back references @item You can do complex look aheads and look behinds (in the spirit of @code{\b}, but with subpatterns). @item You can often improve performance by avoiding that @command{sed} wastes time with backtracking @item You can have if/then/else branches @item You can do recursive matches, for example to look for unbalanced parentheses @item You can have comments and non-significant whitespace, because things can get complex... @end itemize Most of these extensions are introduced by the special @code{(?} sequence, which gives special meanings to parenthesized groups. @end iftex @menu Other extensions can be roughly subdivided in two categories On one hand Perl introduces several more escaped sequences (that is, sequences introduced by a backslash). On the other hand, it specifies that if a question mark follows an open parentheses it should give a special meaning to the parenthesized group. * Backslash:: Introduces special sequences * Circumflex/dollar sign/period:: Behave specially with regard to new lines * Square brackets:: Are a bit different in strange cases * Options setting:: Toggle modifiers in the middle of a regexp * Non-capturing subpatterns:: Are not counted when backreferencing * Repetition:: Allows for non-greedy matching * Backreferences:: Allows for more than 10 back references * Assertions:: Allows for complex look ahead matches * Non-backtracking subpatterns:: Often gives more performance * Conditional subpatterns:: Allows if/then/else branches * Recursive patterns:: For example to match parentheses * Comments:: Because things can get complex... @end menu @node Backslash @appendixsec Backslash @cindex Perl-style regular expressions, escaped sequences There are a few difference in the handling of backslashed sequences in Perl mode. First of all, there are no @code{\o} and @code{\d} sequences. @sc{ascii} values for characters can be specified in octal with a @code{\@var{xxx}} sequence, where @var{xxx} is a sequence of up to three octal digits. If the first digit is a zero, the treatment of the sequence is straightforward; just note that if the character that follows the escaped digit is itself an octal digit, you have to supply three octal digits for @var{xxx}. For example @code{\07} is a @sc{bel} character rather than a @sc{nul} and a literal @code{7} (this sequence is instead represented by @code{\0007}). @cindex Perl-style regular expressions, backreferences The handling of a backslash followed by a digit other than 0 is complicated. Outside a character class, @command{sed} reads it and any following digits as a decimal number. If the number is less than 10, or if there have been at least that many previous capturing left parentheses in the expression, the entire sequence is taken as a back reference. A description of how this works is given later, following the discussion of parenthesized subpatterns. Inside a character class, or if the decimal number is greater than 9 and there have not been that many capturing subpatterns, @command{sed} re-reads up to three octal digits following the backslash, and generates a single byte from the least significant 8 bits of the value. Any subsequent digits stand for themselves. For example: @example \040 @i{is another way of writing a space} \40 @i{is the same, provided there are fewer than 40} @i{previous capturing subpatterns} \7 @i{is always a back reference} \011 @i{is always a tab} \11 @i{might be a back reference, or another way of} @i{writing a tab} \0113 @i{is a tab followed by the character @samp{3}} \113 @i{is the character with octal code 113 (since there} @i{can be no more than 99 back references)} \377 @i{is a byte consisting entirely of 1 bits (@sc{ascii} 255)} \81 @i{is either a back reference, or a binary zero} @i{followed by the two characters @samp{81}} @end example Note that octal values of 100 or greater must not be introduced duced by a leading zero, because no more than three octal digits are ever read. All the sequences that define a single byte value can be used both inside and outside character classes. In addition, inside a character class, the sequence @code{\b} is interpreted as the backspace character (hex 08). Outside a character class it has a different meaning (see below). In addition, there are four additional escapes specifying generic character classes (like @code{\w} and @code{\W} do): @cindex Perl-style regular expressions, character classes @table @samp @item \d Matches any decimal digit @item \D Matches any character that is not a decimal digit @end table In Perl mode, these character type sequences can appear both inside and outside character classes. Instead, in @sc{posix} mode these sequences (as well as @code{\w} and @code{\W}) are treated as two literal characters (a backslash and a letter) inside square brackets. Escaped sequences specifying assertions are also different in Perl mode. An assertion specifies a condition that has to be met at a particular point in a match, without consuming any characters from the subject string. The use of subpatterns for more complicated assertions is described below. The backslashed assertions are @cindex Perl-style regular expressions, assertions @table @samp @item \b Asserts that the point is at a word boundary. A word boundary is a position in the subject string where the current character and the previous character do not both match @code{\w} or @code{\W} (i.e. one matches @code{\w} and the other matches @code{\W}), or the start or end of the string if the first or last character matches @code{\w}, respectively. @item \B Asserts that the point is not at a word boundary. @item \A Asserts the matcher is at the start of pattern space (independent of multiline mode). @item \Z Asserts the matcher is at the end of pattern space, or at a newline before the end of pattern space (independent of multiline mode) @item \z Asserts the matcher is at the end of pattern space (independent of multiline mode) @end table These assertions may not appear in character classes (but note that @code{\b} has a different meaning, namely the backspace character, inside a character class). Note that Perl mode does not support directly assertions for the beginning and the end of word; the @acronym{GNU} extensions @code{\<} and @code{\>} achieve this purpose in @sc{posix} mode instead. The @code{\A}, @code{\Z}, and @code{\z} assertions differ from the traditional circumflex and dollar sign (described below) in that they only ever match at the very start and end of the subject string, whatever options are set; in particular @code{\A} and @code{\z} are the same as the @acronym{GNU} extensions @code{\`} and @code{\'} that are active in @sc{posix} mode. @node Circumflex/dollar sign/period @appendixsec Circumflex, dollar sign, period @cindex Perl-style regular expressions, newlines Outside a character class, in the default matching mode, the circumflex character is an assertion which is true only if the current matching point is at the start of the subject string. Inside a character class, the circumflex has an entirely different meaning (see below). The circumflex need not be the first character of the pattern if a number of alternatives are involved, but it should be the first thing in each alternative in which it appears if the pattern is ever to match that branch. If all possible alternatives, start with a circumflex, that is, if the pattern is constrained to match only at the start of the subject, it is said to be an @dfn{anchored} pattern. (There are also other constructs structs that can cause a pattern to be anchored.) A dollar sign is an assertion which is true only if the current matching point is at the end of the subject string, or immediately before a newline character that is the last character in the string (by default). A dollar sign need not be the last character of the pattern if a number of alternatives are involved, but it should be the last item in any branch in which it appears. A dollar sign has no special meaning in a character class. @cindex Perl-style regular expressions, multiline The meanings of the circumflex and dollar sign characters are changed if the @code{M} modifier option is used. When this is the case, they match immediately after and immediately before an internal @code{\n} character, respectively, in addition to matching at the start and end of the subject string. For example, the pattern @code{/^abc$/} matches the subject string @samp{def\nabc} in multiline mode, but not otherwise. Consequently, patterns that are anchored in single line mode because all branches start with @code{^} are not anchored in multiline mode. @cindex Perl-style regular expressions, multiline Note that the sequences @code{\A}, @code{\Z}, and @code{\z} can be used to match the start and end of the subject in both modes, and if all branches of a pattern start with @code{\A} is it always anchored, whether the @code{M} modifier is set or not. @cindex Perl-style regular expressions, single line Outside a character class, a dot in the pattern matches any one character in the subject, including a non-printing character, but not (by default) newline. If the @code{S} modifier is used, dots match newlines as well. Actually, the handling of dot is entirely independent of the handling of circumflex and dollar sign, the only relationship being that they both involve newline characters. Dot has no special meaning in a character class. @node Square brackets @appendixsec Square brackets @cindex Perl-style regular expressions, character classes An opening square bracket introduces a character class, terminated by a closing square bracket. A closing square bracket on its own is not special. If a closing square bracket is required as a member of the class, it should be the first data character in the class (after an initial circumflex, if present) or escaped with a backslash. A character class matches a single character in the subject; the character must be in the set of characters defined by the class, unless the first character in the class is a circumflex, in which case the subject character must not be in the set defined by the class. If a circumflex is actually required as a member of the class, ensure it is not the first character, or escape it with a backslash. For example, the character class [aeiou] matches any lower case vowel, while [^aeiou] matches any character that is not a lower case vowel. Note that a circumflex is just a convenient venient notation for specifying the characters which are in the class by enumerating those that are not. It is not an assertion: it still consumes a character from the subject string, and fails if the current pointer is at the end of the string. @cindex Perl-style regular expressions, case-insensitive When caseless matching is set, any letters in a class represent both their upper case and lower case versions, so for example, a caseless @code{[aeiou]} matches uppercase and lowercase @samp{A}s, and a caseless @code{[^aeiou]} does not match @samp{A}, whereas a case-sensitive version would. @cindex Perl-style regular expressions, single line @cindex Perl-style regular expressions, multiline The newline character is never treated in any special way in character classes, whatever the setting of the @code{S} and @code{M} options (modifiers) is. A class such as @code{[^a]} will always match a newline. The minus (hyphen) character can be used to specify a range of characters in a character class. For example, @code{[d-m]} matches any letter between d and m, inclusive. If a minus character is required in a class, it must be escaped with a backslash or appear in a position where it cannot be interpreted as indicating a range, typically as the first or last character in the class. It is not possible to have the literal character @code{]} as the end character of a range. A pattern such as @code{[W-]46]} is interpreted as a class of two characters (@code{W} and @code{-}) followed by a literal string @code{46]}, so it would match @samp{W46]} or @samp{-46]}. However, if the @code{]} is escaped with a backslash it is interpreted as the end of range, so @code{[W-\]46]} is interpreted as a single class containing a range followed by two separate characters. The octal or hexadecimal representation of @code{]} can also be used to end a range. Ranges operate in @sc{ascii} collating sequence. They can also be used for characters specified numerically, for example @code{[\000-\037]}. If a range that includes letters is used when caseless matching is set, it matches the letters in either case. For example, a caseless @code{[W-c]} is equivalent to @code{[][\^_`wxyzabc]}, matched caselessly, and if character tables for the French locale are in use, @code{[\xc8-\xcb]} matches accented E characters in both cases. Unlike in @sc{posix} mode, the character types @code{\d}, @code{\D}, @code{\s}, @code{\S}, @code{\w}, and @code{\W} may also appear in a character class, and add the characters that they match to the class. For example, @code{[\dABCDEF]} matches any hexadecimal digit. A circumflex can conveniently be used with the upper case character types to specify a more restricted set of characters than the matching lower case type. For example, the class @code{[^\W_]} matches any letter or digit, but not underscore. All non-alphameric characters other than @code{\}, @code{-}, @code{^} (at the start) and the terminating @code{]} are non-special in character classes, but it does no harm if they are escaped. Perl 5.6 supports the @sc{posix} notation for character classes, which uses names enclosed by @code{[:} and @code{:]} within the enclosing square brackets, and @value{SSED} supports this notation as well. For example, @example [01[:alpha:]%] @end example @noindent matches @samp{0}, @samp{1}, any alphabetic character, or @samp{%}. The supported class names are @table @code @item alnum Matches letters and digits @item alpha Matches letters @item ascii Matches character codes 0 - 127 @item cntrl Matches control characters @item digit Matches decimal digits (same as \d) @item graph Matches printing characters, excluding space @item lower Matches lower case letters @item print Matches printing characters, including space @item punct Matches printing characters, excluding letters and digits @item space Matches white space (same as \s) @item upper Matches upper case letters @item word Matches ``word'' characters (same as \w) @item xdigit Matches hexadecimal digits @end table The names @code{ascii} and @code{word} are extensions valid only in Perl mode. Another Perl extension is negation, which is indicated by a circumflex character after the colon. For example, @example [12[:^digit:]] @end example @noindent matches @samp{1}, @samp{2}, or any non-digit. @node Options setting @appendixsec Options setting @cindex Perl-style regular expressions, toggling options @cindex Perl-style regular expressions, case-insensitive @cindex Perl-style regular expressions, multiline @cindex Perl-style regular expressions, single line @cindex Perl-style regular expressions, extended The settings of the @code{I}, @code{M}, @code{S}, @code{X} modifiers can be changed from within the pattern by a sequence of Perl option letters enclosed between @code{(?} and @code{)}. The option letters must be lowercase. For example, @code{(?im)} sets caseless, multiline matching. It is also possible to unset these options by preceding the letter with a hyphen; you can also have combined settings and unsettings: @code{(?im-sx)} sets caseless and multiline matching, while unsets single line matching (for dots) and extended whitespace interpretation. If a letter appears both before and after the hyphen, the option is unset. The scope of these option changes depends on where in the pattern the setting occurs. For settings that are outside any subpattern (defined below), the effect is the same as if the options were set or unset at the start of matching. The following patterns all behave in exactly the same way: @example (?i)abc a(?i)bc ab(?i)c abc(?i) @end example which in turn is the same as specifying the pattern abc with the @code{I} modifier. In other words, ``top level'' settings apply to the whole pattern (unless there are other changes inside subpatterns). If there is more than one setting of the same option at top level, the rightmost setting is used. If an option change occurs inside a subpattern, the effect is different. This is a change of behaviour in Perl 5.005. An option change inside a subpattern affects only that part of the subpattern @emph{that follows} it, so @example (a(?i)b)c @end example @noindent matches abc and aBc and no other strings (assuming case-sensitive matching is used). By this means, options can be made to have different settings in different parts of the pattern. Any changes made in one alternative do carry on into subsequent branches within the same subpattern. For example, @example (a(?i)b|c) @end example @noindent matches @samp{ab}, @samp{aB}, @samp{c}, and @samp{C}, even though when matching @samp{C} the first branch is abandoned before the option setting. This is because the effects of option settings happen at compile time. There would be some very weird behaviour otherwise. @ignore There are two PCRE-specific options PCRE_UNGREEDY and PCRE_EXTRA that can be changed in the same way as the Perl-compatible options by using the characters U and X respectively. The (?X) flag setting is special in that it must always occur earlier in the pattern than any of the additional features it turns on, even when it is at top level. It is best put at the start. @end ignore @node Non-capturing subpatterns @appendixsec Non-capturing subpatterns @cindex Perl-style regular expressions, non-capturing subpatterns Marking part of a pattern as a subpattern does two things. On one hand, it localizes a set of alternatives; on the other hand, it sets up the subpattern as a capturing subpattern (as defined above). The subpattern can be backreferenced and referenced in the right side of @code{s} commands. For example, if the string @samp{the red king} is matched against the pattern @example the ((red|white) (king|queen)) @end example @noindent the captured substrings are @samp{red king}, @samp{red}, and @samp{king}, and are numbered 1, 2, and 3. The fact that plain parentheses fulfil two functions is not always helpful. There are often times when a grouping subpattern is required without a capturing requirement. If an opening parenthesis is followed by @code{?:}, the subpattern does not do any capturing, and is not counted when computing the number of any subsequent capturing subpatterns. For example, if the string @samp{the white queen} is matched against the pattern @example the ((?:red|white) (king|queen)) @end example @noindent the captured substrings are @samp{white queen} and @samp{queen}, and are numbered 1 and 2. The maximum number of captured substrings is 99, while the maximum number of all subpatterns, both capturing and non-capturing, is 200. As a convenient shorthand, if any option settings are equired at the start of a non-capturing subpattern, the option letters may appear between the @code{?} and the @code{:}. Thus the two patterns @example (?i:saturday|sunday) (?:(?i)saturday|sunday) @end example @noindent match exactly the same set of strings. Because alternative branches are tried from left to right, and options are not reset until the end of the subpattern is reached, an option setting in one branch does affect subsequent branches, so the above patterns match @samp{SUNDAY} as well as @samp{Saturday}. @node Repetition @appendixsec Repetition @cindex Perl-style regular expressions, repetitions Repetition is specified by quantifiers, which can follow any of the following items: @itemize @bullet @item a single character, possibly escaped @item the @code{.} special character @item a character class @item a back reference (see next section) @item a parenthesized subpattern (unless it is an assertion; @pxref{Assertions}) @end itemize The general repetition quantifier specifies a minimum and maximum number of permitted matches, by giving the two numbers in curly brackets (braces), separated by a comma. The numbers must be less than 65536, and the first must be less than or equal to the second. For example: @example z@{2,4@} @end example @noindent matches @samp{zz}, @samp{zzz}, or @samp{zzzz}. A closing brace on its own is not a special character. If the second number is omitted, but the comma is present, there is no upper limit; if the second number and the comma are both omitted, the quantifier specifies an exact number of required matches. Thus @example [aeiou]@{3,@} @end example @noindent matches at least 3 successive vowels, but may match many more, while @example \d@{8@} @end example @noindent matches exactly 8 digits. An opening curly bracket that appears in a position where a quantifier is not allowed, or one that does not match the syntax of a quantifier, is taken as a literal character. For example, @{,6@} is not a quantifier, but a literal string of four characters.@footnote{It raises an error if @option{-R} is not used.} The quantifier @samp{@{0@}} is permitted, causing the expression to behave as if the previous item and the quantifier were not present. For convenience (and historical compatibility) the three most common quantifiers have single-character abbreviations: @table @code @item * is equivalent to @{0,@} @item + is equivalent to @{1,@} @item ? is equivalent to @{0,1@} @end table It is possible to construct infinite loops by following a subpattern that can match no characters with a quantifier that has no upper limit, for example: @example (a?)* @end example Earlier versions of Perl used to give an error at compile time for such patterns. However, because there are cases where this can be useful, such patterns are now accepted, but if any repetition of the subpattern does in fact match no characters, the loop is forcibly broken. @cindex Greedy regular expression matching @cindex Perl-style regular expressions, stingy repetitions By default, the quantifiers are @dfn{greedy} like in @sc{posix} mode, that is, they match as much as possible (up to the maximum number of permitted times), without causing the rest of the pattern to fail. The classic example of where this gives problems is in trying to match comments in C programs. These appear between the sequences @code{/*} and @code{*/} and within the sequence, individual @code{*} and @code{/} characters may appear. An attempt to match C comments by applying the pattern @example /\*.*\*/ @end example @noindent to the string @example /* first command */ not comment /* second comment */ @end example @noindent fails, because it matches the entire string owing to the greediness of the @code{.*} item. However, if a quantifier is followed by a question mark, it ceases to be greedy, and instead matches the minimum number of times possible, so the pattern @code{/\*.*?\*/} does the right thing with the C comments. The meaning of the various quantifiers is not otherwise changed, just the preferred number of matches. Do not confuse this use of question mark with its use as a quantifier in its own right. Because it has two uses, it can sometimes appear doubled, as in @example \d??\d @end example which matches one digit by preference, but can match two if that is the only way the rest of the pattern matches. Note that greediness does not matter when specifying addresses, but can be nevertheless used to improve performance. @ignore If the PCRE_UNGREEDY option is set (an option which is not available in Perl), the quantifiers are not greedy by default, but individual ones can be made greedy by following them with a question mark. In other words, it inverts the default behaviour. @end ignore When a parenthesized subpattern is quantified with a minimum repeat count that is greater than 1 or with a limited maximum, more store is required for the compiled pattern, in proportion to the size of the minimum or maximum. @cindex Perl-style regular expressions, single line If a pattern starts with @code{.*} or @code{.@{0,@}} and the @code{S} modifier is used, the pattern is implicitly anchored, because whatever follows will be tried against every character position in the subject string, so there is no point in retrying the overall match at any position after the first. PCRE treats such a pattern as though it were preceded by \A. When a capturing subpattern is repeated, the value captured is the substring that matched the final iteration. For example, after @example (tweedle[dume]@{3@}\s*)+ @end example @noindent has matched @samp{tweedledum tweedledee} the value of the captured substring is @samp{tweedledee}. However, if there are nested capturing subpatterns, the corresponding captured values may have been set in previous iterations. For example, after @example /(a|(b))+/ @end example matches @samp{aba}, the value of the second captured substring is @samp{b}. @node Backreferences @appendixsec Backreferences @cindex Perl-style regular expressions, backreferences Outside a character class, a backslash followed by a digit greater than 0 (and possibly further digits) is a back reference to a capturing subpattern earlier (i.e. to its left) in the pattern, provided there have been that many previous capturing left parentheses. However, if the decimal number following the backslash is less than 10, it is always taken as a back reference, and causes an error only if there are not that many capturing left parentheses in the entire pattern. In other words, the parentheses that are referenced need not be to the left of the reference for numbers less than 10. @ref{Backslash} for further details of the handling of digits following a backslash. A back reference matches whatever actually matched the capturing subpattern in the current subject string, rather than anything matching the subpattern itself. So the pattern @example (sens|respons)e and \1ibility @end example @noindent matches @samp{sense and sensibility} and @samp{response and responsibility}, but not @samp{sense and responsibility}. If caseful matching is in force at the time of the back reference, the case of letters is relevant. For example, @example ((?i)blah)\s+\1 @end example @noindent matches @samp{blah blah} and @samp{Blah Blah}, but not @samp{BLAH blah}, even though the original capturing subpattern is matched caselessly. There may be more than one back reference to the same subpattern. Also, if a subpattern has not actually been used in a particular match, any back references to it always fail. For example, the pattern @example (a|(bc))\2 @end example @noindent always fails if it starts to match @samp{a} rather than @samp{bc}. Because there may be up to 99 back references, all digits following the backslash are taken as part of a potential back reference number; this is different from what happens in @sc{posix} mode. If the pattern continues with a digit character, some delimiter must be used to terminate the back reference. If the @code{X} modifier option is set, this can be whitespace. Otherwise an empty comment can be used, or the following character can be expressed in hexadecimal or octal. A back reference that occurs inside the parentheses to which it refers fails when the subpattern is first used, so, for example, @code{(a\1)} never matches. However, such references can be useful inside repeated subpatterns. For example, the pattern @example (a|b\1)+ @end example @noindent matches any number of @samp{a}s and also @samp{aba}, @samp{ababbaa}, etc. At each iteration of the subpattern, the back reference matches the character string corresponding to the previous iteration. In order for this to work, the pattern must be such that the first iteration does not need to match the back reference. This can be done using alternation, as in the example above, or by a quantifier with a minimum of zero. @node Assertions @appendixsec Assertions @cindex Perl-style regular expressions, assertions @cindex Perl-style regular expressions, asserting subpatterns An assertion is a test on the characters following or preceding the current matching point that does not actually consume any characters. The simple assertions coded as @code{\b}, @code{\B}, @code{\A}, @code{\Z}, @code{\z}, @code{^} and @code{$} are described above. More complicated assertions are coded as subpatterns. There are two kinds: those that look ahead of the current position in the subject string, and those that look behind it. @cindex Perl-style regular expressions, lookahead subpatterns An assertion subpattern is matched in the normal way, except that it does not cause the current matching position to be changed. Lookahead assertions start with @code{(?=} for positive assertions and @code{(?!} for negative assertions. For example, @example \w+(?=;) @end example @noindent matches a word followed by a semicolon, but does not include the semicolon in the match, and @example foo(?!bar) @end example @noindent matches any occurrence of @samp{foo} that is not followed by @samp{bar}. Note that the apparently similar pattern @example (?!foo)bar @end example @noindent @cindex Perl-style regular expressions, lookbehind subpatterns finds any occurrence of @samp{bar} even if it is preceded by @samp{foo}, because the assertion @code{(?!foo)} is always true when the next three characters are @samp{bar}. A lookbehind assertion is needed to achieve this effect. Lookbehind assertions start with @code{(?<=} for positive assertions and @code{(?} as in this example: @example (?>\d+)bar @end example This kind of parenthesis ``locks up'' the part of the pattern it contains once it has matched, and a failure further into the pattern is prevented from backtracking into it. Backtracking past it to previous items, however, works as normal. Non-backtracking subpatterns are not capturing subpatterns. Simple cases such as the above example can be thought of as a maximizing repeat that must swallow everything it can. So, while both @code{\d+} and @code{\d+?} are prepared to adjust the number of digits they match in order to make the rest of the pattern match, @code{(?>\d+)} can only match an entire sequence of digits. This construction can of course contain arbitrarily complicated subpatterns, and it can be nested. @cindex Perl-style regular expressions, lookbehind subpatterns Non-backtracking subpatterns can be used in conjunction with look-behind assertions to specify efficient matching at the end of the subject string. Consider a simple pattern such as @example abcd$ @end example @noindent when applied to a long string which does not match. Because matching proceeds from left to right, @command{sed} will look for each @samp{a} in the subject and then see if what follows matches the rest of the pattern. If the pattern is specified as @example ^.*abcd$ @end example @noindent the initial @code{.*} matches the entire string at first, but when this fails (because there is no following @samp{a}), it backtracks to match all but the last character, then all but the last two characters, and so on. Once again the search for @samp{a} covers the entire string, from right to left, so we are no better off. However, if the pattern is written as @example ^(?>.*)(?<=abcd) @end example there can be no backtracking for the .* item; it can match only the entire string. The subsequent lookbehind assertion does a single test on the last four characters. If it fails, the match fails immediately. For long strings, this approach makes a significant difference to the processing time. When a pattern contains an unlimited repeat inside a subpattern that can itself be repeated an unlimited number of times, the use of a once-only subpattern is the only way to avoid some failing matches taking a very long time indeed.@footnote{Actually, the matcher embedded in @value{SSED} tries to do something for this in the simplest cases, like @code{([^b]*b)*}. These cases are actually quite common: they happen for example in a regular expression like @code{\/\*([^*]*\*)*\/} which matches C comments.} The pattern @example (\D+|<\d+>)*[!?] @end example ([^0-9<]+<(\d+>)?)*[!?] @noindent matches an unlimited number of substrings that either consist of non-digits, or digits enclosed in angular brackets, followed by an exclamation or question mark. When it matches, it runs quickly. However, if it is applied to @example aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @end example @noindent it takes a long time before reporting failure. This is because the string can be divided between the two repeats in a large number of ways, and all have to be tried.@footnote{The example used @code{[!?]} rather than a single character at the end, because both @value{SSED} and Perl have an optimization that allows for fast failure when a single character is used. They remember the last single character that is required for a match, and fail early if it is not present in the string.} If the pattern is changed to @example ((?>\D+)|<\d+>)*[!?] @end example sequences of non-digits cannot be broken, and failure happens quickly. @node Conditional subpatterns @appendixsec Conditional subpatterns @cindex Perl-style regular expressions, conditional subpatterns It is possible to cause the matching process to obey a subpattern conditionally or to choose between two alternative subpatterns, depending on the result of an assertion, or whether a previous capturing subpattern matched or not. The two possible forms of conditional subpattern are @example (?(@var{condition})@var{yes-pattern}) (?(@var{condition})@var{yes-pattern}|@var{no-pattern}) @end example If the condition is satisfied, the yes-pattern is used; otherwise the no-pattern (if present) is used. If there are more than two alternatives in the subpattern, a compile-time error occurs. There are two kinds of condition. If the text between the parentheses consists of a sequence of digits, the condition is satisfied if the capturing subpattern of that number has previously matched. The number must be greater than zero. Consider the following pattern, which contains non-significant white space to make it more readable (assume the @code{X} modifier) and to divide it into three parts for ease of discussion: @example ( \( )? [^()]+ (?(1) \) ) @end example The first part matches an optional opening parenthesis, and if that character is present, sets it as the first captured substring. The second part matches one or more characters that are not parentheses. The third part is a conditional subpattern that tests whether the first set of parentheses matched or not. If they did, that is, if subject started with an opening parenthesis, the condition is true, and so the yes-pattern is executed and a closing parenthesis is required. Otherwise, since no-pattern is not present, the subpattern matches nothing. In other words, this pattern matches a sequence of non-parentheses, optionally enclosed in parentheses. @cindex Perl-style regular expressions, lookahead subpatterns If the condition is not a sequence of digits, it must be an assertion. This may be a positive or negative lookahead or lookbehind assertion. Consider this pattern, again containing non-significant white space, and with the two alternatives on the second line: @example (?(?=...[a-z]) \d\d-[a-z]@{3@}-\d\d | \d\d-\d\d-\d\d ) @end example The condition is a positive lookahead assertion that matches a letter that is three characters away from the current point. If a letter is found, the subject is matched against the first alternative @samp{@var{dd}-@var{aaa}-@var{dd}} (where @var{aaa} are letters and @var{dd} are digits); otherwise it is matched against the second alternative, @samp{@var{dd}-@var{dd}-@var{dd}}. @node Recursive patterns @appendixsec Recursive patterns @cindex Perl-style regular expressions, recursive patterns @cindex Perl-style regular expressions, recursion Consider the problem of matching a string in parentheses, allowing for unlimited nested parentheses. Without the use of recursion, the best that can be done is to use a pattern that matches up to some fixed depth of nesting. It is not possible to handle an arbitrary nesting depth. Perl 5.6 has provided an experimental facility that allows regular expressions to recurse (amongst other things). It does this by interpolating Perl code in the expression at run time, and the code can refer to the expression itself. A Perl pattern tern to solve the parentheses problem can be created like this: @example $re = qr@{\( (?: (?>[^()]+) | (?p@{$re@}) )* \)@}x; @end example The @code{(?p@{...@})} item interpolates Perl code at run time, and in this case refers recursively to the pattern in which it appears. Obviously, @command{sed} cannot support the interpolation of Perl code. Instead, the special item @code{(?R)} is provided for the specific case of recursion. This pattern solves the parentheses problem (assume the @code{X} modifier option is used so that white space is ignored): @example \( ( (?>[^()]+) | (?R) )* \) @end example First it matches an opening parenthesis. Then it matches any number of substrings which can either be a sequence of non-parentheses, or a recursive match of the pattern itself (i.e. a correctly parenthesized substring). Finally there is a closing parenthesis. This particular example pattern contains nested unlimited repeats, and so the use of a non-backtracking subpattern for matching strings of non-parentheses is important when applying the pattern to strings that do not match. For example, when it is applied to @example (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa() @end example it yields a ``no match'' response quickly. However, if a standard backtracking subpattern is not used, the match runs for a very long time indeed because there are so many different ways the @code{+} and @code{*} repeats can carve up the subject, and all have to be tested before failure can be reported. The values set for any capturing subpatterns are those from the outermost level of the recursion at which the subpattern value is set. If the pattern above is matched against @example (ab(cd)ef) @end example @noindent the value for the capturing parentheses is @samp{ef}, which is the last value taken on at the top level. @node Comments @appendixsec Comments @cindex Perl-style regular expressions, comments The sequence (?# marks the start of a comment which continues ues up to the next closing parenthesis. Nested parentheses are not permitted. The characters that make up a comment play no part in the pattern matching at all. @cindex Perl-style regular expressions, extended If the @code{X} modifier option is used, an unescaped @code{#} character outside a character class introduces a comment that continues up to the next newline character in the pattern. @end ifset @page @node Concept Index @unnumbered Concept Index This is a general index of all issues discussed in this manual, with the exception of the @command{sed} commands and command-line options. @printindex cp @page @node Command and Option Index @unnumbered Command and Option Index This is an alphabetical list of all @command{sed} commands and command-line options. @printindex fn @contents @bye @c XXX FIXME: the term "cycle" is never defined... kbuild-3686/src/oldsed/doc/config.texi0000664000175000017500000000031515053010106017650 0ustar locutuslocutus@dircategory Text creation and manipulation @direntry * sed: (sed). Stream EDitor. @end direntry @clear PERL @set SSEDEXT @acronym{GNU} extensions @set SSED @acronym{GNU} @command{sed} kbuild-3686/src/oldsed/doc/sed.info0000664000175000017500000000436715053010106017153 0ustar locutuslocutusThis is ../../doc/sed.info, produced by makeinfo version 4.5 from ../../doc/sed.texi. INFO-DIR-SECTION Text creation and manipulation START-INFO-DIR-ENTRY * sed: (sed). Stream EDitor. END-INFO-DIR-ENTRY This file documents version 4.1.5 of GNU `sed', a stream editor. Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This document is released under the terms of the GNU Free Documentation License as published by the Free Software Foundation; either version 1.1, or (at your option) any later version. You should have received a copy of the GNU Free Documentation License along with GNU `sed'; see the file `COPYING.DOC'. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02110-1301, USA. There are no Cover Texts and no Invariant Sections; this text, along with its equivalent in the printed manual, constitutes the Title Page.  Indirect: sed.info-1: 935 sed.info-2: 50405  Tag Table: (Indirect) Node: Top935 Node: Introduction3816 Node: Invoking sed4370 Ref: Invoking sed-Footnote-19396 Ref: Invoking sed-Footnote-29588 Node: sed Programs9691 Node: Execution Cycle10838 Ref: Execution Cycle-Footnote-112011 Node: Addresses12322 Node: Regular Expressions17061 Node: Common Commands24610 Node: The "s" Command26608 Ref: The "s" Command-Footnote-130940 Node: Other Commands31012 Ref: Other Commands-Footnote-136149 Node: Programming Commands36221 Node: Extended Commands37130 Node: Escapes40705 Ref: Escapes-Footnote-143711 Node: Examples43902 Node: Centering lines44997 Node: Increment a number45909 Ref: Increment a number-Footnote-147489 Node: Rename files to lower case47609 Node: Print bash environment50405 Node: Reverse chars of lines51185 Ref: Reverse chars of lines-Footnote-152202 Node: tac52424 Node: cat -n53206 Node: cat -b55063 Node: wc -c55815 Ref: wc -c-Footnote-157748 Node: wc -w57817 Node: wc -l59289 Node: head59526 Node: tail59850 Node: uniq61534 Node: uniq -d62330 Node: uniq -u63054 Node: cat -s63778 Node: Limitations65667 Node: Other Resources66507 Node: Reporting Bugs67433 Ref: Reporting Bugs-Footnote-173962 Node: Extended regexps74033 Node: Concept Index75200 Node: Command and Option Index85215  End Tag Table kbuild-3686/src/oldsed/doc/sed.10000664000175000017500000002070515053010105016351 0ustar locutuslocutus.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.28. .TH SED "1" "February 2006" "sed version 4.1.4" "User Commands" .SH NAME sed \- stream editor for filtering and transforming text .SH SYNOPSIS .B sed [\fIOPTION\fR]... \fI{script-only-if-no-other-script} \fR[\fIinput-file\fR]... .SH DESCRIPTION .ds sd \fIsed\fP .ds Sd \fISed\fP \*(Sd is a stream editor. A stream editor is used to perform basic text transformations on an input stream (a file or input from a pipeline). While in some ways similar to an editor which permits scripted edits (such as \fIed\fP), \*(sd works by making only one pass over the input(s), and is consequently more efficient. But it is \*(sd's ability to filter text in a pipeline which particularly distinguishes it from other types of editors. .HP \fB\-n\fR, \fB\-\-quiet\fR, \fB\-\-silent\fR .IP suppress automatic printing of pattern space .HP \fB\-e\fR script, \fB\-\-expression\fR=\fIscript\fR .IP add the script to the commands to be executed .HP \fB\-f\fR script-file, \fB\-\-file\fR=\fIscript\-file\fR .IP add the contents of script-file to the commands to be executed .HP \fB\-i[SUFFIX]\fR, \fB\-\-in\-place\fR[=\fISUFFIX\fR] .IP edit files in place (makes backup if extension supplied) .HP \fB\-l\fR N, \fB\-\-line\-length\fR=\fIN\fR .IP specify the desired line-wrap length for the `l' command .HP \fB\-\-posix\fR .IP disable all GNU extensions. .HP \fB\-r\fR, \fB\-\-regexp\-extended\fR .IP use extended regular expressions in the script. .HP \fB\-s\fR, \fB\-\-separate\fR .IP consider files as separate rather than as a single continuous long stream. .HP \fB\-u\fR, \fB\-\-unbuffered\fR .IP load minimal amounts of data from the input files and flush the output buffers more often .TP \fB\-\-help\fR display this help and exit .TP \fB\-\-version\fR output version information and exit .PP If no \fB\-e\fR, \fB\-\-expression\fR, \fB\-f\fR, or \fB\-\-file\fR option is given, then the first non-option argument is taken as the sed script to interpret. All remaining arguments are names of input files; if no input files are specified, then the standard input is read. .PP E-mail bug reports to: bonzini@gnu.org . Be sure to include the word ``sed'' somewhere in the ``Subject:'' field. .SH "COMMAND SYNOPSIS" This is just a brief synopsis of \*(sd commands to serve as a reminder to those who already know \*(sd; other documentation (such as the texinfo document) must be consulted for fuller descriptions. .SS Zero-address ``commands'' .TP .RI :\ label Label for .B b and .B t commands. .TP .RI # comment The comment extends until the next newline (or the end of a .B -e script fragment). .TP } The closing bracket of a { } block. .SS Zero- or One- address commands .TP = Print the current line number. .TP a \e .TP .I text Append .IR text , which has each embedded newline preceded by a backslash. .TP i \e .TP .I text Insert .IR text , which has each embedded newline preceded by a backslash. .TP q Immediately quit the \*(sd script without processing any more input, except that if auto-print is not disabled the current pattern space will be printed. .TP Q Immediately quit the \*(sd script without processing any more input. .TP .RI r\ filename Append text read from .IR filename . .TP .RI R\ filename Append a line read from .IR filename . .SS Commands which accept address ranges .TP { Begin a block of commands (end with a }). .TP .RI b\ label Branch to .IR label ; if .I label is omitted, branch to end of script. .TP .RI t\ label If a s/// has done a successful substitution since the last input line was read and since the last t or T command, then branch to .IR label ; if .I label is omitted, branch to end of script. .TP .RI T\ label If no s/// has done a successful substitution since the last input line was read and since the last t or T command, then branch to .IR label ; if .I label is omitted, branch to end of script. .TP c \e .TP .I text Replace the selected lines with .IR text , which has each embedded newline preceded by a backslash. .TP d Delete pattern space. Start next cycle. .TP D Delete up to the first embedded newline in the pattern space. Start next cycle, but skip reading from the input if there is still data in the pattern space. .TP h H Copy/append pattern space to hold space. .TP g G Copy/append hold space to pattern space. .TP x Exchange the contents of the hold and pattern spaces. .TP l List out the current line in a ``visually unambiguous'' form. .TP n N Read/append the next line of input into the pattern space. .TP p Print the current pattern space. .TP P Print up to the first embedded newline of the current pattern space. .TP .RI s/ regexp / replacement / Attempt to match .I regexp against the pattern space. If successful, replace that portion matched with .IR replacement . The .I replacement may contain the special character .B & to refer to that portion of the pattern space which matched, and the special escapes \e1 through \e9 to refer to the corresponding matching sub-expressions in the .IR regexp . .TP .RI w\ filename Write the current pattern space to .IR filename . .TP .RI W\ filename Write the first line of the current pattern space to .IR filename . .TP .RI y/ source / dest / Transliterate the characters in the pattern space which appear in .I source to the corresponding character in .IR dest . .SH Addresses \*(Sd commands can be given with no addresses, in which case the command will be executed for all input lines; with one address, in which case the command will only be executed for input lines which match that address; or with two addresses, in which case the command will be executed for all input lines which match the inclusive range of lines starting from the first address and continuing to the second address. Three things to note about address ranges: the syntax is .IR addr1 , addr2 (i.e., the addresses are separated by a comma); the line which .I addr1 matched will always be accepted, even if .I addr2 selects an earlier line; and if .I addr2 is a .IR regexp , it will not be tested against the line that .I addr1 matched. .PP After the address (or address-range), and before the command, a .B ! may be inserted, which specifies that the command shall only be executed if the address (or address-range) does .B not match. .PP The following address types are supported: .TP .I number Match only the specified line .IR number . .TP .IR first ~ step Match every .IR step 'th line starting with line .IR first . For example, ``sed -n 1~2p'' will print all the odd-numbered lines in the input stream, and the address 2~5 will match every fifth line, starting with the second. (This is an extension.) .TP $ Match the last line. .TP .RI / regexp / Match lines matching the regular expression .IR regexp . .TP .BI \fR\e\fPc regexp c Match lines matching the regular expression .IR regexp . The .B c may be any character. .PP GNU \*(sd also supports some special 2-address forms: .TP .RI 0, addr2 Start out in "matched first address" state, until .I addr2 is found. This is similar to .RI 1, addr2 , except that if .I addr2 matches the very first line of input the .RI 0, addr2 form will be at the end of its range, whereas the .RI 1, addr2 form will still be at the beginning of its range. .TP .IR addr1 ,+ N Will match .I addr1 and the .I N lines following .IR addr1 . .TP .IR addr1 ,~ N Will match .I addr1 and the lines following .I addr1 until the next line whose input line number is a multiple of .IR N . .SH "REGULAR EXPRESSIONS" POSIX.2 BREs .I should be supported, but they aren't completely because of performance problems. The .B \en sequence in a regular expression matches the newline character, and similarly for .BR \ea , .BR \et , and other sequences. .SH BUGS .PP E-mail bug reports to .BR bonzini@gnu.org . Be sure to include the word ``sed'' somewhere in the ``Subject:'' field. Also, please include the output of ``sed --version'' in the body of your report if at all possible. .SH COPYRIGHT Copyright \(co 2003 Free Software Foundation, Inc. .br This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, to the extent permitted by law. .SH "SEE ALSO" .BR awk (1), .BR ed (1), .BR grep (1), .BR tr (1), .BR perlre (1), sed.info, any of various books on \*(sd, .na the \*(sd FAQ (http://sed.sf.net/grabbag/tutorials/sedfaq.txt), http://sed.sf.net/grabbag/. .PP The full documentation for .B sed is maintained as a Texinfo manual. If the .B info and .B sed programs are properly installed at your site, the command .IP .B info sed .PP should give you access to the complete manual. kbuild-3686/src/oldsed/configure0000775000175000017500000122160715053010105016663 0ustar locutuslocutus#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for sed 4.1.5. # # Report bugs to . # # Copyright (C) 2003 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 DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/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 -z "`(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 test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # 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='sed' PACKAGE_TARNAME='sed' PACKAGE_VERSION='4.1.5' PACKAGE_STRING='sed 4.1.5' PACKAGE_BUGREPORT='bonzini@gnu.org' ac_unique_file="sed/sed.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 INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar SED_FEATURE_VERSION CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE RANLIB ac_ct_RANLIB CPP EGREP HAVE__BOOL ALLOCA LIBOBJS TEST_REGEX_TRUE TEST_REGEX_FALSE BUILD_HTML_TRUE BUILD_HTML_FALSE TEXI2HTML MAKEINFO_HTML_TRUE MAKEINFO_HTML_FALSE TEXI2HTML_HTML_TRUE TEXI2HTML_HTML_FALSE MKINSTALLDIRS MSGFMT GMSGFMT XGETTEXT MSGMERGE build build_cpu build_vendor build_os host host_cpu host_vendor host_os GLIBC21 LIBICONV LTLIBICONV INTLBISON USE_NLS BUILD_INCLUDED_LIBINTL USE_INCLUDED_LIBINTL CATOBJEXT INTLOBJS DATADIRNAME INSTOBJEXT GENCAT INTL_LIBTOOL_SUFFIX_PREFIX INTLLIBS LIBINTL LTLIBINTL POSUB 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. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures sed 4.1.5 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] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF Program names: --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 System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of sed 4.1.5:";; esac cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --disable-largefile omit support for large files --disable-i18n disable internationalization (default=yes) --enable-regex-tests enable regex matcher regression tests (default=yes) --enable-html build HTML manual (default=no) --disable-nls do not use Native Language Support Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-included-regex use included regex matcher (default=yes) --with-gnu-ld assume the C compiler uses GNU ld default=no --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib --without-libiconv-prefix don't search for libiconv in includedir and libdir --with-included-gettext use the GNU gettext library included here --with-libintl-prefix=DIR search for libintl in DIR/include and DIR/lib --without-libintl-prefix don't search for libintl in includedir and libdir 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. Report bugs to . _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 # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac 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 sed configure 4.1.5 generated by GNU Autoconf 2.59 Copyright (C) 2003 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 sed $as_me 4.1.5, which was generated by GNU Autoconf 2.59. 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 && 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_aux_dir= for ac_dir in config $srcdir/config; 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 config $srcdir/config" >&5 echo "$as_me: error: cannot find install-sh or install.sh in config $srcdir/config" >&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. ac_config_headers="$ac_config_headers config.h:config_h.in" am__api_version="1.9" # 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" # OS/2's system install, which has a completely different semantic # ./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/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /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' echo "$as_me:$LINENO: checking whether build environment is sane" >&5 echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&5 echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&2;} { (exit 1); exit 1; }; } fi test "$2" = conftest.file ) then # Ok. : else { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! Check your system clock" >&5 echo "$as_me: error: newly created file is older than distributed files! Check your system clock" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 test "$program_prefix" != NONE && program_transform_name="s,^,$program_prefix,;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s,\$,$program_suffix,;$program_transform_name" # Double any \ or $. echo might interpret backslashes. # By default was `s,x,x', remove it if useless. cat <<\_ACEOF >conftest.sed s/[\\$]/&&/g;s/;s,x,x,$// _ACEOF program_transform_name=`echo $program_transform_name | sed -f conftest.sed` rm conftest.sed # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then # We used to keeping the `.' as first argument, in order to # allow $(mkdir_p) to be used without argument. As in # $(mkdir_p) $(somedir) # where $(somedir) is conditionally defined. However this is wrong # for two reasons: # 1. if the package is installed by a user who cannot write `.' # make install will fail, # 2. the above comment should most certainly read # $(mkdir_p) $(DESTDIR)$(somedir) # so it does not work when $(somedir) is undefined and # $(DESTDIR) is not. # To support the latter case, we have to write # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), # so the `.' trick is pointless. mkdir_p='mkdir -p --' else # On NextStep and OpenStep, the `mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because `.' already # exists. for d in ./-p ./--version; do test -d $d && rmdir $d done # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. if test -f "$ac_aux_dir/mkinstalldirs"; then mkdir_p='$(mkinstalldirs)' else mkdir_p='$(install_sh) -d' fi fi for ac_prog in gawk mawk nawk awk 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_AWK+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # 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_AWK="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then echo "$as_me:$LINENO: result: $AWK" >&5 echo "${ECHO_T}$AWK" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$AWK" && break done echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF all: @echo 'ac_maketemp="$(MAKE)"' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftest.make fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 SET_MAKE= else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} { (exit 1); exit 1; }; } fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='sed' VERSION='4.1.5' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} install_sh=${install_sh-"$am_aux_dir/install-sh"} # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then 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 fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. AMTAR=${AMTAR-"${am_missing_run}tar"} am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' SED_FEATURE_VERSION=4.1 cat >>confdefs.h <<_ACEOF #define SED_FEATURE_VERSION "$SED_FEATURE_VERSION" _ACEOF 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 /* 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 file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $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 /* 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 /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 /* 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; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std1 is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std1. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF # 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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 \ '' \ '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 /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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.err 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 DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi echo "$as_me:$LINENO: result: $_am_result" >&5 echo "${ECHO_T}$_am_result" >&6 rm -f confinc confmf # Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then enableval="$enable_dependency_tracking" fi; if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 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 cat >>confdefs.h <<\_ACEOF #define _GNU_SOURCE 1 _ACEOF 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 /* 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 ac_cpp_err=$ac_cpp_err$ac_c_werror_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 /* 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 ac_cpp_err=$ac_cpp_err$ac_c_werror_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 /* 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 ac_cpp_err=$ac_cpp_err$ac_c_werror_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 /* 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 ac_cpp_err=$ac_cpp_err$ac_c_werror_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 AIX" >&5 echo $ECHO_N "checking for AIX... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef _AIX yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define _ALL_SOURCE 1 _ACEOF else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest* 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 /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* 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 /* 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 /* 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 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 /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 if test "${ac_cv_header_minix_config_h+set}" = set; then echo "$as_me:$LINENO: checking for minix/config.h" >&5 echo $ECHO_N "checking for minix/config.h... $ECHO_C" >&6 if test "${ac_cv_header_minix_config_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_minix_config_h" >&5 echo "${ECHO_T}$ac_cv_header_minix_config_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking minix/config.h usability" >&5 echo $ECHO_N "checking minix/config.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 minix/config.h presence" >&5 echo $ECHO_N "checking minix/config.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* 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 ac_cpp_err=$ac_cpp_err$ac_c_werror_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:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: minix/config.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: minix/config.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: minix/config.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: minix/config.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: minix/config.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: minix/config.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: minix/config.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: minix/config.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: minix/config.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: minix/config.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: minix/config.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: minix/config.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: minix/config.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: minix/config.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: minix/config.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: minix/config.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------ ## ## Report this to bonzini@gnu.org ## ## ------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for minix/config.h" >&5 echo $ECHO_N "checking for minix/config.h... $ECHO_C" >&6 if test "${ac_cv_header_minix_config_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_minix_config_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_minix_config_h" >&5 echo "${ECHO_T}$ac_cv_header_minix_config_h" >&6 fi if test $ac_cv_header_minix_config_h = yes; then MINIX=yes else MINIX= fi if test "$MINIX" = yes; then cat >>confdefs.h <<\_ACEOF #define _POSIX_SOURCE 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define _POSIX_1_SOURCE 2 _ACEOF cat >>confdefs.h <<\_ACEOF #define _MINIX 1 _ACEOF fi echo "$as_me:$LINENO: checking for library containing strerror" >&5 echo $ECHO_N "checking for library containing strerror... $ECHO_C" >&6 if test "${ac_cv_search_strerror+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_strerror=no cat >conftest.$ac_ext <<_ACEOF /* 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 strerror (); int main () { strerror (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_search_strerror="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_strerror" = no; then for ac_lib in cposix; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* 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 strerror (); int main () { strerror (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_search_strerror="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_strerror" >&5 echo "${ECHO_T}$ac_cv_search_strerror" >&6 if test "$ac_cv_search_strerror" != no; then test "$ac_cv_search_strerror" = "none required" || LIBS="$ac_cv_search_strerror $LIBS" fi # Check whether --enable-largefile or --disable-largefile was given. if test "${enable_largefile+set}" = set; then enableval="$enable_largefile" fi; if test "$enable_largefile" != no; then echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5 echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6 if test "${ac_cv_sys_largefile_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_sys_largefile_CC=no if test "$GCC" != yes; then ac_save_CC=$CC while :; do # IRIX 6.2 and later do not support large files by default, # so use the C compiler's -n32 option if that helps. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err conftest.$ac_objext CC="$CC -n32" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_sys_largefile_CC=' -n32'; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext break done CC=$ac_save_CC rm -f conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5 echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6 if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5 echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6 if test "${ac_cv_sys_file_offset_bits+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else while :; do ac_cv_sys_file_offset_bits=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_sys_file_offset_bits=64; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext break done fi echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5 echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6 if test "$ac_cv_sys_file_offset_bits" != no; then cat >>confdefs.h <<_ACEOF #define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits _ACEOF fi rm -f conftest* echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5 echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6 if test "${ac_cv_sys_large_files+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else while :; do ac_cv_sys_large_files=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _LARGE_FILES 1 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_sys_large_files=1; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext break done fi echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5 echo "${ECHO_T}$ac_cv_sys_large_files" >&6 if test "$ac_cv_sys_large_files" != no; then cat >>confdefs.h <<_ACEOF #define _LARGE_FILES $ac_cv_sys_large_files _ACEOF fi rm -f conftest* fi echo "$as_me:$LINENO: checking for long file names" >&5 echo $ECHO_N "checking for long file names... $ECHO_C" >&6 if test "${ac_cv_sys_long_file_names+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_sys_long_file_names=yes # Test for long file names in all the places we know might matter: # . the current directory, where building will happen # $prefix/lib where we will be installing things # $exec_prefix/lib likewise # eval it to expand exec_prefix. # $TMPDIR if set, where it might want to write temporary files # if $TMPDIR is not set: # /tmp where it might want to write temporary files # /var/tmp likewise # /usr/tmp likewise if test -n "$TMPDIR" && test -d "$TMPDIR" && test -w "$TMPDIR"; then ac_tmpdirs=$TMPDIR else ac_tmpdirs='/tmp /var/tmp /usr/tmp' fi for ac_dir in . $ac_tmpdirs `eval echo $prefix/lib $exec_prefix/lib` ; do test -d $ac_dir || continue test -w $ac_dir || continue # It is less confusing to not echo anything here. ac_xdir=$ac_dir/cf$$ (umask 077 && mkdir $ac_xdir 2>/dev/null) || continue ac_tf1=$ac_xdir/conftest9012345 ac_tf2=$ac_xdir/conftest9012346 (echo 1 >$ac_tf1) 2>/dev/null (echo 2 >$ac_tf2) 2>/dev/null ac_val=`cat $ac_tf1 2>/dev/null` if test ! -f $ac_tf1 || test "$ac_val" != 1; then ac_cv_sys_long_file_names=no rm -rf $ac_xdir 2>/dev/null break fi rm -rf $ac_xdir 2>/dev/null done fi echo "$as_me:$LINENO: result: $ac_cv_sys_long_file_names" >&5 echo "${ECHO_T}$ac_cv_sys_long_file_names" >&6 if test $ac_cv_sys_long_file_names = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_LONG_FILE_NAMES 1 _ACEOF fi echo "$as_me:$LINENO: checking whether -lcP is needed" >&5 echo $ECHO_N "checking whether -lcP is needed... $ECHO_C" >&6 if test "${sed_cv_libcp_needed+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then sed_cv_libcp_needed="assuming no" else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main() { FILE *fp; int result; errno = 0; fp = fopen ("conftest.c", "r"); if (!fp) return 0; /* error, assume not needed */ result = fflush (fp) == EOF && errno == 0; fclose (fp); return result; } _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 sed_cv_libcp_needed=no 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 ) sed_cv_libcp_needed=yes fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $sed_cv_libcp_needed" >&5 echo "${ECHO_T}$sed_cv_libcp_needed" >&6 if test "$sed_cv_libcp_needed" = yes; then LIBS="-lcP $LIBS" fi ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 echo $ECHO_N "checking for $ac_hdr that defines DIR... $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 /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then echo "$as_me:$LINENO: checking for library containing opendir" >&5 echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6 if test "${ac_cv_search_opendir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_opendir=no cat >conftest.$ac_ext <<_ACEOF /* 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 opendir (); int main () { opendir (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_search_opendir="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_opendir" = no; then for ac_lib in dir; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* 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 opendir (); int main () { opendir (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_search_opendir="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 echo "${ECHO_T}$ac_cv_search_opendir" >&6 if test "$ac_cv_search_opendir" != no; then test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS" fi else echo "$as_me:$LINENO: checking for library containing opendir" >&5 echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6 if test "${ac_cv_search_opendir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_opendir=no cat >conftest.$ac_ext <<_ACEOF /* 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 opendir (); int main () { opendir (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_search_opendir="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_opendir" = no; then for ac_lib in x; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* 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 opendir (); int main () { opendir (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_search_opendir="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 echo "${ECHO_T}$ac_cv_search_opendir" >&6 if test "$ac_cv_search_opendir" != no; then test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS" fi fi for ac_header in io.h limits.h locale.h stdarg.h alloca.h stddef.h errno.h \ wchar.h wctype.h sys/file.h mcheck.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 /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 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 /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 echo "$as_me:$LINENO: checking for ssize_t" >&5 echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6 if test "${ac_cv_type_ssize_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((ssize_t *) 0) return 0; if (sizeof (ssize_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_ssize_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_ssize_t=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_ssize_t" >&5 echo "${ECHO_T}$ac_cv_type_ssize_t" >&6 if test $ac_cv_type_ssize_t = yes; then : else cat >>confdefs.h <<_ACEOF #define ssize_t int _ACEOF fi echo "$as_me:$LINENO: checking for stdbool.h that conforms to C99" >&5 echo $ECHO_N "checking for stdbool.h that conforms to C99... $ECHO_C" >&6 if test "${ac_cv_header_stdbool_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #ifndef bool "error: bool is not defined" #endif #ifndef false "error: false is not defined" #endif #if false "error: false is not 0" #endif #ifndef true "error: false is not defined" #endif #if true != 1 "error: true is not 1" #endif #ifndef __bool_true_false_are_defined "error: __bool_true_false_are_defined is not defined" #endif struct s { _Bool s: 1; _Bool t; } s; char a[true == 1 ? 1 : -1]; char b[false == 0 ? 1 : -1]; char c[__bool_true_false_are_defined == 1 ? 1 : -1]; char d[(bool) -0.5 == true ? 1 : -1]; bool e = &s; char f[(_Bool) -0.0 == false ? 1 : -1]; char g[true]; char h[sizeof (_Bool)]; char i[sizeof s.t]; int main () { return !a + !b + !c + !d + !e + !f + !g + !h + !i; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_stdbool_h=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdbool_h=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_header_stdbool_h" >&5 echo "${ECHO_T}$ac_cv_header_stdbool_h" >&6 echo "$as_me:$LINENO: checking for _Bool" >&5 echo $ECHO_N "checking for _Bool... $ECHO_C" >&6 if test "${ac_cv_type__Bool+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((_Bool *) 0) return 0; if (sizeof (_Bool)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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__Bool=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type__Bool=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type__Bool" >&5 echo "${ECHO_T}$ac_cv_type__Bool" >&6 if test $ac_cv_type__Bool = yes; then cat >>confdefs.h <<_ACEOF #define HAVE__BOOL 1 _ACEOF fi if test $ac_cv_header_stdbool_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_STDBOOL_H 1 _ACEOF fi if test "$ac_cv_type__Bool" = no; then HAVE__BOOL=0 else HAVE__BOOL=1 fi if test "$ac_cv_header_stdbool_h" = no; then ac_config_files="$ac_config_files lib/stdbool.h:lib/stdbool_.h" fi # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo "$as_me:$LINENO: checking for working alloca.h" >&5 echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6 if test "${ac_cv_working_alloca_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { char *p = (char *) alloca (2 * sizeof (int)); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_working_alloca_h=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_working_alloca_h=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5 echo "${ECHO_T}$ac_cv_working_alloca_h" >&6 if test $ac_cv_working_alloca_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_ALLOCA_H 1 _ACEOF fi echo "$as_me:$LINENO: checking for alloca" >&5 echo $ECHO_N "checking for alloca... $ECHO_C" >&6 if test "${ac_cv_func_alloca_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __GNUC__ # define alloca __builtin_alloca #else # ifdef _MSC_VER # include # define alloca _alloca # else # if HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif # endif #endif int main () { char *p = (char *) alloca (1); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_alloca_works=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_alloca_works=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5 echo "${ECHO_T}$ac_cv_func_alloca_works" >&6 if test $ac_cv_func_alloca_works = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_ALLOCA 1 _ACEOF else # The SVR3 libPW and SVR4 libucb both contain incompatible functions # that cause trouble. Some versions do not even contain alloca or # contain a buggy version. If you still want to use their alloca, # use ar to extract alloca.o from them instead of compiling alloca.c. ALLOCA=alloca.$ac_objext cat >>confdefs.h <<\_ACEOF #define C_ALLOCA 1 _ACEOF echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5 echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6 if test "${ac_cv_os_cray+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if defined(CRAY) && ! defined(CRAY2) webecray #else wenotbecray #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "webecray" >/dev/null 2>&1; then ac_cv_os_cray=yes else ac_cv_os_cray=no fi rm -f conftest* fi echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5 echo "${ECHO_T}$ac_cv_os_cray" >&6 if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; 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 /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* 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 #undef $ac_func /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 CRAY_STACKSEG_END $ac_func _ACEOF break fi done fi echo "$as_me:$LINENO: checking stack direction for C alloca" >&5 echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6 if test "${ac_cv_c_stack_direction+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_c_stack_direction=0 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int find_stack_direction () { static char *addr = 0; auto char dummy; if (addr == 0) { addr = &dummy; return find_stack_direction (); } else return (&dummy > addr) ? 1 : -1; } int main () { exit (find_stack_direction () < 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 ac_cv_c_stack_direction=1 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_c_stack_direction=-1 fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5 echo "${ECHO_T}$ac_cv_c_stack_direction" >&6 cat >>confdefs.h <<_ACEOF #define STACK_DIRECTION $ac_cv_c_stack_direction _ACEOF fi for ac_func in vprintf 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 /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* 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 #undef $ac_func /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 echo "$as_me:$LINENO: checking for _doprnt" >&5 echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6 if test "${ac_cv_func__doprnt+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define _doprnt to an innocuous variant, in case declares _doprnt. For example, HP-UX 11i declares gettimeofday. */ #define _doprnt innocuous__doprnt /* System header to define __stub macros and hopefully few prototypes, which can conflict with char _doprnt (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef _doprnt /* 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 _doprnt (); /* 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__doprnt) || defined (__stub____doprnt) choke me #else char (*f) () = _doprnt; #endif #ifdef __cplusplus } #endif int main () { return f != _doprnt; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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__doprnt=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func__doprnt=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5 echo "${ECHO_T}$ac_cv_func__doprnt" >&6 if test $ac_cv_func__doprnt = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_DOPRNT 1 _ACEOF fi fi done am_getline_needs_run_time_check=no echo "$as_me:$LINENO: checking for getline" >&5 echo $ECHO_N "checking for getline... $ECHO_C" >&6 if test "${ac_cv_func_getline+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define getline to an innocuous variant, in case declares getline. For example, HP-UX 11i declares gettimeofday. */ #define getline innocuous_getline /* System header to define __stub macros and hopefully few prototypes, which can conflict with char getline (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef getline /* 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 getline (); /* 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_getline) || defined (__stub___getline) choke me #else char (*f) () = getline; #endif #ifdef __cplusplus } #endif int main () { return f != getline; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_getline=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_getline=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_getline" >&5 echo "${ECHO_T}$ac_cv_func_getline" >&6 if test $ac_cv_func_getline = yes; then am_getline_needs_run_time_check=yes else am_cv_func_working_getline=no fi if test $am_getline_needs_run_time_check = yes; then echo "$as_me:$LINENO: checking for working getline function" >&5 echo $ECHO_N "checking for working getline function... $ECHO_C" >&6 if test "${am_cv_func_working_getline+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else echo fooN |tr -d '\012'|tr N '\012' > conftest.data if test "$cross_compiling" = yes; then am_cv_func_working_getline=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include # include # include int main () { /* Based on a test program from Karl Heuer. */ char *line = NULL; size_t siz = 0; int len; FILE *in = fopen ("./conftest.data", "r"); if (!in) return 1; len = getline (&line, &siz, in); exit ((len == 4 && line && strcmp (line, "foo\n") == 0) ? 0 : 1); } _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 am_cv_func_working_getline=yes 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 ) am_cv_func_working_getline=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $am_cv_func_working_getline" >&5 echo "${ECHO_T}$am_cv_func_working_getline" >&6 fi if test $am_cv_func_working_getline = no; then case $LIBOBJS in "getline.$ac_objext" | \ *" getline.$ac_objext" | \ "getline.$ac_objext "* | \ *" getline.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS getline.$ac_objext" ;; esac fi echo "$as_me:$LINENO: checking for obstacks" >&5 echo $ECHO_N "checking for obstacks... $ECHO_C" >&6 if test "${ac_cv_func_obstack+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "obstack.h" int main () { struct obstack *mem; obstack_free(mem,(char *) 0) ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_obstack=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_obstack=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_obstack" >&5 echo "${ECHO_T}$ac_cv_func_obstack" >&6 if test $ac_cv_func_obstack = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_OBSTACK 1 _ACEOF else case $LIBOBJS in "obstack.$ac_objext" | \ *" obstack.$ac_objext" | \ "obstack.$ac_objext "* | \ *" obstack.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS obstack.$ac_objext" ;; esac fi echo "$as_me:$LINENO: checking whether mbrtowc and mbstate_t are properly declared" >&5 echo $ECHO_N "checking whether mbrtowc and mbstate_t are properly declared... $ECHO_C" >&6 if test "${ac_cv_func_mbrtowc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { mbstate_t state; return ! (sizeof state && mbrtowc); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_mbrtowc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_mbrtowc=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_mbrtowc" >&5 echo "${ECHO_T}$ac_cv_func_mbrtowc" >&6 if test $ac_cv_func_mbrtowc = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_MBRTOWC 1 _ACEOF fi echo "$as_me:$LINENO: checking for mbstate_t" >&5 echo $ECHO_N "checking for mbstate_t... $ECHO_C" >&6 if test "${ac_cv_type_mbstate_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default # include int main () { mbstate_t x; return sizeof x; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_mbstate_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_mbstate_t=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_mbstate_t" >&5 echo "${ECHO_T}$ac_cv_type_mbstate_t" >&6 if test $ac_cv_type_mbstate_t = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_MBSTATE_T 1 _ACEOF else cat >>confdefs.h <<\_ACEOF #define mbstate_t int _ACEOF fi for ac_func in strverscmp 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 /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* 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 #undef $ac_func /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 else case $LIBOBJS in "$ac_func.$ac_objext" | \ *" $ac_func.$ac_objext" | \ "$ac_func.$ac_objext "* | \ *" $ac_func.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;; esac fi done if test $ac_cv_func_strverscmp = no; then : fi for ac_func in memchr memcmp memmove strerror mkstemp 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 /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* 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 #undef $ac_func /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 else case $LIBOBJS in "$ac_func.$ac_objext" | \ *" $ac_func.$ac_objext" | \ "$ac_func.$ac_objext "* | \ *" $ac_func.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;; esac fi done for ac_func in isatty bcopy bzero isascii memcpy memset strchr strtoul popen \ pathconf isblank fchown fchmod setlocale wcrtomb wcscoll btowc 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 /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* 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 #undef $ac_func /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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-i18n or --disable-i18n was given. if test "${enable_i18n+set}" = set; then enableval="$enable_i18n" else enable_i18n=yes fi; if test "x$enable_i18n" = xno; then ac_cv_func_wcscoll=false fi # Check whether --with-included-regex or --without-included-regex was given. if test "${with_included_regex+set}" = set; then withval="$with_included_regex" else with_included_regex=yes fi; if test "x$with_included_regex" = xno; then for ac_header in regex.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 /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 /* 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 ac_cpp_err=$ac_cpp_err$ac_c_werror_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:$ac_c_preproc_warn_flag 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 compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; 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: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&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;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------ ## ## Report this to bonzini@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 re_search in -lregex" >&5 echo $ECHO_N "checking for re_search in -lregex... $ECHO_C" >&6 if test "${ac_cv_lib_regex_re_search+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lregex $LIBS" cat >conftest.$ac_ext <<_ACEOF /* 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 re_search (); int main () { re_search (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_regex_re_search=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_regex_re_search=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_regex_re_search" >&5 echo "${ECHO_T}$ac_cv_lib_regex_re_search" >&6 if test $ac_cv_lib_regex_re_search = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBREGEX 1 _ACEOF LIBS="-lregex $LIBS" fi echo "$as_me:$LINENO: checking for re_search" >&5 echo $ECHO_N "checking for re_search... $ECHO_C" >&6 if test "${ac_cv_func_re_search+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define re_search to an innocuous variant, in case declares re_search. For example, HP-UX 11i declares gettimeofday. */ #define re_search innocuous_re_search /* System header to define __stub macros and hopefully few prototypes, which can conflict with char re_search (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef re_search /* 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 re_search (); /* 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_re_search) || defined (__stub___re_search) choke me #else char (*f) () = re_search; #endif #ifdef __cplusplus } #endif int main () { return f != re_search; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_re_search=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_re_search=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_re_search" >&5 echo "${ECHO_T}$ac_cv_func_re_search" >&6 if test $ac_cv_header_regex_h = no || test $ac_cv_func_re_search = no; then { echo "$as_me:$LINENO: WARNING: GNU regex not found, falling back to the included version" >&5 echo "$as_me: WARNING: GNU regex not found, falling back to the included version" >&2;} with_included_regex=yes fi fi # Check whether --enable-regex-tests or --disable-regex-tests was given. if test "${enable_regex_tests+set}" = set; then enableval="$enable_regex_tests" if test "x$with_included_regex" = xno; then enable_regex_tests=no fi else enable_regex_tests=$with_included_regex fi; if test "x$enable_regex_tests" != xno; then TEST_REGEX_TRUE= TEST_REGEX_FALSE='#' else TEST_REGEX_TRUE='#' TEST_REGEX_FALSE= fi if test "x$with_included_regex" != xno; then ac_config_links="$ac_config_links lib/regex.h:lib/regex_.h" case $LIBOBJS in "regex.$ac_objext" | \ *" regex.$ac_objext" | \ "regex.$ac_objext "* | \ *" regex.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS regex.$ac_objext" ;; esac fi if test "x$enable_regex_tests" = xyes; then cat >>confdefs.h <<_ACEOF #define _REGEX_RE_COMP 1 _ACEOF fi # Check whether --enable-html or --disable-html was given. if test "${enable_html+set}" = set; then enableval="$enable_html" else enable_html=no fi; if test "x$enable_html" != xno; then BUILD_HTML_TRUE= BUILD_HTML_FALSE='#' else BUILD_HTML_TRUE='#' BUILD_HTML_FALSE= fi : ${TEXI2HTML=texi2html -monolithic} echo "$as_me:$LINENO: checking how to build HTML documentation" >&5 echo $ECHO_N "checking how to build HTML documentation... $ECHO_C" >&6 if eval $am_missing_run makeinfo --help 2>&1 | grep .-html > /dev/null; then echo "$as_me:$LINENO: result: with makeinfo" >&5 echo "${ECHO_T}with makeinfo" >&6 enable_html=makeinfo else if $TEXI2HTML --help 2>&1 | grep monolithic > /dev/null; then echo "$as_me:$LINENO: result: with texi2html" >&5 echo "${ECHO_T}with texi2html" >&6 enable_html=texi2html else echo "$as_me:$LINENO: result: not built" >&5 echo "${ECHO_T}not built" >&6 if test "x$enable_html" != xno; then { { echo "$as_me:$LINENO: error: cannot build HTML documentation" >&5 echo "$as_me: error: cannot build HTML documentation" >&2;} { (exit install makeinfo 4.0 or texi2html); exit install makeinfo 4.0 or texi2html; }; } fi enable_html=no fi fi if test "x$enable_html" = xmakeinfo; then MAKEINFO_HTML_TRUE= MAKEINFO_HTML_FALSE='#' else MAKEINFO_HTML_TRUE='#' MAKEINFO_HTML_FALSE= fi if test "x$enable_html" = xtexi2html; then TEXI2HTML_HTML_TRUE= TEXI2HTML_HTML_FALSE='#' else TEXI2HTML_HTML_TRUE='#' TEXI2HTML_HTML_FALSE= fi MKINSTALLDIRS="$mkdir_p" # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; 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_path_MSGFMT+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case "$MSGFMT" in /*) ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. ;; *) 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 if $ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_MSGFMT="$ac_dir/$ac_word" break fi fi done IFS="$ac_save_ifs" test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" ;; esac fi MSGFMT="$ac_cv_path_MSGFMT" if test "$MSGFMT" != ":"; then echo "$as_me:$LINENO: result: $MSGFMT" >&5 echo "${ECHO_T}$MSGFMT" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # Extract the first word of "gmsgfmt", so it can be a program name with args. set dummy gmsgfmt; 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_path_GMSGFMT+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $GMSGFMT in [\\/]* | ?:[\\/]*) ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. ;; *) 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_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" ;; esac fi GMSGFMT=$ac_cv_path_GMSGFMT if test -n "$GMSGFMT"; then echo "$as_me:$LINENO: result: $GMSGFMT" >&5 echo "${ECHO_T}$GMSGFMT" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; 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_path_XGETTEXT+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case "$XGETTEXT" in /*) ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. ;; *) 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 if $ac_dir/$ac_word --omit-header --copyright-holder= /dev/null >/dev/null 2>&1 && (if $ac_dir/$ac_word --omit-header --copyright-holder= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_XGETTEXT="$ac_dir/$ac_word" break fi fi done IFS="$ac_save_ifs" test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" ;; esac fi XGETTEXT="$ac_cv_path_XGETTEXT" if test "$XGETTEXT" != ":"; then echo "$as_me:$LINENO: result: $XGETTEXT" >&5 echo "${ECHO_T}$XGETTEXT" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f messages.po # Extract the first word of "msgmerge", so it can be a program name with args. set dummy msgmerge; 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_path_MSGMERGE+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case "$MSGMERGE" in /*) ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. ;; *) 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 if $ac_dir/$ac_word --update -q /dev/null /dev/null >/dev/null 2>&1; then ac_cv_path_MSGMERGE="$ac_dir/$ac_word" break fi fi done IFS="$ac_save_ifs" test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" ;; esac fi MSGMERGE="$ac_cv_path_MSGMERGE" if test "$MSGMERGE" != ":"; then echo "$as_me:$LINENO: result: $MSGMERGE" >&5 echo "${ECHO_T}$MSGMERGE" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test "$GMSGFMT" != ":"; then if $GMSGFMT --statistics /dev/null >/dev/null 2>&1 && (if $GMSGFMT --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then : ; else GMSGFMT=`echo "$GMSGFMT" | sed -e 's,^.*/,,'` echo "$as_me:$LINENO: result: found $GMSGFMT program is not GNU msgfmt; ignore it" >&5 echo "${ECHO_T}found $GMSGFMT program is not GNU msgfmt; ignore it" >&6 GMSGFMT=":" fi fi if test "$XGETTEXT" != ":"; then if $XGETTEXT --omit-header --copyright-holder= /dev/null >/dev/null 2>&1 && (if $XGETTEXT --omit-header --copyright-holder= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then : ; else echo "$as_me:$LINENO: result: found xgettext program is not GNU xgettext; ignore it" >&5 echo "${ECHO_T}found xgettext program is not GNU xgettext; ignore it" >&6 XGETTEXT=":" fi rm -f messages.po fi ac_config_commands="$ac_config_commands default-1" # 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/'` echo "$as_me:$LINENO: checking for inline" >&5 echo $ECHO_N "checking for inline... $ECHO_C" >&6 if test "${ac_cv_c_inline+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_inline=$ac_kw; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done fi echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 echo "${ECHO_T}$ac_cv_c_inline" >&6 case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac echo "$as_me:$LINENO: checking for off_t" >&5 echo $ECHO_N "checking for off_t... $ECHO_C" >&6 if test "${ac_cv_type_off_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((off_t *) 0) return 0; if (sizeof (off_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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_off_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_off_t=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5 echo "${ECHO_T}$ac_cv_type_off_t" >&6 if test $ac_cv_type_off_t = yes; then : else cat >>confdefs.h <<_ACEOF #define off_t long _ACEOF fi for ac_header in stdlib.h unistd.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 /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 /* 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 ac_cpp_err=$ac_cpp_err$ac_c_werror_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:$ac_c_preproc_warn_flag 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 compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; 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: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&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;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------ ## ## Report this to bonzini@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 for ac_func in getpagesize 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 /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* 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 #undef $ac_func /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 echo "$as_me:$LINENO: checking for working mmap" >&5 echo $ECHO_N "checking for working mmap... $ECHO_C" >&6 if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_mmap_fixed_mapped=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default /* malloc might have been renamed as rpl_malloc. */ #undef malloc /* Thanks to Mike Haertel and Jim Avera for this test. Here is a matrix of mmap possibilities: mmap private not fixed mmap private fixed at somewhere currently unmapped mmap private fixed at somewhere already mapped mmap shared not fixed mmap shared fixed at somewhere currently unmapped mmap shared fixed at somewhere already mapped For private mappings, we should verify that changes cannot be read() back from the file, nor mmap's back from the file at a different address. (There have been systems where private was not correctly implemented like the infamous i386 svr4.0, and systems where the VM page cache was not coherent with the file system buffer cache like early versions of FreeBSD and possibly contemporary NetBSD.) For shared mappings, we should conversely verify that changes get propagated back to all the places they're supposed to be. Grep wants private fixed already mapped. The main things grep needs to know about mmap are: * does it exist and is it safe to write into the mmap'd area * how to use it (BSD variants) */ #include #include #if !STDC_HEADERS && !HAVE_STDLIB_H char *malloc (); #endif /* This mess was copied from the GNU getpagesize.h. */ #if !HAVE_GETPAGESIZE /* Assume that all systems that can run configure have sys/param.h. */ # if !HAVE_SYS_PARAM_H # define HAVE_SYS_PARAM_H 1 # endif # ifdef _SC_PAGESIZE # define getpagesize() sysconf(_SC_PAGESIZE) # else /* no _SC_PAGESIZE */ # if HAVE_SYS_PARAM_H # include # ifdef EXEC_PAGESIZE # define getpagesize() EXEC_PAGESIZE # else /* no EXEC_PAGESIZE */ # ifdef NBPG # define getpagesize() NBPG * CLSIZE # ifndef CLSIZE # define CLSIZE 1 # endif /* no CLSIZE */ # else /* no NBPG */ # ifdef NBPC # define getpagesize() NBPC # else /* no NBPC */ # ifdef PAGESIZE # define getpagesize() PAGESIZE # endif /* PAGESIZE */ # endif /* no NBPC */ # endif /* no NBPG */ # endif /* no EXEC_PAGESIZE */ # else /* no HAVE_SYS_PARAM_H */ # define getpagesize() 8192 /* punt totally */ # endif /* no HAVE_SYS_PARAM_H */ # endif /* no _SC_PAGESIZE */ #endif /* no HAVE_GETPAGESIZE */ int main () { char *data, *data2, *data3; int i, pagesize; int fd; pagesize = getpagesize (); /* First, make a file with some known garbage in it. */ data = (char *) malloc (pagesize); if (!data) exit (1); for (i = 0; i < pagesize; ++i) *(data + i) = rand (); umask (0); fd = creat ("conftest.mmap", 0600); if (fd < 0) exit (1); if (write (fd, data, pagesize) != pagesize) exit (1); close (fd); /* Next, try to mmap the file at a fixed address which already has something else allocated at it. If we can, also make sure that we see the same garbage. */ fd = open ("conftest.mmap", O_RDWR); if (fd < 0) exit (1); data2 = (char *) malloc (2 * pagesize); if (!data2) exit (1); data2 += (pagesize - ((long) data2 & (pagesize - 1))) & (pagesize - 1); if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0L)) exit (1); for (i = 0; i < pagesize; ++i) if (*(data + i) != *(data2 + i)) exit (1); /* Finally, make sure that changes to the mapped area do not percolate back to the file as seen by read(). (This is a bug on some variants of i386 svr4.0.) */ for (i = 0; i < pagesize; ++i) *(data2 + i) = *(data2 + i) + 1; data3 = (char *) malloc (pagesize); if (!data3) exit (1); if (read (fd, data3, pagesize) != pagesize) exit (1); for (i = 0; i < pagesize; ++i) if (*(data + i) != *(data3 + i)) exit (1); close (fd); 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 ac_cv_func_mmap_fixed_mapped=yes 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_func_mmap_fixed_mapped=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5 echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6 if test $ac_cv_func_mmap_fixed_mapped = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_MMAP 1 _ACEOF fi rm -f conftest.mmap echo "$as_me:$LINENO: checking whether we are using the GNU C Library 2.1 or newer" >&5 echo $ECHO_N "checking whether we are using the GNU C Library 2.1 or newer... $ECHO_C" >&6 if test "${ac_cv_gnu_library_2_1+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #ifdef __GNU_LIBRARY__ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) Lucky GNU user #endif #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "Lucky GNU user" >/dev/null 2>&1; then ac_cv_gnu_library_2_1=yes else ac_cv_gnu_library_2_1=no fi rm -f conftest* fi echo "$as_me:$LINENO: result: $ac_cv_gnu_library_2_1" >&5 echo "${ECHO_T}$ac_cv_gnu_library_2_1" >&6 GLIBC21="$ac_cv_gnu_library_2_1" if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" # 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 "${acl_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 acl_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 "$acl_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 acl_cv_path_LD="$LD" # Let the user override the test with a path. fi fi LD="$acl_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 "${acl_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 acl_cv_prog_gnu_ld=yes else acl_cv_prog_gnu_ld=no fi fi echo "$as_me:$LINENO: result: $acl_cv_prog_gnu_ld" >&5 echo "${ECHO_T}$acl_cv_prog_gnu_ld" >&6 with_gnu_ld=$acl_cv_prog_gnu_ld echo "$as_me:$LINENO: checking for shared library run path origin" >&5 echo $ECHO_N "checking for shared library run path origin... $ECHO_C" >&6 if test "${acl_cv_rpath+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done fi echo "$as_me:$LINENO: result: $acl_cv_rpath" >&5 echo "${ECHO_T}$acl_cv_rpath" >&6 wl="$acl_cv_wl" libext="$acl_cv_libext" shlibext="$acl_cv_shlibext" hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" hardcode_direct="$acl_cv_hardcode_direct" hardcode_minus_L="$acl_cv_hardcode_minus_L" sys_lib_search_path_spec="$acl_cv_sys_lib_search_path_spec" sys_lib_dlsearch_path_spec="$acl_cv_sys_lib_dlsearch_path_spec" use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libiconv-prefix or --without-libiconv-prefix was given. if test "${with_libiconv_prefix+set}" = set; then withval="$with_libiconv_prefix" if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/lib" fi fi fi; LIBICONV= LTLIBICONV= INCICONV= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='iconv ' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" else : fi else found_dir= found_la= found_so= found_a= if test $use_additional = yes; then if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then found_dir="$additional_libdir" found_so="$additional_libdir/lib$name.$shlibext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi else if test -f "$additional_libdir/lib$name.$libext"; then found_dir="$additional_libdir" found_a="$additional_libdir/lib$name.$libext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then found_dir="$dir" found_so="$dir/lib$name.$shlibext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi else if test -f "$dir/lib$name.$libext"; then found_dir="$dir" found_a="$dir/lib$name.$libext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then if test "X$found_dir" = "X/usr/lib"; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi if test "$hardcode_direct" = yes; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else haveit= for x in $LDFLAGS $LIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" fi if test "$hardcode_minus_L" != no; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" else LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" fi fi additional_includedir= case "$found_dir" in */lib | */lib/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/lib"; then haveit= if test "X$additional_libdir" = "X/usr/local/lib"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" fi fi fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" ;; esac done fi else LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$hardcode_libdir_separator"; then alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" else for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then for found_dir in $ltrpathdirs; do LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" done fi am_save_CPPFLAGS="$CPPFLAGS" for element in $INCICONV; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done echo "$as_me:$LINENO: checking for iconv" >&5 echo $ECHO_N "checking for iconv... $ECHO_C" >&6 if test "${am_cv_func_iconv+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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 am_cv_func_iconv=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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 am_cv_lib_iconv=yes am_cv_func_iconv=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$am_save_LIBS" fi fi echo "$as_me:$LINENO: result: $am_cv_func_iconv" >&5 echo "${ECHO_T}$am_cv_func_iconv" >&6 if test "$am_cv_func_iconv" = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_ICONV 1 _ACEOF fi if test "$am_cv_lib_iconv" = yes; then echo "$as_me:$LINENO: checking how to link with libiconv" >&5 echo $ECHO_N "checking how to link with libiconv... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $LIBICONV" >&5 echo "${ECHO_T}$LIBICONV" >&6 else CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi for ac_header in argz.h limits.h locale.h nl_types.h malloc.h stddef.h \ stdlib.h string.h unistd.h sys/param.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 /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 /* 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 ac_cpp_err=$ac_cpp_err$ac_c_werror_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:$ac_c_preproc_warn_flag 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 compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; 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: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&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;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------ ## ## Report this to bonzini@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 for ac_func in feof_unlocked fgets_unlocked getc_unlocked getcwd getegid \ geteuid getgid getuid mempcpy munmap putenv setenv setlocale stpcpy \ strcasecmp strdup strtoul tsearch __argz_count __argz_stringify __argz_next 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 /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* 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 #undef $ac_func /* 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>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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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.err 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 if test "$am_cv_func_iconv" = yes; then echo "$as_me:$LINENO: checking for iconv declaration" >&5 echo $ECHO_N "checking for iconv declaration... $ECHO_C" >&6 if test "${am_cv_proto_iconv+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include extern #ifdef __cplusplus "C" #endif #if defined(__STDC__) || defined(__cplusplus) size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); #else size_t iconv(); #endif int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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 am_cv_proto_iconv_arg1="" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 am_cv_proto_iconv_arg1="const" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);" fi am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` echo "$as_me:$LINENO: result: ${ac_t:- }$am_cv_proto_iconv" >&5 echo "${ECHO_T}${ac_t:- }$am_cv_proto_iconv" >&6 cat >>confdefs.h <<_ACEOF #define ICONV_CONST $am_cv_proto_iconv_arg1 _ACEOF fi echo "$as_me:$LINENO: checking for nl_langinfo and CODESET" >&5 echo $ECHO_N "checking for nl_langinfo and CODESET... $ECHO_C" >&6 if test "${am_cv_langinfo_codeset+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { char* cs = nl_langinfo(CODESET); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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 am_cv_langinfo_codeset=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 am_cv_langinfo_codeset=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $am_cv_langinfo_codeset" >&5 echo "${ECHO_T}$am_cv_langinfo_codeset" >&6 if test $am_cv_langinfo_codeset = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_LANGINFO_CODESET 1 _ACEOF fi if test $ac_cv_header_locale_h = yes; then echo "$as_me:$LINENO: checking for LC_MESSAGES" >&5 echo $ECHO_N "checking for LC_MESSAGES... $ECHO_C" >&6 if test "${am_cv_val_LC_MESSAGES+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { return LC_MESSAGES ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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 am_cv_val_LC_MESSAGES=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 am_cv_val_LC_MESSAGES=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $am_cv_val_LC_MESSAGES" >&5 echo "${ECHO_T}$am_cv_val_LC_MESSAGES" >&6 if test $am_cv_val_LC_MESSAGES = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_LC_MESSAGES 1 _ACEOF fi fi for ac_prog in bison 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_INTLBISON+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$INTLBISON"; then ac_cv_prog_INTLBISON="$INTLBISON" # 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_INTLBISON="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi INTLBISON=$ac_cv_prog_INTLBISON if test -n "$INTLBISON"; then echo "$as_me:$LINENO: result: $INTLBISON" >&5 echo "${ECHO_T}$INTLBISON" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$INTLBISON" && break done if test -z "$INTLBISON"; then ac_verc_fail=yes else echo "$as_me:$LINENO: checking version of bison" >&5 echo $ECHO_N "checking version of bison... $ECHO_C" >&6 ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` case $ac_prog_version in '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; esac echo "$as_me:$LINENO: result: $ac_prog_version" >&5 echo "${ECHO_T}$ac_prog_version" >&6 fi if test $ac_verc_fail = yes; then INTLBISON=: fi echo "$as_me:$LINENO: checking whether NLS is requested" >&5 echo $ECHO_N "checking whether NLS is requested... $ECHO_C" >&6 # Check whether --enable-nls or --disable-nls was given. if test "${enable_nls+set}" = set; then enableval="$enable_nls" USE_NLS=$enableval else USE_NLS=yes fi; echo "$as_me:$LINENO: result: $USE_NLS" >&5 echo "${ECHO_T}$USE_NLS" >&6 BUILD_INCLUDED_LIBINTL=no USE_INCLUDED_LIBINTL=no LIBINTL= LTLIBINTL= POSUB= if test "$USE_NLS" = "yes"; then gt_use_preinstalled_gnugettext=no echo "$as_me:$LINENO: checking whether included gettext is requested" >&5 echo $ECHO_N "checking whether included gettext is requested... $ECHO_C" >&6 # Check whether --with-included-gettext or --without-included-gettext was given. if test "${with_included_gettext+set}" = set; then withval="$with_included_gettext" nls_cv_force_use_gnu_gettext=$withval else nls_cv_force_use_gnu_gettext=no fi; echo "$as_me:$LINENO: result: $nls_cv_force_use_gnu_gettext" >&5 echo "${ECHO_T}$nls_cv_force_use_gnu_gettext" >&6 nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" if test "$nls_cv_force_use_gnu_gettext" != "yes"; then echo "$as_me:$LINENO: checking for GNU gettext in libc" >&5 echo $ECHO_N "checking for GNU gettext in libc... $ECHO_C" >&6 if test "${gt_cv_func_gnugettext2_libc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include extern int _nl_msg_cat_cntr; int main () { bindtextdomain ("", ""); return (int) gettext ("") + (int) ngettext ("", "", 0) + _nl_msg_cat_cntr ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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 gt_cv_func_gnugettext2_libc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 gt_cv_func_gnugettext2_libc=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $gt_cv_func_gnugettext2_libc" >&5 echo "${ECHO_T}$gt_cv_func_gnugettext2_libc" >&6 if test "$gt_cv_func_gnugettext2_libc" != "yes"; then use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libintl-prefix or --without-libintl-prefix was given. if test "${with_libintl_prefix+set}" = set; then withval="$with_libintl_prefix" if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/lib" fi fi fi; LIBINTL= LTLIBINTL= INCINTL= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='intl ' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIBINTL="${LIBINTL}${LIBINTL:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$value" else : fi else found_dir= found_la= found_so= found_a= if test $use_additional = yes; then if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then found_dir="$additional_libdir" found_so="$additional_libdir/lib$name.$shlibext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi else if test -f "$additional_libdir/lib$name.$libext"; then found_dir="$additional_libdir" found_a="$additional_libdir/lib$name.$libext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then found_dir="$dir" found_so="$dir/lib$name.$shlibext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi else if test -f "$dir/lib$name.$libext"; then found_dir="$dir" found_a="$dir/lib$name.$libext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then if test "X$found_dir" = "X/usr/lib"; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi if test "$hardcode_direct" = yes; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else haveit= for x in $LDFLAGS $LIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir" fi if test "$hardcode_minus_L" != no; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_a" else LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir -l$name" fi fi additional_includedir= case "$found_dir" in */lib | */lib/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/lib"; then haveit= if test "X$additional_libdir" = "X/usr/local/lib"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir" fi fi fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBINTL="${LIBINTL}${LIBINTL:+ }$dep" LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep" ;; esac done fi else LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$hardcode_libdir_separator"; then alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" else for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then for found_dir in $ltrpathdirs; do LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-R$found_dir" done fi echo "$as_me:$LINENO: checking for GNU gettext in libintl" >&5 echo $ECHO_N "checking for GNU gettext in libintl... $ECHO_C" >&6 if test "${gt_cv_func_gnugettext2_libintl+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $INCINTL" gt_save_LIBS="$LIBS" LIBS="$LIBS $LIBINTL" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include extern int _nl_msg_cat_cntr; int main () { bindtextdomain ("", ""); return (int) gettext ("") + (int) ngettext ("", "", 0) + _nl_msg_cat_cntr ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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 gt_cv_func_gnugettext2_libintl=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 gt_cv_func_gnugettext2_libintl=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$gt_cv_func_gnugettext2_libintl" != yes && test -n "$LIBICONV"; then LIBS="$LIBS $LIBICONV" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include extern int _nl_msg_cat_cntr; int main () { bindtextdomain ("", ""); return (int) gettext ("") + (int) ngettext ("", "", 0) + _nl_msg_cat_cntr ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 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); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (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); }; } && { 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 LIBINTL="$LIBINTL $LIBICONV" LTLIBINTL="$LTLIBINTL $LTLIBICONV" gt_cv_func_gnugettext2_libintl=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS" fi echo "$as_me:$LINENO: result: $gt_cv_func_gnugettext2_libintl" >&5 echo "${ECHO_T}$gt_cv_func_gnugettext2_libintl" >&6 fi if test "$gt_cv_func_gnugettext2_libc" = "yes" \ || { test "$gt_cv_func_gnugettext2_libintl" = "yes" \ && test "$PACKAGE" != gettext; }; then gt_use_preinstalled_gnugettext=yes fi if test "$gt_use_preinstalled_gnugettext" != "yes"; then nls_cv_use_gnu_gettext=yes fi fi if test "$nls_cv_use_gnu_gettext" = "yes"; then INTLOBJS="\$(GETTOBJS)" BUILD_INCLUDED_LIBINTL=yes USE_INCLUDED_LIBINTL=yes LIBINTL="../intl/libintl.a $LIBICONV" LTLIBINTL="../intl/libintl.a $LTLIBICONV" LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then CATOBJEXT=.gmo fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then cat >>confdefs.h <<\_ACEOF #define ENABLE_NLS 1 _ACEOF else USE_NLS=no fi fi if test "$USE_NLS" = "yes"; then if test "$gt_use_preinstalled_gnugettext" = "yes"; then if test "$gt_cv_func_gnugettext2_libintl" = "yes"; then echo "$as_me:$LINENO: checking how to link with libintl" >&5 echo $ECHO_N "checking how to link with libintl... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $LIBINTL" >&5 echo "${ECHO_T}$LIBINTL" >&6 for element in $INCINTL; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done fi cat >>confdefs.h <<\_ACEOF #define HAVE_GETTEXT 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define HAVE_DCGETTEXT 1 _ACEOF fi POSUB=po fi if test "$PACKAGE" = gettext; then BUILD_INCLUDED_LIBINTL=yes fi nls_cv_header_intl= nls_cv_header_libgt= DATADIRNAME=share INSTOBJEXT=.mo GENCAT=gencat INTL_LIBTOOL_SUFFIX_PREFIX= INTLLIBS="$LIBINTL" ac_config_commands="$ac_config_commands gettext-fix" ac_config_files="$ac_config_files bootstrap.sh" ac_config_files="$ac_config_files Makefile doc/Makefile lib/Makefile sed/Makefile testsuite/Makefile po/Makefile.in intl/Makefile" 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 if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${TEST_REGEX_TRUE}" && test -z "${TEST_REGEX_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"TEST_REGEX\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"TEST_REGEX\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${BUILD_HTML_TRUE}" && test -z "${BUILD_HTML_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"BUILD_HTML\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"BUILD_HTML\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${MAKEINFO_HTML_TRUE}" && test -z "${MAKEINFO_HTML_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"MAKEINFO_HTML\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"MAKEINFO_HTML\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${TEXI2HTML_HTML_TRUE}" && test -z "${TEXI2HTML_HTML_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"TEXI2HTML_HTML\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"TEXI2HTML_HTML\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi : ${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 DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/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 -z "`(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 test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # 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 sed $as_me 4.1.5, which was generated by GNU Autoconf 2.59. 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 links: $config_links Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ sed config.status 4.1.5 configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2003 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 # # INIT-COMMANDS section. # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # Capture the value of obsolete $ALL_LINGUAS because we need it to compute # POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES, CATALOGS. But hide it # from automake. eval 'ALL_LINGUAS''="$ALL_LINGUAS"' # Capture the value of LINGUAS because we need it to compute CATALOGS. LINGUAS="${LINGUAS-%UNSET%}" install_sh="$install_sh" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "lib/stdbool.h" ) CONFIG_FILES="$CONFIG_FILES lib/stdbool.h:lib/stdbool_.h" ;; "bootstrap.sh" ) CONFIG_FILES="$CONFIG_FILES bootstrap.sh" ;; "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; "sed/Makefile" ) CONFIG_FILES="$CONFIG_FILES sed/Makefile" ;; "testsuite/Makefile" ) CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;; "po/Makefile.in" ) CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; "intl/Makefile" ) CONFIG_FILES="$CONFIG_FILES intl/Makefile" ;; "lib/regex.h" ) CONFIG_LINKS="$CONFIG_LINKS lib/regex.h:lib/regex_.h" ;; "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; "gettext-fix" ) CONFIG_COMMANDS="$CONFIG_COMMANDS gettext-fix" ;; "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h:config_h.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_LINKS+set}" = set || CONFIG_LINKS=$config_links 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,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t s,@CYGPATH_W@,$CYGPATH_W,;t t s,@PACKAGE@,$PACKAGE,;t t s,@VERSION@,$VERSION,;t t s,@ACLOCAL@,$ACLOCAL,;t t s,@AUTOCONF@,$AUTOCONF,;t t s,@AUTOMAKE@,$AUTOMAKE,;t t s,@AUTOHEADER@,$AUTOHEADER,;t t s,@MAKEINFO@,$MAKEINFO,;t t s,@install_sh@,$install_sh,;t t s,@STRIP@,$STRIP,;t t s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t s,@mkdir_p@,$mkdir_p,;t t s,@AWK@,$AWK,;t t s,@SET_MAKE@,$SET_MAKE,;t t s,@am__leading_dot@,$am__leading_dot,;t t s,@AMTAR@,$AMTAR,;t t s,@am__tar@,$am__tar,;t t s,@am__untar@,$am__untar,;t t s,@SED_FEATURE_VERSION@,$SED_FEATURE_VERSION,;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,@DEPDIR@,$DEPDIR,;t t s,@am__include@,$am__include,;t t s,@am__quote@,$am__quote,;t t s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t s,@CCDEPMODE@,$CCDEPMODE,;t t s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t s,@RANLIB@,$RANLIB,;t t s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t s,@CPP@,$CPP,;t t s,@EGREP@,$EGREP,;t t s,@HAVE__BOOL@,$HAVE__BOOL,;t t s,@ALLOCA@,$ALLOCA,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@TEST_REGEX_TRUE@,$TEST_REGEX_TRUE,;t t s,@TEST_REGEX_FALSE@,$TEST_REGEX_FALSE,;t t s,@BUILD_HTML_TRUE@,$BUILD_HTML_TRUE,;t t s,@BUILD_HTML_FALSE@,$BUILD_HTML_FALSE,;t t s,@TEXI2HTML@,$TEXI2HTML,;t t s,@MAKEINFO_HTML_TRUE@,$MAKEINFO_HTML_TRUE,;t t s,@MAKEINFO_HTML_FALSE@,$MAKEINFO_HTML_FALSE,;t t s,@TEXI2HTML_HTML_TRUE@,$TEXI2HTML_HTML_TRUE,;t t s,@TEXI2HTML_HTML_FALSE@,$TEXI2HTML_HTML_FALSE,;t t s,@MKINSTALLDIRS@,$MKINSTALLDIRS,;t t s,@MSGFMT@,$MSGFMT,;t t s,@GMSGFMT@,$GMSGFMT,;t t s,@XGETTEXT@,$XGETTEXT,;t t s,@MSGMERGE@,$MSGMERGE,;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,@GLIBC21@,$GLIBC21,;t t s,@LIBICONV@,$LIBICONV,;t t s,@LTLIBICONV@,$LTLIBICONV,;t t s,@INTLBISON@,$INTLBISON,;t t s,@USE_NLS@,$USE_NLS,;t t s,@BUILD_INCLUDED_LIBINTL@,$BUILD_INCLUDED_LIBINTL,;t t s,@USE_INCLUDED_LIBINTL@,$USE_INCLUDED_LIBINTL,;t t s,@CATOBJEXT@,$CATOBJEXT,;t t s,@INTLOBJS@,$INTLOBJS,;t t s,@DATADIRNAME@,$DATADIRNAME,;t t s,@INSTOBJEXT@,$INSTOBJEXT,;t t s,@GENCAT@,$GENCAT,;t t s,@INTL_LIBTOOL_SUFFIX_PREFIX@,$INTL_LIBTOOL_SUFFIX_PREFIX,;t t s,@INTLLIBS@,$INTLLIBS,;t t s,@LIBINTL@,$LIBINTL,;t t s,@LTLIBINTL@,$LTLIBINTL,;t t s,@POSUB@,$POSUB,;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 # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac 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 # Run the commands associated with the file. case $ac_file in bootstrap.sh ) chmod +x bootstrap.sh ;; esac 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; }; } # Do quote $f, to prevent DOS paths from being IFS'd. 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 # Compute $ac_file's index in $config_headers. _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $ac_file | $ac_file:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $ac_file" >`(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'`/stamp-h$_am_stamp_count done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_LINKS section. # for ac_file in : $CONFIG_LINKS; do test "x$ac_file" = x: && continue ac_dest=`echo "$ac_file" | sed 's,:.*,,'` ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` { echo "$as_me:$LINENO: linking $srcdir/$ac_source to $ac_dest" >&5 echo "$as_me: linking $srcdir/$ac_source to $ac_dest" >&6;} if test ! -r $srcdir/$ac_source; then { { echo "$as_me:$LINENO: error: $srcdir/$ac_source: file not found" >&5 echo "$as_me: error: $srcdir/$ac_source: file not found" >&2;} { (exit 1); exit 1; }; } fi rm -f $ac_dest # Make relative symlinks. ac_dest_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'` { if $as_mkdir_p; then mkdir -p "$ac_dest_dir" else as_dir="$ac_dest_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_dest_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dest_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dest_dir" != .; then ac_dir_suffix=/`echo "$ac_dest_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 # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dest_dir";; *) case "$ac_dest_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dest_dir";; *) ac_abs_builddir=`pwd`/"$ac_dest_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac case $srcdir in [\\/$]* | ?:[\\/]* ) ac_rel_source=$srcdir/$ac_source ;; *) ac_rel_source=$ac_top_builddir$srcdir/$ac_source ;; esac # Try a symlink, then a hard link, then a copy. ln -s $ac_rel_source $ac_dest 2>/dev/null || ln $srcdir/$ac_source $ac_dest 2>/dev/null || cp -p $srcdir/$ac_source $ac_dest || { { echo "$as_me:$LINENO: error: cannot link or copy $srcdir/$ac_source to $ac_dest" >&5 echo "$as_me: error: cannot link or copy $srcdir/$ac_source to $ac_dest" >&2;} { (exit 1); exit 1; }; } 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'` { 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 # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 echo "$as_me: executing $ac_dest commands" >&6;} case $ac_dest in depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`(dirname "$mf") 2>/dev/null || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`(dirname "$file") 2>/dev/null || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$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 $dirpart/$fdir else as_dir=$dirpart/$fdir 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 $dirpart/$fdir" >&5 echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} { (exit 1); exit 1; }; }; } # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ;; default-1 ) for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" case "$ac_file" in *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; esac # PO directories have a Makefile.in generated from Makefile.in.in. case "$ac_file" in */Makefile.in) # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" # ALL_LINGUAS, POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES depend # on $ac_dir but don't depend on user-specified configuration # parameters. if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then # The LINGUAS file contains the set of available languages. if test -n "$ALL_LINGUAS"; then test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" "$ac_given_srcdir/$ac_dir/LINGUAS"` # Hide the ALL_LINGUAS assigment from automake. eval 'ALL_LINGUAS''=$ALL_LINGUAS_' fi case "$ac_given_srcdir" in .) srcdirpre= ;; *) srcdirpre='$(srcdir)/' ;; esac POFILES= GMOFILES= UPDATEPOFILES= DUMMYPOFILES= for lang in $ALL_LINGUAS; do POFILES="$POFILES $srcdirpre$lang.po" GMOFILES="$GMOFILES $srcdirpre$lang.gmo" UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" DUMMYPOFILES="$DUMMYPOFILES $lang.nop" done # CATALOGS depends on both $ac_dir and the user's LINGUAS # environment variable. INST_LINGUAS= if test -n "$ALL_LINGUAS"; then for presentlang in $ALL_LINGUAS; do useit=no if test "%UNSET%" != "$LINGUAS"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then INST_LINGUAS="$INST_LINGUAS $presentlang" fi done fi CATALOGS= if test -n "$INST_LINGUAS"; then for lang in $INST_LINGUAS; do CATALOGS="$CATALOGS $lang.gmo" done fi test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do if test -f "$f"; then case "$f" in *.orig | *.bak | *~) ;; *) cat "$f" >> "$ac_dir/Makefile" ;; esac fi done fi ;; esac done ;; gettext-fix ) sed -e '/^mkinstalldirs *=/a\' \ -e "install_sh=$install_sh" \ -e 's/^mkinstalldirs *=.*/mkinstalldirs=$(MKINSTALLDIRS)/' \ intl/Makefile > intl/Makefile.tmp mv intl/Makefile.tmp intl/Makefile sed -e '/^mkinstalldirs *=/a\' \ -e "install_sh=$install_sh" \ -e 's/^mkinstalldirs *=.*/mkinstalldirs=$(MKINSTALLDIRS)/' \ po/Makefile > po/Makefile.tmp mv po/Makefile.tmp po/Makefile ;; 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 kbuild-3686/src/oldsed/README0000664000175000017500000000067715053010105015635 0ustar locutuslocutusThis is the GNU implementation of sed, the Unix stream editor. See the NEWS file for a brief summary and the ChangeLog for more detailed descriptions of changes. See the file INSTALL for generic compilation and installation instructions. See the file BUGS for instructions about reporting bugs. The file README.boot gives instructions for making a "bootstrap" version of sed on systems which lack any pre-existing and working version of sed. kbuild-3686/src/oldsed/config.h.solaris0000664000175000017500000002442315053010105020041 0ustar locutuslocutus/* config.h. Generated by configure. */ /* config_h.in. Generated from configure.ac by autoheader. */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if translation of program messages to the user's native language is requested. */ /* #undef ENABLE_NLS */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ #define HAVE_ALLOCA_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_ARGZ_H */ /* Define to 1 if you have the `bcopy' function. */ #define HAVE_BCOPY 1 /* Define to 1 if you have the `btowc' function. */ #define HAVE_BTOWC 1 /* Define to 1 if you have the `bzero' function. */ #define HAVE_BZERO 1 /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* #undef HAVE_DCGETTEXT */ /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #define HAVE_DOPRNT 1 /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H 1 /* Define to 1 if you have the `fchmod' function. */ #define HAVE_FCHMOD 1 /* Define to 1 if you have the `fchown' function. */ #define HAVE_FCHOWN 1 /* Define to 1 if you have the `feof_unlocked' function. */ /* #undef HAVE_FEOF_UNLOCKED */ /* Define to 1 if you have the `fgets_unlocked' function. */ /* #undef HAVE_FGETS_UNLOCKED */ /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getc_unlocked' function. */ #define HAVE_GETC_UNLOCKED 1 /* Define to 1 if you have the `getegid' function. */ #define HAVE_GETEGID 1 /* Define to 1 if you have the `geteuid' function. */ #define HAVE_GETEUID 1 /* Define to 1 if you have the `getgid' function. */ #define HAVE_GETGID 1 /* Define to 1 if you have the `getpagesize' function. */ #define HAVE_GETPAGESIZE 1 /* Define if the GNU gettext() function is already present or preinstalled. */ /* #undef HAVE_GETTEXT */ /* Define to 1 if you have the `getuid' function. */ #define HAVE_GETUID 1 /* Define if you have the iconv() function. */ #define HAVE_ICONV 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_IO_H */ /* Define to 1 if you have the `isascii' function. */ #define HAVE_ISASCII 1 /* Define to 1 if you have the `isatty' function. */ #define HAVE_ISATTY 1 /* Define to 1 if you have the `isblank' function. */ #define HAVE_ISBLANK 1 /* Define if you have and nl_langinfo(CODESET). */ #define HAVE_LANGINFO_CODESET 1 /* Define if your file defines LC_MESSAGES. */ #define HAVE_LC_MESSAGES 1 /* Define to 1 if you have the `regex' library (-lregex). */ /* #undef HAVE_LIBREGEX */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you support file names longer than 14 characters. */ #define HAVE_LONG_FILE_NAMES 1 /* Define to 1 if you have the header file. */ #define HAVE_MALLOC_H 1 /* Define to 1 if mbrtowc and mbstate_t are properly declared. */ #define HAVE_MBRTOWC 1 /* Define to 1 if declares mbstate_t. */ #define HAVE_MBSTATE_T 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MCHECK_H */ /* Define to 1 if you have the `memchr' function. */ #define HAVE_MEMCHR 1 /* Define to 1 if you have the `memcmp' function. */ #define HAVE_MEMCMP 1 /* Define to 1 if you have the `memcpy' function. */ #define HAVE_MEMCPY 1 /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mempcpy' function. */ /* #undef HAVE_MEMPCPY */ /* Define to 1 if you have the `memset' function. */ #define HAVE_MEMSET 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have a working `mmap' system call. */ #define HAVE_MMAP 1 /* Define to 1 if you have the `munmap' function. */ #define HAVE_MUNMAP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_NL_TYPES_H 1 /* Define to 1 if libc includes obstacks. */ /* #undef HAVE_OBSTACK */ /* Define to 1 if you have the `pathconf' function. */ #define HAVE_PATHCONF 1 /* Define to 1 if you have the `popen' function. */ #define HAVE_POPEN 1 /* Define to 1 if you have the `putenv' function. */ #define HAVE_PUTENV 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_REGEX_H */ /* Define to 1 if you have the `setenv' function. */ #define HAVE_SETENV 1 /* Define to 1 if you have the `setlocale' function. */ #define HAVE_SETLOCALE 1 /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if stdbool.h conforms to C99. */ #define HAVE_STDBOOL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `stpcpy' function. */ /* #undef HAVE_STPCPY */ /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strtoul' function. */ #define HAVE_STRTOUL 1 /* Define to 1 if you have the `strverscmp' function. */ /* #undef HAVE_STRVERSCMP */ /* 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. */ #define HAVE_SYS_FILE_H 1 /* 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. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the `tsearch' function. */ #define HAVE_TSEARCH 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_WCHAR_H 1 /* Define to 1 if you have the `wcrtomb' function. */ #define HAVE_WCRTOMB 1 /* Define to 1 if you have the `wcscoll' function. */ #define HAVE_WCSCOLL 1 /* Define to 1 if you have the header file. */ #define HAVE_WCTYPE_H 1 /* Define to 1 if the system has the type `_Bool'. */ #define HAVE__BOOL 1 /* Define to 1 if you have the `__argz_count' function. */ /* #undef HAVE___ARGZ_COUNT */ /* Define to 1 if you have the `__argz_next' function. */ /* #undef HAVE___ARGZ_NEXT */ /* Define to 1 if you have the `__argz_stringify' function. */ /* #undef HAVE___ARGZ_STRINGIFY */ /* Define as const if the declaration of iconv() needs const. */ #define ICONV_CONST const /* Name of package */ #define PACKAGE "sed" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bonzini@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "sed" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "sed 4.1.5" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "sed" /* Define to the version of this package. */ #define PACKAGE_VERSION "4.1.5" /* Define to the version of GNU sed whose features are supported by this sed. */ #define SED_FEATURE_VERSION "4.1" /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ #define VERSION "4.1.5" /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* # undef _ALL_SOURCE */ #endif /* Number of bits in a file offset, on hosts where this is settable. */ #define _FILE_OFFSET_BITS 64 /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Include BSD functions in regex, used by the testsuite */ #define _REGEX_RE_COMP 1 /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to a type if does not define. */ /* #undef mbstate_t */ /* Define to `long' if does not define. */ /* #undef off_t */ /* Define to `unsigned' if does not define. */ /* #undef size_t */ /* Define to `int' if does not define. */ /* #undef ssize_t */ kbuild-3686/src/oldsed/lib/0000775000175000017500000000000015053010105015511 5ustar locutuslocutuskbuild-3686/src/oldsed/lib/utils.h0000664000175000017500000000367115053010105017031 0ustar locutuslocutus/* Functions from hack's utils library. Copyright (C) 1989, 1990, 1991, 1998, 1999, 2003 Free Software Foundation, Inc. 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, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "basicdefs.h" void panic P_((const char *str, ...)); FILE *ck_fopen P_((const char *name, const char *mode, bool fail)); void ck_fwrite P_((const VOID *ptr, size_t size, size_t nmemb, FILE *stream)); size_t ck_fread P_((VOID *ptr, size_t size, size_t nmemb, FILE *stream)); void ck_fflush P_((FILE *stream)); void ck_fclose P_((FILE *stream)); size_t ck_getline P_((char **text, size_t *buflen, FILE *stream)); FILE * ck_mkstemp P_((char **p_filename, char *tmpdir, char *base)); void ck_rename P_((const char *from, const char *to, const char *unlink_if_fail)); VOID *ck_malloc P_((size_t size)); VOID *xmalloc P_((size_t size)); VOID *ck_realloc P_((VOID *ptr, size_t size)); char *ck_strdup P_((const char *str)); VOID *ck_memdup P_((const VOID *buf, size_t len)); void ck_free P_((VOID *ptr)); struct buffer *init_buffer P_((void)); char *get_buffer P_((struct buffer *b)); size_t size_buffer P_((struct buffer *b)); char *add_buffer P_((struct buffer *b, const char *p, size_t n)); char *add1_buffer P_((struct buffer *b, int ch)); void free_buffer P_((struct buffer *b)); extern const char *myname; kbuild-3686/src/oldsed/lib/getopt.c0000664000175000017500000007323715053010105017173 0ustar locutuslocutus/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. 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, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO # define _NO_PROTO #endif #ifdef HAVE_CONFIG_H # include #endif #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 # include # if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ # include # include #endif /* GNU C library. */ #ifdef VMS # include # if HAVE_STRING_H - 0 # include # endif #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ macro is predefined. */ # ifdef HAVE_LIBINTL_H # include # define _(msgid) gettext (msgid) # else # define _(msgid) (msgid) # endif #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ int optind = 1; /* Formerly, initialization of getopt depended on optind==0, which causes problems with re-calling getopt as programs generally don't know that. */ int __getopt_initialized = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ # include # define my_index strchr #elif defined(_MSC_VER) || defined(__APPLE__) || defined(__FreeBSD__) \ || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__) \ || defined(__OS2__) || defined(__DragonFly__) # include # include # include # define my_index strchr #else /* Avoid depending on library functions or files whose names are inconsistent. */ #ifndef getenv extern char *getenv (); #endif #ifndef strncmp extern int strncmp (); #endif static char * my_index (str, chr) const char *str; int chr; { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ # if (!defined __STDC__ || !__STDC__) && !defined strlen /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); # endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #ifdef _LIBC /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; static int nonoption_flags_max_len; static int nonoption_flags_len; static int original_argc; static char *const *original_argv; /* Make sure the environment variable bash 2.0 puts in the environment is valid for the getopt call we must make sure that the ARGV passed to getopt is that one passed to the process. */ static void __attribute__ ((unused)) store_args_and_env (int argc, char *const *argv) { /* XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ original_argc = argc; original_argv = argv; } # ifdef text_set_element text_set_element (__libc_subinit, store_args_and_env); # endif /* text_set_element */ # define SWAP_FLAGS(ch1, ch2) \ if (nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } #else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) #endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ #if defined __STDC__ && __STDC__ static void exchange (char **); #endif static void exchange (argv) char **argv; { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ #ifdef _LIBC /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = malloc (top + 1); if (new_str == NULL) nonoption_flags_len = nonoption_flags_max_len = 0; else { memset (__mempcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len), '\0', top + 1 - nonoption_flags_max_len); nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } #endif while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; SWAP_FLAGS (bottom + i, middle + i); } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined __STDC__ && __STDC__ static const char *_getopt_initialize (int, char *const *, const char *); #endif static const char * _getopt_initialize (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; #ifdef _LIBC if (posixly_correct == NULL && argc == original_argc && argv == original_argv) { if (nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; int len = nonoption_flags_max_len = strlen (orig_str); if (nonoption_flags_max_len < argc) nonoption_flags_max_len = argc; __getopt_nonoption_flags = (char *) malloc (nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) nonoption_flags_max_len = -1; else memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), '\0', nonoption_flags_max_len - len); } } nonoption_flags_len = nonoption_flags_max_len; } else nonoption_flags_len = 0; #endif return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; { optarg = NULL; if (optind == 0 || !__getopt_initialized) { if (optind == 0) optind = 1; /* Don't scan ARGV[0], the program name. */ optstring = _getopt_initialize (argc, argv, optstring); __getopt_initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #ifdef _LIBC # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ || (optind < nonoption_flags_len \ && __getopt_nonoption_flags[optind] == '1')) #else # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (last_nonopt > optind) last_nonopt = optind; if (first_nonopt > optind) first_nonopt = optind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && NONOPTION_P) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, _("%s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, _("%s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); nextchar += strlen (nextchar); optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); else /* +option or -option */ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); else fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); } optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) fprintf (stderr, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == -1) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ kbuild-3686/src/oldsed/lib/utils.c0000664000175000017500000002407215053010105017022 0ustar locutuslocutus/* Functions from hack's utils library. Copyright (C) 1989, 1990, 1991, 1998, 1999, 2003 Free Software Foundation, Inc. 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, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h" #include #include #ifndef errno extern int errno; #endif #ifdef HAVE_STRINGS_H # include #else # include #endif /* HAVE_STRINGS_H */ #ifdef HAVE_STDLIB_H # include #endif /* HAVE_STDLIB_H */ #ifdef HAVE_UNISTD_H /* bird: for unlink on darwin */ # include #endif #include "utils.h" #ifdef KBUILD_OS_WINDOWS /* bird: Way faster console output! */ # include "console.h" # define fwrite maybe_con_fwrite #endif const char *myname; /* Store information about files opened with ck_fopen so that error messages from ck_fread, ck_fwrite, etc. can print the name of the file that had the error */ struct open_file { FILE *fp; char *name; struct open_file *link; unsigned temp : 1; }; static struct open_file *open_files = NULL; static void do_ck_fclose P_((FILE *fp)); /* Print an error message and exit */ #if !defined __STDC__ || !(__STDC__-0) # include # define VSTART(l,a) va_start(l) void panic(str, va_alist) char *str; va_dcl #else /*__STDC__*/ # include # define VSTART(l,a) va_start(l, a) void panic(const char *str, ...) #endif /* __STDC__ */ { va_list iggy; fprintf(stderr, "%s: ", myname); VSTART(iggy, str); #ifndef HAVE_VPRINTF # ifndef HAVE_DOPRNT fputs(str, stderr); /* not great, but perhaps better than nothing... */ # else /* HAVE_DOPRNT */ _doprnt(str, &iggy, stderr); # endif /* HAVE_DOPRNT */ #else /* HAVE_VFPRINTF */ vfprintf(stderr, str, iggy); #endif /* HAVE_VFPRINTF */ va_end(iggy); putc('\n', stderr); /* Unlink the temporary files. */ while (open_files) { if (open_files->temp) { int fd = fileno (open_files->fp); fclose (open_files->fp); errno = 0; unlink (open_files->name); if (errno != 0) fprintf (stderr, _("cannot remove %s: %s"), open_files->name, strerror (errno)); } open_files = open_files->link; } exit(4); } /* Internal routine to get a filename from open_files */ static const char *utils_fp_name P_((FILE *fp)); static const char * utils_fp_name(fp) FILE *fp; { struct open_file *p; for (p=open_files; p; p=p->link) if (p->fp == fp) return p->name; if (fp == stdin) return "stdin"; else if (fp == stdout) return "stdout"; else if (fp == stderr) return "stderr"; return ""; } /* Panic on failing fopen */ FILE * ck_fopen(name, mode, fail) const char *name; const char *mode; bool fail; { FILE *fp; struct open_file *p; fp = fopen (name, mode); if (!fp) { if (fail) panic(_("couldn't open file %s: %s"), name, strerror(errno)); return NULL; } for (p=open_files; p; p=p->link) { if (fp == p->fp) { FREE(p->name); break; } } if (!p) { p = MALLOC(1, struct open_file); p->link = open_files; open_files = p; } p->name = ck_strdup(name); p->fp = fp; p->temp = false; return fp; } FILE * ck_mkstemp (p_filename, tmpdir, base) char **p_filename; char *base, *tmpdir; { char *template; FILE *fp; int fd; struct open_file *p; if (tmpdir == NULL) tmpdir = getenv("TMPDIR"); if (tmpdir == NULL) { tmpdir = getenv("TMP"); if (tmpdir == NULL) #ifdef P_tmpdir tmpdir = P_tmpdir; #else tmpdir = "/tmp"; #endif } template = xmalloc (strlen (tmpdir) + strlen (base) + 8); sprintf (template, "%s/%sXXXXXX", tmpdir, base); fd = mkstemp (template); if (fd == -1) panic(_("couldn't open temporary file %s: %s"), template, strerror(errno)); *p_filename = template; fp = fdopen (fd, "w"); p = MALLOC(1, struct open_file); p->name = ck_strdup (template); p->fp = fp; p->temp = true; p->link = open_files; open_files = p; return fp; } /* Panic on failing fwrite */ void ck_fwrite(ptr, size, nmemb, stream) const VOID *ptr; size_t size; size_t nmemb; FILE *stream; { clearerr(stream); if (size && fwrite(ptr, size, nmemb, stream) != nmemb) panic(ngettext("couldn't write %d item to %s: %s", "couldn't write %d items to %s: %s", nmemb), nmemb, utils_fp_name(stream), strerror(errno)); } /* Panic on failing fread */ size_t ck_fread(ptr, size, nmemb, stream) VOID *ptr; size_t size; size_t nmemb; FILE *stream; { clearerr(stream); if (size && (nmemb=fread(ptr, size, nmemb, stream)) <= 0 && ferror(stream)) panic(_("read error on %s: %s"), utils_fp_name(stream), strerror(errno)); return nmemb; } size_t ck_getline(text, buflen, stream) char **text; size_t *buflen; FILE *stream; { int result; if (!ferror (stream)) result = getline (text, buflen, stream); if (ferror (stream)) panic (_("read error on %s: %s"), utils_fp_name(stream), strerror(errno)); return result; } /* Panic on failing fflush */ void ck_fflush(stream) FILE *stream; { clearerr(stream); if (fflush(stream) == EOF && errno != EBADF) panic("couldn't flush %s: %s", utils_fp_name(stream), strerror(errno)); } /* Panic on failing fclose */ void ck_fclose(stream) FILE *stream; { struct open_file r; struct open_file *prev; struct open_file *cur; /* a NULL stream means to close all files */ r.link = open_files; prev = &r; while ( (cur = prev->link) ) { if (!stream || stream == cur->fp) { do_ck_fclose (cur->fp); prev->link = cur->link; FREE(cur->name); FREE(cur); } else prev = cur; } open_files = r.link; /* Also care about stdout, because if it is redirected the last output operations might fail and it is important to signal this as an error (perhaps to make). */ if (!stream) { do_ck_fclose (stdout); do_ck_fclose (stderr); } } /* Close a single file. */ void do_ck_fclose(fp) FILE *fp; { int fd; ck_fflush(fp); clearerr(fp); /* We want to execute both arms, so use | not ||. */ if (fclose(fp) == EOF) panic("couldn't close %s: %s", utils_fp_name(fp), strerror(errno)); } /* Panic on failing rename */ void ck_rename (from, to, unlink_if_fail) const char *from, *to; const char *unlink_if_fail; { int rd = rename (from, to); if (rd != -1) return; if (unlink_if_fail) { int save_errno = errno; errno = 0; unlink (unlink_if_fail); /* Failure to remove the temporary file is more severe, so trigger it first. */ if (errno != 0) panic (_("cannot remove %s: %s"), unlink_if_fail, strerror (errno)); errno = save_errno; } panic (_("cannot rename %s: %s"), from, strerror (errno)); } /* Panic on failing malloc */ VOID * ck_malloc(size) size_t size; { VOID *ret = calloc(1, size ? size : 1); if (!ret) panic("couldn't allocate memory"); return ret; } /* Panic on failing malloc */ VOID * xmalloc(size) size_t size; { return ck_malloc(size); } /* Panic on failing realloc */ VOID * ck_realloc(ptr, size) VOID *ptr; size_t size; { VOID *ret; if (size == 0) { FREE(ptr); return NULL; } if (!ptr) return ck_malloc(size); ret = realloc(ptr, size); if (!ret) panic("couldn't re-allocate memory"); return ret; } /* Return a malloc()'d copy of a string */ char * ck_strdup(str) const char *str; { char *ret = MALLOC(strlen(str)+1, char); return strcpy(ret, str); } /* Return a malloc()'d copy of a block of memory */ VOID * ck_memdup(buf, len) const VOID *buf; size_t len; { VOID *ret = ck_malloc(len); return memcpy(ret, buf, len); } /* Release a malloc'd block of memory */ void ck_free(ptr) VOID *ptr; { if (ptr) free(ptr); } /* Implement a variable sized buffer of `stuff'. We don't know what it is, nor do we care, as long as it doesn't mind being aligned by malloc. */ struct buffer { size_t allocated; size_t length; char *b; }; #define MIN_ALLOCATE 50 struct buffer * init_buffer() { struct buffer *b = MALLOC(1, struct buffer); b->b = MALLOC(MIN_ALLOCATE, char); b->allocated = MIN_ALLOCATE; b->length = 0; return b; } char * get_buffer(b) struct buffer *b; { return b->b; } size_t size_buffer(b) struct buffer *b; { return b->length; } static void resize_buffer P_((struct buffer *b, size_t newlen)); static void resize_buffer(b, newlen) struct buffer *b; size_t newlen; { char *try = NULL; size_t alen = b->allocated; if (newlen <= alen) return; alen *= 2; if (newlen < alen) try = realloc(b->b, alen); /* Note: *not* the REALLOC() macro! */ if (!try) { alen = newlen; try = REALLOC(b->b, alen, char); } b->allocated = alen; b->b = try; } char * add_buffer(b, p, n) struct buffer *b; const char *p; size_t n; { char *result; if (b->allocated - b->length < n) resize_buffer(b, b->length+n); result = memcpy(b->b + b->length, p, n); b->length += n; return result; } char * add1_buffer(b, c) struct buffer *b; int c; { /* This special case should be kept cheap; * don't make it just a mere convenience * wrapper for add_buffer() -- even "builtin" * versions of memcpy(a, b, 1) can become * expensive when called too often. */ if (c != EOF) { char *result; if (b->allocated - b->length < 1) resize_buffer(b, b->length+1); result = b->b + b->length++; *result = c; return result; } return NULL; } void free_buffer(b) struct buffer *b; { if (b) FREE(b->b); FREE(b); } kbuild-3686/src/oldsed/lib/strerror.c0000664000175000017500000000277615053010104017552 0ustar locutuslocutus/* strerror -- return a string corresponding to an error number. This is a quickie version only intended as compatability glue for systems which predate the ANSI C definition of the function; the glibc version is recommended for more general use. Copyright (C) 1998 Free Software Foundation, Inc. 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, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h" #ifndef HAVE_STRERROR # ifndef BOOTSTRAP # include # endif # ifdef HAVE_STRING_H # include # endif # include # undef strerror extern int sys_nerr; extern char *sys_errlist[]; char * strerror(e) int e; { static char unknown_string[] = "Unknown error code #xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; if (0<=e && e contributed the Cray support. There are some preprocessor constants that can be defined when compiling for your specific system, for improved efficiency; however, the defaults should be okay. The general concept of this implementation is to keep track of all alloca-allocated blocks, and reclaim any that are found to be deeper in the stack than the current invocation. This heuristic does not reclaim storage as soon as it becomes invalid, but it will do so eventually. As a special case, alloca(0) reclaims storage without allocating any. It is a good idea to use alloca(0) in your main control loop, etc. to force garbage collection. */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef emacs #include "blockinput.h" #endif /* If compiling with GCC 2, this file's not needed. */ #if !defined (__GNUC__) || __GNUC__ < 2 /* If someone has defined alloca as a macro, there must be some other way alloca is supposed to work. */ #ifndef alloca #ifdef emacs #ifdef static /* actually, only want this if static is defined as "" -- this is for usg, in which emacs must undefine static in order to make unexec workable */ #ifndef STACK_DIRECTION you lose -- must know STACK_DIRECTION at compile-time #endif /* STACK_DIRECTION undefined */ #endif /* static */ #endif /* emacs */ /* If your stack is a linked list of frames, you have to provide an "address metric" ADDRESS_FUNCTION macro. */ #if defined (CRAY) && defined (CRAY_STACKSEG_END) long i00afunc (); #define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) #else #define ADDRESS_FUNCTION(arg) &(arg) #endif #if __STDC__ typedef void *pointer; #else typedef char *pointer; #endif #ifndef NULL #define NULL 0 #endif /* Different portions of Emacs need to call different versions of malloc. The Emacs executable needs alloca to call xmalloc, because ordinary malloc isn't protected from input signals. On the other hand, the utilities in lib-src need alloca to call malloc; some of them are very simple, and don't have an xmalloc routine. Non-Emacs programs expect this to call xmalloc. Callers below should use malloc. */ #ifndef emacs #define malloc xmalloc #endif extern pointer malloc (); /* Define STACK_DIRECTION if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ #ifndef STACK_DIRECTION #define STACK_DIRECTION 0 /* Direction unknown. */ #endif #if STACK_DIRECTION != 0 #define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ #else /* STACK_DIRECTION == 0; need run-time code. */ static int stack_dir; /* 1 or -1 once known. */ #define STACK_DIR stack_dir static void find_stack_direction () { static char *addr = NULL; /* Address of first `dummy', once known. */ auto char dummy; /* To get stack address. */ if (addr == NULL) { /* Initial entry. */ addr = ADDRESS_FUNCTION (dummy); find_stack_direction (); /* Recurse once. */ } else { /* Second entry. */ if (ADDRESS_FUNCTION (dummy) > addr) stack_dir = 1; /* Stack grew upward. */ else stack_dir = -1; /* Stack grew downward. */ } } #endif /* STACK_DIRECTION == 0 */ /* An "alloca header" is used to: (a) chain together all alloca'ed blocks; (b) keep track of stack depth. It is very important that sizeof(header) agree with malloc alignment chunk size. The following default should work okay. */ #ifndef ALIGN_SIZE #define ALIGN_SIZE sizeof(double) #endif typedef union hdr { char align[ALIGN_SIZE]; /* To force sizeof(header). */ struct { union hdr *next; /* For chaining headers. */ char *deep; /* For stack depth measure. */ } h; } header; static header *last_alloca_header = NULL; /* -> last alloca header. */ /* Return a pointer to at least SIZE bytes of storage, which will be automatically reclaimed upon exit from the procedure that called alloca. Originally, this space was supposed to be taken from the current stack frame of the caller, but that method cannot be made to work for some implementations of C, for example under Gould's UTX/32. */ pointer alloca (size) unsigned size; { auto char probe; /* Probes stack depth: */ register char *depth = ADDRESS_FUNCTION (probe); #if STACK_DIRECTION == 0 if (STACK_DIR == 0) /* Unknown growth direction. */ find_stack_direction (); #endif /* Reclaim garbage, defined as all alloca'd storage that was allocated from deeper in the stack than currently. */ { register header *hp; /* Traverses linked list. */ #ifdef emacs BLOCK_INPUT; #endif for (hp = last_alloca_header; hp != NULL;) if ((STACK_DIR > 0 && hp->h.deep > depth) || (STACK_DIR < 0 && hp->h.deep < depth)) { register header *np = hp->h.next; free ((pointer) hp); /* Collect garbage. */ hp = np; /* -> next header. */ } else break; /* Rest are not deeper. */ last_alloca_header = hp; /* -> last valid storage. */ #ifdef emacs UNBLOCK_INPUT; #endif } if (size == 0) return NULL; /* No allocation required. */ /* Allocate combined header + user data storage. */ { register pointer new = malloc (sizeof (header) + size); /* Address of header. */ if (new == 0) abort(); ((header *) new)->h.next = last_alloca_header; ((header *) new)->h.deep = depth; last_alloca_header = (header *) new; /* User storage begins just after header. */ return (pointer) ((char *) new + sizeof (header)); } } #if defined (CRAY) && defined (CRAY_STACKSEG_END) #ifdef DEBUG_I00AFUNC #include #endif #ifndef CRAY_STACK #define CRAY_STACK #ifndef CRAY2 /* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ struct stack_control_header { long shgrow:32; /* Number of times stack has grown. */ long shaseg:32; /* Size of increments to stack. */ long shhwm:32; /* High water mark of stack. */ long shsize:32; /* Current size of stack (all segments). */ }; /* The stack segment linkage control information occurs at the high-address end of a stack segment. (The stack grows from low addresses to high addresses.) The initial part of the stack segment linkage control information is 0200 (octal) words. This provides for register storage for the routine which overflows the stack. */ struct stack_segment_linkage { long ss[0200]; /* 0200 overflow words. */ long sssize:32; /* Number of words in this segment. */ long ssbase:32; /* Offset to stack base. */ long:32; long sspseg:32; /* Offset to linkage control of previous segment of stack. */ long:32; long sstcpt:32; /* Pointer to task common address block. */ long sscsnm; /* Private control structure number for microtasking. */ long ssusr1; /* Reserved for user. */ long ssusr2; /* Reserved for user. */ long sstpid; /* Process ID for pid based multi-tasking. */ long ssgvup; /* Pointer to multitasking thread giveup. */ long sscray[7]; /* Reserved for Cray Research. */ long ssa0; long ssa1; long ssa2; long ssa3; long ssa4; long ssa5; long ssa6; long ssa7; long sss0; long sss1; long sss2; long sss3; long sss4; long sss5; long sss6; long sss7; }; #else /* CRAY2 */ /* The following structure defines the vector of words returned by the STKSTAT library routine. */ struct stk_stat { long now; /* Current total stack size. */ long maxc; /* Amount of contiguous space which would be required to satisfy the maximum stack demand to date. */ long high_water; /* Stack high-water mark. */ long overflows; /* Number of stack overflow ($STKOFEN) calls. */ long hits; /* Number of internal buffer hits. */ long extends; /* Number of block extensions. */ long stko_mallocs; /* Block allocations by $STKOFEN. */ long underflows; /* Number of stack underflow calls ($STKRETN). */ long stko_free; /* Number of deallocations by $STKRETN. */ long stkm_free; /* Number of deallocations by $STKMRET. */ long segments; /* Current number of stack segments. */ long maxs; /* Maximum number of stack segments so far. */ long pad_size; /* Stack pad size. */ long current_address; /* Current stack segment address. */ long current_size; /* Current stack segment size. This number is actually corrupted by STKSTAT to include the fifteen word trailer area. */ long initial_address; /* Address of initial segment. */ long initial_size; /* Size of initial segment. */ }; /* The following structure describes the data structure which trails any stack segment. I think that the description in 'asdef' is out of date. I only describe the parts that I am sure about. */ struct stk_trailer { long this_address; /* Address of this block. */ long this_size; /* Size of this block (does not include this trailer). */ long unknown2; long unknown3; long link; /* Address of trailer block of previous segment. */ long unknown5; long unknown6; long unknown7; long unknown8; long unknown9; long unknown10; long unknown11; long unknown12; long unknown13; long unknown14; }; #endif /* CRAY2 */ #endif /* not CRAY_STACK */ #ifdef CRAY2 /* Determine a "stack measure" for an arbitrary ADDRESS. I doubt that "lint" will like this much. */ static long i00afunc (long *address) { struct stk_stat status; struct stk_trailer *trailer; long *block, size; long result = 0; /* We want to iterate through all of the segments. The first step is to get the stack status structure. We could do this more quickly and more directly, perhaps, by referencing the $LM00 common block, but I know that this works. */ STKSTAT (&status); /* Set up the iteration. */ trailer = (struct stk_trailer *) (status.current_address + status.current_size - 15); /* There must be at least one stack segment. Therefore it is a fatal error if "trailer" is null. */ if (trailer == 0) abort (); /* Discard segments that do not contain our argument address. */ while (trailer != 0) { block = (long *) trailer->this_address; size = trailer->this_size; if (block == 0 || size == 0) abort (); trailer = (struct stk_trailer *) trailer->link; if ((block <= address) && (address < (block + size))) break; } /* Set the result to the offset in this segment and add the sizes of all predecessor segments. */ result = address - block; if (trailer == 0) { return result; } do { if (trailer->this_size <= 0) abort (); result += trailer->this_size; trailer = (struct stk_trailer *) trailer->link; } while (trailer != 0); /* We are done. Note that if you present a bogus address (one not in any segment), you will get a different number back, formed from subtracting the address of the first block. This is probably not what you want. */ return (result); } #else /* not CRAY2 */ /* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. Determine the number of the cell within the stack, given the address of the cell. The purpose of this routine is to linearize, in some sense, stack addresses for alloca. */ static long i00afunc (long address) { long stkl = 0; long size, pseg, this_segment, stack; long result = 0; struct stack_segment_linkage *ssptr; /* Register B67 contains the address of the end of the current stack segment. If you (as a subprogram) store your registers on the stack and find that you are past the contents of B67, you have overflowed the segment. B67 also points to the stack segment linkage control area, which is what we are really interested in. */ stkl = CRAY_STACKSEG_END (); ssptr = (struct stack_segment_linkage *) stkl; /* If one subtracts 'size' from the end of the segment, one has the address of the first word of the segment. If this is not the first segment, 'pseg' will be nonzero. */ pseg = ssptr->sspseg; size = ssptr->sssize; this_segment = stkl - size; /* It is possible that calling this routine itself caused a stack overflow. Discard stack segments which do not contain the target address. */ while (!(this_segment <= address && address <= stkl)) { #ifdef DEBUG_I00AFUNC fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); #endif if (pseg == 0) break; stkl = stkl - pseg; ssptr = (struct stack_segment_linkage *) stkl; size = ssptr->sssize; pseg = ssptr->sspseg; this_segment = stkl - size; } result = address - this_segment; /* If you subtract pseg from the current end of the stack, you get the address of the previous stack segment's end. This seems a little convoluted to me, but I'll bet you save a cycle somewhere. */ while (pseg != 0) { #ifdef DEBUG_I00AFUNC fprintf (stderr, "%011o %011o\n", pseg, size); #endif stkl = stkl - pseg; ssptr = (struct stack_segment_linkage *) stkl; size = ssptr->sssize; pseg = ssptr->sspseg; result += size; } return (result); } #endif /* not CRAY2 */ #endif /* CRAY */ #endif /* no alloca */ #endif /* not GCC version 2 */ kbuild-3686/src/oldsed/lib/regcomp.c0000664000175000017500000032735015053010105017323 0ustar locutuslocutus/* Extended regular expression matching and search library. Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, size_t length, reg_syntax_t syntax); static void re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, char *fastmap); static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len); #ifdef RE_ENABLE_I18N static void free_charset (re_charset_t *cset); #endif /* RE_ENABLE_I18N */ static void free_workarea_compile (regex_t *preg); static reg_errcode_t create_initial_state (re_dfa_t *dfa); #ifdef RE_ENABLE_I18N static void optimize_utf8 (re_dfa_t *dfa); #endif static reg_errcode_t analyze (regex_t *preg); static reg_errcode_t preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), void *extra); static reg_errcode_t postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), void *extra); static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node); static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node); static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node); static reg_errcode_t calc_first (void *extra, bin_tree_t *node); static reg_errcode_t calc_next (void *extra, bin_tree_t *node); static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node); static int duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint); static int search_duplicated_node (const re_dfa_t *dfa, int org_node, unsigned int constraint); static reg_errcode_t calc_eclosure (re_dfa_t *dfa); static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root); static reg_errcode_t calc_inveclosure (re_dfa_t *dfa); static int fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax); static int peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) internal_function; static bin_tree_t *parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, reg_errcode_t *err); static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err); static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err); static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err); static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err); static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err); static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err); static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, re_token_t *token, int token_len, re_dfa_t *dfa, reg_syntax_t syntax, int accept_hyphen); static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, re_token_t *token); #ifdef RE_ENABLE_I18N static reg_errcode_t build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, int *equiv_class_alloc, const unsigned char *name); static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, re_charset_t *mbcset, int *char_class_alloc, const unsigned char *class_name, reg_syntax_t syntax); #else /* not RE_ENABLE_I18N */ static reg_errcode_t build_equiv_class (bitset_t sbcset, const unsigned char *name); static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, const unsigned char *class_name, reg_syntax_t syntax); #endif /* not RE_ENABLE_I18N */ static bin_tree_t *build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, const unsigned char *class_name, const unsigned char *extra, int non_match, reg_errcode_t *err); static bin_tree_t *create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, re_token_type_t type); static bin_tree_t *create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, const re_token_t *token); static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa); static void free_token (re_token_t *node); static reg_errcode_t free_tree (void *extra, bin_tree_t *node); static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node); /* This table gives an error message for each of the error codes listed in regex.h. Obviously the order here has to be same as there. POSIX doesn't require that we do anything for REG_NOERROR, but why not be nice? */ const char __re_error_msgid[] attribute_hidden = { #define REG_NOERROR_IDX 0 gettext_noop ("Success") /* REG_NOERROR */ "\0" #define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") gettext_noop ("No match") /* REG_NOMATCH */ "\0" #define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") gettext_noop ("Invalid regular expression") /* REG_BADPAT */ "\0" #define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ "\0" #define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") gettext_noop ("Invalid character class name") /* REG_ECTYPE */ "\0" #define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") gettext_noop ("Trailing backslash") /* REG_EESCAPE */ "\0" #define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") gettext_noop ("Invalid back reference") /* REG_ESUBREG */ "\0" #define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */ "\0" #define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ "\0" #define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") gettext_noop ("Unmatched \\{") /* REG_EBRACE */ "\0" #define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ "\0" #define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") gettext_noop ("Invalid range end") /* REG_ERANGE */ "\0" #define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") gettext_noop ("Memory exhausted") /* REG_ESPACE */ "\0" #define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ "\0" #define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") gettext_noop ("Premature end of regular expression") /* REG_EEND */ "\0" #define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") gettext_noop ("Regular expression too big") /* REG_ESIZE */ "\0" #define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ }; const size_t __re_error_msgid_idx[] attribute_hidden = { REG_NOERROR_IDX, REG_NOMATCH_IDX, REG_BADPAT_IDX, REG_ECOLLATE_IDX, REG_ECTYPE_IDX, REG_EESCAPE_IDX, REG_ESUBREG_IDX, REG_EBRACK_IDX, REG_EPAREN_IDX, REG_EBRACE_IDX, REG_BADBR_IDX, REG_ERANGE_IDX, REG_ESPACE_IDX, REG_BADRPT_IDX, REG_EEND_IDX, REG_ESIZE_IDX, REG_ERPAREN_IDX }; /* Entry points for GNU code. */ /* re_compile_pattern is the GNU regular expression compiler: it compiles PATTERN (of length LENGTH) and puts the result in BUFP. Returns 0 if the pattern was valid, otherwise an error string. Assumes the `allocated' (and perhaps `buffer') and `translate' fields are set in BUFP on entry. */ const char * re_compile_pattern (pattern, length, bufp) const char *pattern; size_t length; struct re_pattern_buffer *bufp; { reg_errcode_t ret; /* And GNU code determines whether or not to get register information by passing null for the REGS argument to re_match, etc., not by setting no_sub, unless RE_NO_SUB is set. */ bufp->no_sub = !!(re_syntax_options & RE_NO_SUB); /* Match anchors at newline. */ bufp->newline_anchor = 1; ret = re_compile_internal (bufp, pattern, length, re_syntax_options); if (!ret) return NULL; return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); } #ifdef _LIBC weak_alias (__re_compile_pattern, re_compile_pattern) #endif /* Set by `re_set_syntax' to the current regexp syntax to recognize. Can also be assigned to arbitrarily: each pattern buffer stores its own syntax, so it can be changed between regex compilations. */ /* This has no initializer because initialized variables in Emacs become read-only after dumping. */ reg_syntax_t re_syntax_options; /* Specify the precise syntax of regexps for compilation. This provides for compatibility for various utilities which historically have different, incompatible syntaxes. The argument SYNTAX is a bit mask comprised of the various bits defined in regex.h. We return the old syntax. */ reg_syntax_t re_set_syntax (syntax) reg_syntax_t syntax; { reg_syntax_t ret = re_syntax_options; re_syntax_options = syntax; return ret; } #ifdef _LIBC weak_alias (__re_set_syntax, re_set_syntax) #endif int re_compile_fastmap (bufp) struct re_pattern_buffer *bufp; { re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; char *fastmap = bufp->fastmap; memset (fastmap, '\0', sizeof (char) * SBC_MAX); re_compile_fastmap_iter (bufp, dfa->init_state, fastmap); if (dfa->init_state != dfa->init_state_word) re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap); if (dfa->init_state != dfa->init_state_nl) re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap); if (dfa->init_state != dfa->init_state_begbuf) re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap); bufp->fastmap_accurate = 1; return 0; } #ifdef _LIBC weak_alias (__re_compile_fastmap, re_compile_fastmap) #endif static inline void __attribute ((always_inline)) re_set_fastmap (char *fastmap, int icase, int ch) { fastmap[ch] = 1; if (icase) fastmap[tolower (ch)] = 1; } /* Helper function for re_compile_fastmap. Compile fastmap for the initial_state INIT_STATE. */ static void re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, char *fastmap) { re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; int node_cnt; int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) { int node = init_state->nodes.elems[node_cnt]; re_token_type_t type = dfa->nodes[node].type; if (type == CHARACTER) { re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); #ifdef RE_ENABLE_I18N if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) { unsigned char *buf = alloca (dfa->mb_cur_max), *p; wchar_t wc; mbstate_t state; p = buf; *p++ = dfa->nodes[node].opr.c; while (++node < dfa->nodes_len && dfa->nodes[node].type == CHARACTER && dfa->nodes[node].mb_partial) *p++ = dfa->nodes[node].opr.c; memset (&state, '\0', sizeof (state)); if (mbrtowc (&wc, (const char *) buf, p - buf, &state) == p - buf && (__wcrtomb ((char *) buf, towlower (wc), &state) != (size_t) -1)) re_set_fastmap (fastmap, 0, buf[0]); } #endif } else if (type == SIMPLE_BRACKET) { int i, ch; for (i = 0, ch = 0; i < BITSET_WORDS; ++i) { int j; bitset_word_t w = dfa->nodes[node].opr.sbcset[i]; for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) if (w & ((bitset_word_t) 1 << j)) re_set_fastmap (fastmap, icase, ch); } } #ifdef RE_ENABLE_I18N else if (type == COMPLEX_BRACKET) { int i; re_charset_t *cset = dfa->nodes[node].opr.mbcset; if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes || cset->nranges || cset->nchar_classes) { # ifdef _LIBC if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0) { /* In this case we want to catch the bytes which are the first byte of any collation elements. e.g. In da_DK, we want to catch 'a' since "aa" is a valid collation element, and don't catch 'b' since 'b' is the only collation element which starts from 'b'. */ const int32_t *table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); for (i = 0; i < SBC_MAX; ++i) if (table[i] < 0) re_set_fastmap (fastmap, icase, i); } # else if (dfa->mb_cur_max > 1) for (i = 0; i < SBC_MAX; ++i) if (__btowc (i) == WEOF) re_set_fastmap (fastmap, icase, i); # endif /* not _LIBC */ } for (i = 0; i < cset->nmbchars; ++i) { char buf[256]; mbstate_t state; memset (&state, '\0', sizeof (state)); if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) re_set_fastmap (fastmap, icase, *(unsigned char *) buf); if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) { if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state) != (size_t) -1) re_set_fastmap (fastmap, 0, *(unsigned char *) buf); } } } #endif /* RE_ENABLE_I18N */ else if (type == OP_PERIOD #ifdef RE_ENABLE_I18N || type == OP_UTF8_PERIOD #endif /* RE_ENABLE_I18N */ || type == END_OF_RE) { memset (fastmap, '\1', sizeof (char) * SBC_MAX); if (type == END_OF_RE) bufp->can_be_null = 1; return; } } } /* Entry point for POSIX code. */ /* regcomp takes a regular expression as a string and compiles it. PREG is a regex_t *. We do not expect any fields to be initialized, since POSIX says we shouldn't. Thus, we set `buffer' to the compiled pattern; `used' to the length of the compiled pattern; `syntax' to RE_SYNTAX_POSIX_EXTENDED if the REG_EXTENDED bit in CFLAGS is set; otherwise, to RE_SYNTAX_POSIX_BASIC; `newline_anchor' to REG_NEWLINE being set in CFLAGS; `fastmap' to an allocated space for the fastmap; `fastmap_accurate' to zero; `re_nsub' to the number of subexpressions in PATTERN. PATTERN is the address of the pattern string. CFLAGS is a series of bits which affect compilation. If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we use POSIX basic syntax. If REG_NEWLINE is set, then . and [^...] don't match newline. Also, regexec will try a match beginning after every newline. If REG_ICASE is set, then we considers upper- and lowercase versions of letters to be equivalent when matching. If REG_NOSUB is set, then when PREG is passed to regexec, that routine will report only success or failure, and nothing about the registers. It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for the return codes and their meanings.) */ int regcomp (preg, pattern, cflags) regex_t *__restrict preg; const char *__restrict pattern; int cflags; { reg_errcode_t ret; reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC); preg->buffer = NULL; preg->allocated = 0; preg->used = 0; /* Try to allocate space for the fastmap. */ preg->fastmap = re_malloc (char, SBC_MAX); if (BE (preg->fastmap == NULL, 0)) return REG_ESPACE; syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0; /* If REG_NEWLINE is set, newlines are treated differently. */ if (cflags & REG_NEWLINE) { /* REG_NEWLINE implies neither . nor [^...] match newline. */ syntax &= ~RE_DOT_NEWLINE; syntax |= RE_HAT_LISTS_NOT_NEWLINE; /* It also changes the matching behavior. */ preg->newline_anchor = 1; } else preg->newline_anchor = 0; preg->no_sub = !!(cflags & REG_NOSUB); preg->translate = NULL; ret = re_compile_internal (preg, pattern, strlen (pattern), syntax); /* POSIX doesn't distinguish between an unmatched open-group and an unmatched close-group: both are REG_EPAREN. */ if (ret == REG_ERPAREN) ret = REG_EPAREN; /* We have already checked preg->fastmap != NULL. */ if (BE (ret == REG_NOERROR, 1)) /* Compute the fastmap now, since regexec cannot modify the pattern buffer. This function never fails in this implementation. */ (void) re_compile_fastmap (preg); else { /* Some error occurred while compiling the expression. */ re_free (preg->fastmap); preg->fastmap = NULL; } return (int) ret; } #ifdef _LIBC weak_alias (__regcomp, regcomp) #endif /* Returns a message corresponding to an error code, ERRCODE, returned from either regcomp or regexec. We don't use PREG here. */ size_t regerror (errcode, preg, errbuf, errbuf_size) int errcode; const regex_t *__restrict preg; char *__restrict errbuf; size_t errbuf_size; { const char *msg; size_t msg_size; if (BE (errcode < 0 || errcode >= (int) (sizeof (__re_error_msgid_idx) / sizeof (__re_error_msgid_idx[0])), 0)) /* Only error codes returned by the rest of the code should be passed to this routine. If we are given anything else, or if other regex code generates an invalid error code, then the program has a bug. Dump core so we can fix it. */ abort (); msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); msg_size = strlen (msg) + 1; /* Includes the null. */ if (BE (errbuf_size != 0, 1)) { if (BE (msg_size > errbuf_size, 0)) { #if defined HAVE_MEMPCPY || defined _LIBC *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0'; #else memcpy (errbuf, msg, errbuf_size - 1); errbuf[errbuf_size - 1] = 0; #endif } else memcpy (errbuf, msg, msg_size); } return msg_size; } #ifdef _LIBC weak_alias (__regerror, regerror) #endif #ifdef RE_ENABLE_I18N /* This static array is used for the map to single-byte characters when UTF-8 is used. Otherwise we would allocate memory just to initialize it the same all the time. UTF-8 is the preferred encoding so this is a worthwhile optimization. */ static const bitset_t utf8_sb_map = { /* Set the first 128 bits. */ #ifdef _MSC_VER BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX, 0, 0, 0, 0 #else [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX #endif }; #endif static void free_dfa_content (re_dfa_t *dfa) { int i, j; if (dfa->nodes) for (i = 0; i < dfa->nodes_len; ++i) free_token (dfa->nodes + i); re_free (dfa->nexts); for (i = 0; i < dfa->nodes_len; ++i) { if (dfa->eclosures != NULL) re_node_set_free (dfa->eclosures + i); if (dfa->inveclosures != NULL) re_node_set_free (dfa->inveclosures + i); if (dfa->edests != NULL) re_node_set_free (dfa->edests + i); } re_free (dfa->edests); re_free (dfa->eclosures); re_free (dfa->inveclosures); re_free (dfa->nodes); if (dfa->state_table) for (i = 0; i <= dfa->state_hash_mask; ++i) { struct re_state_table_entry *entry = dfa->state_table + i; for (j = 0; j < entry->num; ++j) { re_dfastate_t *state = entry->array[j]; free_state (state); } re_free (entry->array); } re_free (dfa->state_table); #ifdef RE_ENABLE_I18N if (dfa->sb_char != utf8_sb_map) re_free (dfa->sb_char); #endif re_free (dfa->subexp_map); #ifdef DEBUG re_free (dfa->re_str); #endif re_free (dfa); } /* Free dynamically allocated space used by PREG. */ void regfree (preg) regex_t *preg; { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; if (BE (dfa != NULL, 1)) free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; re_free (preg->fastmap); preg->fastmap = NULL; re_free (preg->translate); preg->translate = NULL; } #ifdef _LIBC weak_alias (__regfree, regfree) #endif /* Entry points compatible with 4.2 BSD regex library. We don't define them unless specifically requested. */ #if defined _REGEX_RE_COMP || defined _LIBC /* BSD has one and only one pattern buffer. */ static struct re_pattern_buffer re_comp_buf; char * # ifdef _LIBC /* Make these definitions weak in libc, so POSIX programs can redefine these names if they don't use our functions, and still use regcomp/regexec above without link errors. */ weak_function # endif re_comp (s) const char *s; { reg_errcode_t ret; char *fastmap; if (!s) { if (!re_comp_buf.buffer) return gettext ("No previous regular expression"); return 0; } if (re_comp_buf.buffer) { fastmap = re_comp_buf.fastmap; re_comp_buf.fastmap = NULL; __regfree (&re_comp_buf); memset (&re_comp_buf, '\0', sizeof (re_comp_buf)); re_comp_buf.fastmap = fastmap; } if (re_comp_buf.fastmap == NULL) { re_comp_buf.fastmap = (char *) malloc (SBC_MAX); if (re_comp_buf.fastmap == NULL) return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) REG_ESPACE]); } /* Since `re_exec' always passes NULL for the `regs' argument, we don't need to initialize the pattern buffer fields which affect it. */ /* Match anchors at newlines. */ re_comp_buf.newline_anchor = 1; ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options); if (!ret) return NULL; /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); } #ifdef _LIBC libc_freeres_fn (free_mem) { __regfree (&re_comp_buf); } #endif #endif /* _REGEX_RE_COMP */ /* Internal entry point. Compile the regular expression PATTERN, whose length is LENGTH. SYNTAX indicate regular expression's syntax. */ static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, size_t length, reg_syntax_t syntax) { reg_errcode_t err = REG_NOERROR; re_dfa_t *dfa; re_string_t regexp; /* Initialize the pattern buffer. */ preg->fastmap_accurate = 0; preg->syntax = syntax; preg->not_bol = preg->not_eol = 0; preg->used = 0; preg->re_nsub = 0; preg->can_be_null = 0; preg->regs_allocated = REGS_UNALLOCATED; /* Initialize the dfa. */ dfa = (re_dfa_t *) preg->buffer; if (BE (preg->allocated < sizeof (re_dfa_t), 0)) { /* If zero allocated, but buffer is non-null, try to realloc enough space. This loses if buffer's address is bogus, but that is the user's responsibility. If ->buffer is NULL this is a simple allocation. */ dfa = re_realloc (preg->buffer, re_dfa_t, 1); if (dfa == NULL) return REG_ESPACE; preg->allocated = sizeof (re_dfa_t); preg->buffer = (unsigned char *) dfa; } preg->used = sizeof (re_dfa_t); err = init_dfa (dfa, length); if (BE (err != REG_NOERROR, 0)) { free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; return err; } #ifdef DEBUG /* Note: length+1 will not overflow since it is checked in init_dfa. */ dfa->re_str = re_malloc (char, length + 1); strncpy (dfa->re_str, pattern, length + 1); #endif __libc_lock_init (dfa->lock); err = re_string_construct (®exp, pattern, length, preg->translate, syntax & RE_ICASE, dfa); if (BE (err != REG_NOERROR, 0)) { re_compile_internal_free_return: free_workarea_compile (preg); re_string_destruct (®exp); free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; return err; } /* Parse the regular expression, and build a structure tree. */ preg->re_nsub = 0; dfa->str_tree = parse (®exp, preg, syntax, &err); if (BE (dfa->str_tree == NULL, 0)) goto re_compile_internal_free_return; /* Analyze the tree and create the nfa. */ err = analyze (preg); if (BE (err != REG_NOERROR, 0)) goto re_compile_internal_free_return; #ifdef RE_ENABLE_I18N /* If possible, do searching in single byte encoding to speed things up. */ if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL) optimize_utf8 (dfa); #endif /* Then create the initial state of the dfa. */ err = create_initial_state (dfa); /* Release work areas. */ free_workarea_compile (preg); re_string_destruct (®exp); if (BE (err != REG_NOERROR, 0)) { free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; } return err; } /* Initialize DFA. We use the length of the regular expression PAT_LEN as the initial length of some arrays. */ static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len) { unsigned int table_size; #ifndef _LIBC char *codeset_name; #endif memset (dfa, '\0', sizeof (re_dfa_t)); /* Force allocation of str_tree_storage the first time. */ dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; /* Avoid overflows. */ if (pat_len == SIZE_MAX) return REG_ESPACE; dfa->nodes_alloc = pat_len + 1; dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc); /* table_size = 2 ^ ceil(log pat_len) */ for (table_size = 1; ; table_size <<= 1) if (table_size > pat_len) break; dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size); dfa->state_hash_mask = table_size - 1; dfa->mb_cur_max = MB_CUR_MAX; #ifdef _LIBC if (dfa->mb_cur_max == 6 && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) dfa->is_utf8 = 1; dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) != 0); #else # ifdef KBUILD_OS_WINDOWS (void)codeset_name; if (get_crt_codepage() == MY_CP_UTF8) # else # ifdef HAVE_LANGINFO_CODESET codeset_name = nl_langinfo (CODESET); # else codeset_name = getenv ("LC_ALL"); if (codeset_name == NULL || codeset_name[0] == '\0') codeset_name = getenv ("LC_CTYPE"); if (codeset_name == NULL || codeset_name[0] == '\0') codeset_name = getenv ("LANG"); if (codeset_name == NULL) codeset_name = ""; else if (strchr (codeset_name, '.') != NULL) codeset_name = strchr (codeset_name, '.') + 1; # endif if (strcasecmp (codeset_name, "UTF-8") == 0 || strcasecmp (codeset_name, "UTF8") == 0) # endif dfa->is_utf8 = 1; /* We check exhaustively in the loop below if this charset is a superset of ASCII. */ dfa->map_notascii = 0; #endif #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { if (dfa->is_utf8) dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; else { int i, j, ch; dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); if (BE (dfa->sb_char == NULL, 0)) return REG_ESPACE; /* Set the bits corresponding to single byte chars. */ for (i = 0, ch = 0; i < BITSET_WORDS; ++i) for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) { wint_t wch = __btowc (ch); if (wch != WEOF) dfa->sb_char[i] |= (bitset_word_t) 1 << j; # ifndef _LIBC if (isascii (ch) && wch != ch) dfa->map_notascii = 1; # endif } } } #endif if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0)) return REG_ESPACE; return REG_NOERROR; } /* Initialize WORD_CHAR table, which indicate which character is "word". In this case "word" means that it is the word construction character used by some operators like "\<", "\>", etc. */ static void internal_function init_word_char (re_dfa_t *dfa) { int i, j, ch; dfa->word_ops_used = 1; for (i = 0, ch = 0; i < BITSET_WORDS; ++i) for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) if (isalnum (ch) || ch == '_') dfa->word_char[i] |= (bitset_word_t) 1 << j; } /* Free the work area which are only used while compiling. */ static void free_workarea_compile (regex_t *preg) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_storage_t *storage, *next; for (storage = dfa->str_tree_storage; storage; storage = next) { next = storage->next; re_free (storage); } dfa->str_tree_storage = NULL; dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; dfa->str_tree = NULL; re_free (dfa->org_indices); dfa->org_indices = NULL; } /* Create initial states for all contexts. */ static reg_errcode_t create_initial_state (re_dfa_t *dfa) { int first, i; reg_errcode_t err; re_node_set init_nodes; /* Initial states have the epsilon closure of the node which is the first node of the regular expression. */ first = dfa->str_tree->first->node_idx; dfa->init_node = first; err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first); if (BE (err != REG_NOERROR, 0)) return err; /* The back-references which are in initial states can epsilon transit, since in this case all of the subexpressions can be null. Then we add epsilon closures of the nodes which are the next nodes of the back-references. */ if (dfa->nbackref > 0) for (i = 0; i < init_nodes.nelem; ++i) { int node_idx = init_nodes.elems[i]; re_token_type_t type = dfa->nodes[node_idx].type; int clexp_idx; if (type != OP_BACK_REF) continue; for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx) { re_token_t *clexp_node; clexp_node = dfa->nodes + init_nodes.elems[clexp_idx]; if (clexp_node->type == OP_CLOSE_SUBEXP && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx) break; } if (clexp_idx == init_nodes.nelem) continue; if (type == OP_BACK_REF) { int dest_idx = dfa->edests[node_idx].elems[0]; if (!re_node_set_contains (&init_nodes, dest_idx)) { re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); i = 0; } } } /* It must be the first time to invoke acquire_state. */ dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); /* We don't check ERR here, since the initial state must not be NULL. */ if (BE (dfa->init_state == NULL, 0)) return err; if (dfa->init_state->has_constraint) { dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, CONTEXT_WORD); dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes, CONTEXT_NEWLINE); dfa->init_state_begbuf = re_acquire_state_context (&err, dfa, &init_nodes, CONTEXT_NEWLINE | CONTEXT_BEGBUF); if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL || dfa->init_state_begbuf == NULL, 0)) return err; } else dfa->init_state_word = dfa->init_state_nl = dfa->init_state_begbuf = dfa->init_state; re_node_set_free (&init_nodes); return REG_NOERROR; } #ifdef RE_ENABLE_I18N /* If it is possible to do searching in single byte encoding instead of UTF-8 to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change DFA nodes where needed. */ static void optimize_utf8 (re_dfa_t *dfa) { int node, i, mb_chars = 0, has_period = 0; for (node = 0; node < dfa->nodes_len; ++node) switch (dfa->nodes[node].type) { case CHARACTER: if (dfa->nodes[node].opr.c >= 0x80) mb_chars = 1; break; case ANCHOR: switch (dfa->nodes[node].opr.idx) { case LINE_FIRST: case LINE_LAST: case BUF_FIRST: case BUF_LAST: break; default: /* Word anchors etc. cannot be handled. */ return; } break; case OP_PERIOD: has_period = 1; break; case OP_BACK_REF: case OP_ALT: case END_OF_RE: case OP_DUP_ASTERISK: case OP_OPEN_SUBEXP: case OP_CLOSE_SUBEXP: break; case COMPLEX_BRACKET: return; case SIMPLE_BRACKET: /* Just double check. The non-ASCII range starts at 0x80. */ assert (0x80 % BITSET_WORD_BITS == 0); for (i = 0x80 / BITSET_WORD_BITS; i < BITSET_WORDS; ++i) if (dfa->nodes[node].opr.sbcset[i]) return; break; default: abort (); } if (mb_chars || has_period) for (node = 0; node < dfa->nodes_len; ++node) { if (dfa->nodes[node].type == CHARACTER && dfa->nodes[node].opr.c >= 0x80) dfa->nodes[node].mb_partial = 0; else if (dfa->nodes[node].type == OP_PERIOD) dfa->nodes[node].type = OP_UTF8_PERIOD; } /* The search can be in single byte locale. */ dfa->mb_cur_max = 1; dfa->is_utf8 = 0; dfa->has_mb_node = dfa->nbackref > 0 || has_period; } #endif /* Analyze the structure tree, and calculate "first", "next", "edest", "eclosure", and "inveclosure". */ static reg_errcode_t analyze (regex_t *preg) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; reg_errcode_t ret; /* Allocate arrays. */ dfa->nexts = re_malloc (int, dfa->nodes_alloc); dfa->org_indices = re_malloc (int, dfa->nodes_alloc); dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc); dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc); if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL || dfa->eclosures == NULL, 0)) return REG_ESPACE; dfa->subexp_map = re_malloc (int, preg->re_nsub); if (dfa->subexp_map != NULL) { int i; for (i = 0; i < preg->re_nsub; i++) dfa->subexp_map[i] = i; preorder (dfa->str_tree, optimize_subexps, dfa); for (i = 0; i < preg->re_nsub; i++) if (dfa->subexp_map[i] != i) break; if (i == preg->re_nsub) { free (dfa->subexp_map); dfa->subexp_map = NULL; } } ret = postorder (dfa->str_tree, lower_subexps, preg); if (BE (ret != REG_NOERROR, 0)) return ret; ret = postorder (dfa->str_tree, calc_first, dfa); if (BE (ret != REG_NOERROR, 0)) return ret; preorder (dfa->str_tree, calc_next, dfa); ret = preorder (dfa->str_tree, link_nfa_nodes, dfa); if (BE (ret != REG_NOERROR, 0)) return ret; ret = calc_eclosure (dfa); if (BE (ret != REG_NOERROR, 0)) return ret; /* We only need this during the prune_impossible_nodes pass in regexec.c; skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */ if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match) || dfa->nbackref) { dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len); if (BE (dfa->inveclosures == NULL, 0)) return REG_ESPACE; ret = calc_inveclosure (dfa); } return ret; } /* Our parse trees are very unbalanced, so we cannot use a stack to implement parse tree visits. Instead, we use parent pointers and some hairy code in these two functions. */ static reg_errcode_t postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), void *extra) { bin_tree_t *node, *prev; for (node = root; ; ) { /* Descend down the tree, preferably to the left (or to the right if that's the only child). */ while (node->left || node->right) if (node->left) node = node->left; else node = node->right; do { reg_errcode_t err = fn (extra, node); if (BE (err != REG_NOERROR, 0)) return err; if (node->parent == NULL) return REG_NOERROR; prev = node; node = node->parent; } /* Go up while we have a node that is reached from the right. */ while (node->right == prev || node->right == NULL); node = node->right; } } static reg_errcode_t preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), void *extra) { bin_tree_t *node; for (node = root; ; ) { reg_errcode_t err = fn (extra, node); if (BE (err != REG_NOERROR, 0)) return err; /* Go to the left node, or up and to the right. */ if (node->left) node = node->left; else { bin_tree_t *prev = NULL; while (node->right == prev || node->right == NULL) { prev = node; node = node->parent; if (!node) return REG_NOERROR; } node = node->right; } } } /* Optimization pass: if a SUBEXP is entirely contained, strip it and tell re_search_internal to map the inner one's opr.idx to this one's. Adjust backreferences as well. Requires a preorder visit. */ static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node) { re_dfa_t *dfa = (re_dfa_t *) extra; if (node->token.type == OP_BACK_REF && dfa->subexp_map) { int idx = node->token.opr.idx; node->token.opr.idx = dfa->subexp_map[idx]; dfa->used_bkref_map |= 1 << node->token.opr.idx; } else if (node->token.type == SUBEXP && node->left && node->left->token.type == SUBEXP) { int other_idx = node->left->token.opr.idx; node->left = node->left->left; if (node->left) node->left->parent = node; dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx]; if (other_idx < BITSET_WORD_BITS) dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx); } return REG_NOERROR; } /* Lowering pass: Turn each SUBEXP node into the appropriate concatenation of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */ static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node) { regex_t *preg = (regex_t *) extra; reg_errcode_t err = REG_NOERROR; if (node->left && node->left->token.type == SUBEXP) { node->left = lower_subexp (&err, preg, node->left); if (node->left) node->left->parent = node; } if (node->right && node->right->token.type == SUBEXP) { node->right = lower_subexp (&err, preg, node->right); if (node->right) node->right->parent = node; } return err; } static bin_tree_t * lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *body = node->left; bin_tree_t *op, *cls, *tree1, *tree; if (preg->no_sub /* We do not optimize empty subexpressions, because otherwise we may have bad CONCAT nodes with NULL children. This is obviously not very common, so we do not lose much. An example that triggers this case is the sed "script" /\(\)/x. */ && node->left != NULL && (node->token.opr.idx >= BITSET_WORD_BITS || !(dfa->used_bkref_map & ((bitset_word_t) 1 << node->token.opr.idx)))) return node->left; /* Convert the SUBEXP node to the concatenation of an OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */ op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP); cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP); tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls; tree = create_tree (dfa, op, tree1, CONCAT); if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0)) { *err = REG_ESPACE; return NULL; } op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx; op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp; return tree; } /* Pass 1 in building the NFA: compute FIRST and create unlinked automaton nodes. Requires a postorder visit. */ static reg_errcode_t calc_first (void *extra, bin_tree_t *node) { re_dfa_t *dfa = (re_dfa_t *) extra; if (node->token.type == CONCAT) { node->first = node->left->first; node->node_idx = node->left->node_idx; } else { node->first = node; node->node_idx = re_dfa_add_node (dfa, node->token); if (BE (node->node_idx == -1, 0)) return REG_ESPACE; } return REG_NOERROR; } /* Pass 2: compute NEXT on the tree. Preorder visit. */ static reg_errcode_t calc_next (void *extra, bin_tree_t *node) { switch (node->token.type) { case OP_DUP_ASTERISK: node->left->next = node; break; case CONCAT: node->left->next = node->right->first; node->right->next = node->next; break; default: if (node->left) node->left->next = node->next; if (node->right) node->right->next = node->next; break; } return REG_NOERROR; } /* Pass 3: link all DFA nodes to their NEXT node (any order will do). */ static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node) { re_dfa_t *dfa = (re_dfa_t *) extra; int idx = node->node_idx; reg_errcode_t err = REG_NOERROR; switch (node->token.type) { case CONCAT: break; case END_OF_RE: assert (node->next == NULL); break; case OP_DUP_ASTERISK: case OP_ALT: { int left, right; dfa->has_plural_match = 1; if (node->left != NULL) left = node->left->first->node_idx; else left = node->next->node_idx; if (node->right != NULL) right = node->right->first->node_idx; else right = node->next->node_idx; assert (left > -1); assert (right > -1); err = re_node_set_init_2 (dfa->edests + idx, left, right); } break; case ANCHOR: case OP_OPEN_SUBEXP: case OP_CLOSE_SUBEXP: err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx); break; case OP_BACK_REF: dfa->nexts[idx] = node->next->node_idx; if (node->token.type == OP_BACK_REF) re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]); break; default: assert (!IS_EPSILON_NODE (node->token.type)); dfa->nexts[idx] = node->next->node_idx; break; } return err; } /* Duplicate the epsilon closure of the node ROOT_NODE. Note that duplicated nodes have constraint INIT_CONSTRAINT in addition to their own constraint. */ static reg_errcode_t internal_function duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node, int root_node, unsigned int init_constraint) { int org_node, clone_node, ret; unsigned int constraint = init_constraint; for (org_node = top_org_node, clone_node = top_clone_node;;) { int org_dest, clone_dest; if (dfa->nodes[org_node].type == OP_BACK_REF) { /* If the back reference epsilon-transit, its destination must also have the constraint. Then duplicate the epsilon closure of the destination of the back reference, and store it in edests of the back reference. */ org_dest = dfa->nexts[org_node]; re_node_set_empty (dfa->edests + clone_node); clone_dest = duplicate_node (dfa, org_dest, constraint); if (BE (clone_dest == -1, 0)) return REG_ESPACE; dfa->nexts[clone_node] = dfa->nexts[org_node]; ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; } else if (dfa->edests[org_node].nelem == 0) { /* In case of the node can't epsilon-transit, don't duplicate the destination and store the original destination as the destination of the node. */ dfa->nexts[clone_node] = dfa->nexts[org_node]; break; } else if (dfa->edests[org_node].nelem == 1) { /* In case of the node can epsilon-transit, and it has only one destination. */ org_dest = dfa->edests[org_node].elems[0]; re_node_set_empty (dfa->edests + clone_node); if (dfa->nodes[org_node].type == ANCHOR) { /* In case of the node has another constraint, append it. */ if (org_node == root_node && clone_node != org_node) { /* ...but if the node is root_node itself, it means the epsilon closure have a loop, then tie it to the destination of the root_node. */ ret = re_node_set_insert (dfa->edests + clone_node, org_dest); if (BE (ret < 0, 0)) return REG_ESPACE; break; } constraint |= dfa->nodes[org_node].opr.ctx_type; } clone_dest = duplicate_node (dfa, org_dest, constraint); if (BE (clone_dest == -1, 0)) return REG_ESPACE; ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; } else /* dfa->edests[org_node].nelem == 2 */ { /* In case of the node can epsilon-transit, and it has two destinations. In the bin_tree_t and DFA, that's '|' and '*'. */ org_dest = dfa->edests[org_node].elems[0]; re_node_set_empty (dfa->edests + clone_node); /* Search for a duplicated node which satisfies the constraint. */ clone_dest = search_duplicated_node (dfa, org_dest, constraint); if (clone_dest == -1) { /* There are no such a duplicated node, create a new one. */ reg_errcode_t err; clone_dest = duplicate_node (dfa, org_dest, constraint); if (BE (clone_dest == -1, 0)) return REG_ESPACE; ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; err = duplicate_node_closure (dfa, org_dest, clone_dest, root_node, constraint); if (BE (err != REG_NOERROR, 0)) return err; } else { /* There are a duplicated node which satisfy the constraint, use it to avoid infinite loop. */ ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; } org_dest = dfa->edests[org_node].elems[1]; clone_dest = duplicate_node (dfa, org_dest, constraint); if (BE (clone_dest == -1, 0)) return REG_ESPACE; ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; } org_node = org_dest; clone_node = clone_dest; } return REG_NOERROR; } /* Search for a node which is duplicated from the node ORG_NODE, and satisfies the constraint CONSTRAINT. */ static int search_duplicated_node (const re_dfa_t *dfa, int org_node, unsigned int constraint) { int idx; for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx) { if (org_node == dfa->org_indices[idx] && constraint == dfa->nodes[idx].constraint) return idx; /* Found. */ } return -1; /* Not found. */ } /* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT. Return the index of the new node, or -1 if insufficient storage is available. */ static int duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint) { int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]); if (BE (dup_idx != -1, 1)) { dfa->nodes[dup_idx].constraint = constraint; if (dfa->nodes[org_idx].type == ANCHOR) dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type; dfa->nodes[dup_idx].duplicated = 1; /* Store the index of the original node. */ dfa->org_indices[dup_idx] = org_idx; } return dup_idx; } static reg_errcode_t calc_inveclosure (re_dfa_t *dfa) { int src, idx, ret; for (idx = 0; idx < dfa->nodes_len; ++idx) re_node_set_init_empty (dfa->inveclosures + idx); for (src = 0; src < dfa->nodes_len; ++src) { int *elems = dfa->eclosures[src].elems; for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx) { ret = re_node_set_insert_last (dfa->inveclosures + elems[idx], src); if (BE (ret == -1, 0)) return REG_ESPACE; } } return REG_NOERROR; } /* Calculate "eclosure" for all the node in DFA. */ static reg_errcode_t calc_eclosure (re_dfa_t *dfa) { int node_idx, incomplete; #ifdef DEBUG assert (dfa->nodes_len > 0); #endif incomplete = 0; /* For each nodes, calculate epsilon closure. */ for (node_idx = 0; ; ++node_idx) { reg_errcode_t err; re_node_set eclosure_elem; if (node_idx == dfa->nodes_len) { if (!incomplete) break; incomplete = 0; node_idx = 0; } #ifdef DEBUG assert (dfa->eclosures[node_idx].nelem != -1); #endif /* If we have already calculated, skip it. */ if (dfa->eclosures[node_idx].nelem != 0) continue; /* Calculate epsilon closure of `node_idx'. */ err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1); if (BE (err != REG_NOERROR, 0)) return err; if (dfa->eclosures[node_idx].nelem == 0) { incomplete = 1; re_node_set_free (&eclosure_elem); } } return REG_NOERROR; } /* Calculate epsilon closure of NODE. */ static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root) { reg_errcode_t err; unsigned int constraint; int i, incomplete; re_node_set eclosure; incomplete = 0; err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); if (BE (err != REG_NOERROR, 0)) return err; /* This indicates that we are calculating this node now. We reference this value to avoid infinite loop. */ dfa->eclosures[node].nelem = -1; constraint = ((dfa->nodes[node].type == ANCHOR) ? dfa->nodes[node].opr.ctx_type : 0); /* If the current node has constraints, duplicate all nodes. Since they must inherit the constraints. */ if (constraint && dfa->edests[node].nelem && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) { int org_node, cur_node; org_node = cur_node = node; err = duplicate_node_closure (dfa, node, node, node, constraint); if (BE (err != REG_NOERROR, 0)) return err; } /* Expand each epsilon destination nodes. */ if (IS_EPSILON_NODE(dfa->nodes[node].type)) for (i = 0; i < dfa->edests[node].nelem; ++i) { re_node_set eclosure_elem; int edest = dfa->edests[node].elems[i]; /* If calculating the epsilon closure of `edest' is in progress, return intermediate result. */ if (dfa->eclosures[edest].nelem == -1) { incomplete = 1; continue; } /* If we haven't calculated the epsilon closure of `edest' yet, calculate now. Otherwise use calculated epsilon closure. */ if (dfa->eclosures[edest].nelem == 0) { err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0); if (BE (err != REG_NOERROR, 0)) return err; } else eclosure_elem = dfa->eclosures[edest]; /* Merge the epsilon closure of `edest'. */ re_node_set_merge (&eclosure, &eclosure_elem); /* If the epsilon closure of `edest' is incomplete, the epsilon closure of this node is also incomplete. */ if (dfa->eclosures[edest].nelem == 0) { incomplete = 1; re_node_set_free (&eclosure_elem); } } /* Epsilon closures include itself. */ re_node_set_insert (&eclosure, node); if (incomplete && !root) dfa->eclosures[node].nelem = 0; else dfa->eclosures[node] = eclosure; *new_set = eclosure; return REG_NOERROR; } /* Functions for token which are used in the parser. */ /* Fetch a token from INPUT. We must not use this function inside bracket expressions. */ static void internal_function fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax) { re_string_skip_bytes (input, peek_token (result, input, syntax)); } /* Peek a token from INPUT, and return the length of the token. We must not use this function inside bracket expressions. */ static int internal_function peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) { unsigned char c; if (re_string_eoi (input)) { token->type = END_OF_RE; return 0; } c = re_string_peek_byte (input, 0); token->opr.c = c; token->word_char = 0; #ifdef RE_ENABLE_I18N token->mb_partial = 0; if (input->mb_cur_max > 1 && !re_string_first_byte (input, re_string_cur_idx (input))) { token->type = CHARACTER; token->mb_partial = 1; return 1; } #endif if (c == '\\') { unsigned char c2; if (re_string_cur_idx (input) + 1 >= re_string_length (input)) { token->type = BACK_SLASH; return 1; } c2 = re_string_peek_byte_case (input, 1); token->opr.c = c2; token->type = CHARACTER; #ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1) { wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input) + 1); token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; } else #endif token->word_char = IS_WORD_CHAR (c2) != 0; switch (c2) { case '|': if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR)) token->type = OP_ALT; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (!(syntax & RE_NO_BK_REFS)) { token->type = OP_BACK_REF; token->opr.idx = c2 - '1'; } break; case '<': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = WORD_FIRST; } break; case '>': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = WORD_LAST; } break; case 'b': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = WORD_DELIM; } break; case 'B': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = NOT_WORD_DELIM; } break; case 'w': if (!(syntax & RE_NO_GNU_OPS)) token->type = OP_WORD; break; case 'W': if (!(syntax & RE_NO_GNU_OPS)) token->type = OP_NOTWORD; break; case 's': if (!(syntax & RE_NO_GNU_OPS)) token->type = OP_SPACE; break; case 'S': if (!(syntax & RE_NO_GNU_OPS)) token->type = OP_NOTSPACE; break; case '`': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = BUF_FIRST; } break; case '\'': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = BUF_LAST; } break; case '(': if (!(syntax & RE_NO_BK_PARENS)) token->type = OP_OPEN_SUBEXP; break; case ')': if (!(syntax & RE_NO_BK_PARENS)) token->type = OP_CLOSE_SUBEXP; break; case '+': if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) token->type = OP_DUP_PLUS; break; case '?': if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) token->type = OP_DUP_QUESTION; break; case '{': if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) token->type = OP_OPEN_DUP_NUM; break; case '}': if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) token->type = OP_CLOSE_DUP_NUM; break; default: break; } return 2; } token->type = CHARACTER; #ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1) { wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; } else #endif token->word_char = IS_WORD_CHAR (token->opr.c); switch (c) { case '\n': if (syntax & RE_NEWLINE_ALT) token->type = OP_ALT; break; case '|': if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR)) token->type = OP_ALT; break; case '*': token->type = OP_DUP_ASTERISK; break; case '+': if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) token->type = OP_DUP_PLUS; break; case '?': if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) token->type = OP_DUP_QUESTION; break; case '{': if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) token->type = OP_OPEN_DUP_NUM; break; case '}': if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) token->type = OP_CLOSE_DUP_NUM; break; case '(': if (syntax & RE_NO_BK_PARENS) token->type = OP_OPEN_SUBEXP; break; case ')': if (syntax & RE_NO_BK_PARENS) token->type = OP_CLOSE_SUBEXP; break; case '[': token->type = OP_OPEN_BRACKET; break; case '.': token->type = OP_PERIOD; break; case '^': if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) && re_string_cur_idx (input) != 0) { char prev = re_string_peek_byte (input, -1); if (!(syntax & RE_NEWLINE_ALT) || prev != '\n') break; } token->type = ANCHOR; token->opr.ctx_type = LINE_FIRST; break; case '$': if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) && re_string_cur_idx (input) + 1 != re_string_length (input)) { re_token_t next; re_string_skip_bytes (input, 1); peek_token (&next, input, syntax); re_string_skip_bytes (input, -1); if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP) break; } token->type = ANCHOR; token->opr.ctx_type = LINE_LAST; break; default: break; } return 1; } /* Peek a token from INPUT, and return the length of the token. We must not use this function out of bracket expressions. */ static int internal_function peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) { unsigned char c; if (re_string_eoi (input)) { token->type = END_OF_RE; return 0; } c = re_string_peek_byte (input, 0); token->opr.c = c; #ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1 && !re_string_first_byte (input, re_string_cur_idx (input))) { token->type = CHARACTER; return 1; } #endif /* RE_ENABLE_I18N */ if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && re_string_cur_idx (input) + 1 < re_string_length (input)) { /* In this case, '\' escape a character. */ unsigned char c2; re_string_skip_bytes (input, 1); c2 = re_string_peek_byte (input, 0); token->opr.c = c2; token->type = CHARACTER; return 1; } if (c == '[') /* '[' is a special char in a bracket exps. */ { unsigned char c2; int token_len; if (re_string_cur_idx (input) + 1 < re_string_length (input)) c2 = re_string_peek_byte (input, 1); else c2 = 0; token->opr.c = c2; token_len = 2; switch (c2) { case '.': token->type = OP_OPEN_COLL_ELEM; break; case '=': token->type = OP_OPEN_EQUIV_CLASS; break; case ':': if (syntax & RE_CHAR_CLASSES) { token->type = OP_OPEN_CHAR_CLASS; break; } /* else fall through. */ default: token->type = CHARACTER; token->opr.c = c; token_len = 1; break; } return token_len; } switch (c) { case '-': token->type = OP_CHARSET_RANGE; break; case ']': token->type = OP_CLOSE_BRACKET; break; case '^': token->type = OP_NON_MATCH_LIST; break; default: token->type = CHARACTER; } return 1; } /* Functions for parser. */ /* Entry point of the parser. Parse the regular expression REGEXP and return the structure tree. If an error is occured, ERR is set by error code, and return NULL. This function build the following tree, from regular expression : CAT / \ / \ EOR CAT means concatenation. EOR means end of regular expression. */ static bin_tree_t * parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, reg_errcode_t *err) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *tree, *eor, *root; re_token_t current_token; dfa->syntax = syntax; fetch_token (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE); tree = parse_reg_exp (regexp, preg, ¤t_token, syntax, 0, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; eor = create_tree (dfa, NULL, NULL, END_OF_RE); if (tree != NULL) root = create_tree (dfa, tree, eor, CONCAT); else root = eor; if (BE (eor == NULL || root == NULL, 0)) { *err = REG_ESPACE; return NULL; } return root; } /* This function build the following tree, from regular expression |: ALT / \ / \ ALT means alternative, which represents the operator `|'. */ static bin_tree_t * parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *tree, *branch = NULL; tree = parse_branch (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; while (token->type == OP_ALT) { fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); if (token->type != OP_ALT && token->type != END_OF_RE && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) { branch = parse_branch (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && branch == NULL, 0)) return NULL; } else branch = NULL; tree = create_tree (dfa, tree, branch, OP_ALT); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } } return tree; } /* This function build the following tree, from regular expression : CAT / \ / \ CAT means concatenation. */ static bin_tree_t * parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err) { bin_tree_t *tree, *exp; re_dfa_t *dfa = (re_dfa_t *) preg->buffer; tree = parse_expression (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; while (token->type != OP_ALT && token->type != END_OF_RE && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) { exp = parse_expression (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && exp == NULL, 0)) { return NULL; } if (tree != NULL && exp != NULL) { tree = create_tree (dfa, tree, exp, CONCAT); if (tree == NULL) { *err = REG_ESPACE; return NULL; } } else if (tree == NULL) tree = exp; /* Otherwise exp == NULL, we don't need to create new tree. */ } return tree; } /* This function build the following tree, from regular expression a*: * | a */ static bin_tree_t * parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *tree; switch (token->type) { case CHARACTER: tree = create_token_tree (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { while (!re_string_eoi (regexp) && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) { bin_tree_t *mbc_remain; fetch_token (token, regexp, syntax); mbc_remain = create_token_tree (dfa, NULL, NULL, token); tree = create_tree (dfa, tree, mbc_remain, CONCAT); if (BE (mbc_remain == NULL || tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } } } #endif break; case OP_OPEN_SUBEXP: tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; break; case OP_OPEN_BRACKET: tree = parse_bracket_exp (regexp, dfa, token, syntax, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; break; case OP_BACK_REF: if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1)) { *err = REG_ESUBREG; return NULL; } dfa->used_bkref_map |= 1 << token->opr.idx; tree = create_token_tree (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } ++dfa->nbackref; dfa->has_mb_node = 1; break; case OP_OPEN_DUP_NUM: if (syntax & RE_CONTEXT_INVALID_DUP) { *err = REG_BADRPT; return NULL; } /* FALLTHROUGH */ case OP_DUP_ASTERISK: case OP_DUP_PLUS: case OP_DUP_QUESTION: if (syntax & RE_CONTEXT_INVALID_OPS) { *err = REG_BADRPT; return NULL; } else if (syntax & RE_CONTEXT_INDEP_OPS) { fetch_token (token, regexp, syntax); return parse_expression (regexp, preg, token, syntax, nest, err); } /* else fall through */ case OP_CLOSE_SUBEXP: if ((token->type == OP_CLOSE_SUBEXP) && !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)) { *err = REG_ERPAREN; return NULL; } /* else fall through */ case OP_CLOSE_DUP_NUM: /* We treat it as a normal character. */ /* Then we can these characters as normal characters. */ token->type = CHARACTER; /* mb_partial and word_char bits should be initialized already by peek_token. */ tree = create_token_tree (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } break; case ANCHOR: if ((token->opr.ctx_type & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST)) && dfa->word_ops_used == 0) init_word_char (dfa); if (token->opr.ctx_type == WORD_DELIM || token->opr.ctx_type == NOT_WORD_DELIM) { bin_tree_t *tree_first, *tree_last; if (token->opr.ctx_type == WORD_DELIM) { token->opr.ctx_type = WORD_FIRST; tree_first = create_token_tree (dfa, NULL, NULL, token); token->opr.ctx_type = WORD_LAST; } else { token->opr.ctx_type = INSIDE_WORD; tree_first = create_token_tree (dfa, NULL, NULL, token); token->opr.ctx_type = INSIDE_NOTWORD; } tree_last = create_token_tree (dfa, NULL, NULL, token); tree = create_tree (dfa, tree_first, tree_last, OP_ALT); if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } } else { tree = create_token_tree (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } } /* We must return here, since ANCHORs can't be followed by repetition operators. eg. RE"^*" is invalid or "", it must not be "". */ fetch_token (token, regexp, syntax); return tree; case OP_PERIOD: tree = create_token_tree (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } if (dfa->mb_cur_max > 1) dfa->has_mb_node = 1; break; case OP_WORD: case OP_NOTWORD: tree = build_charclass_op (dfa, regexp->trans, (const unsigned char *) "alnum", (const unsigned char *) "_", token->type == OP_NOTWORD, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; break; case OP_SPACE: case OP_NOTSPACE: tree = build_charclass_op (dfa, regexp->trans, (const unsigned char *) "space", (const unsigned char *) "", token->type == OP_NOTSPACE, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; break; case OP_ALT: case END_OF_RE: return NULL; case BACK_SLASH: *err = REG_EESCAPE; return NULL; default: /* Must not happen? */ #ifdef DEBUG assert (0); #endif return NULL; } fetch_token (token, regexp, syntax); while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM) { tree = parse_dup_op (tree, regexp, dfa, token, syntax, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; /* In BRE consecutive duplications are not allowed. */ if ((syntax & RE_CONTEXT_INVALID_DUP) && (token->type == OP_DUP_ASTERISK || token->type == OP_OPEN_DUP_NUM)) { *err = REG_BADRPT; return NULL; } } return tree; } /* This function build the following tree, from regular expression (): SUBEXP | */ static bin_tree_t * parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *tree; size_t cur_nsub; cur_nsub = preg->re_nsub++; fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); /* The subexpression may be a null string. */ if (token->type == OP_CLOSE_SUBEXP) tree = NULL; else { tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0)) *err = REG_EPAREN; if (BE (*err != REG_NOERROR, 0)) return NULL; } if (cur_nsub <= '9' - '1') dfa->completed_bkref_map |= 1 << cur_nsub; tree = create_tree (dfa, tree, NULL, SUBEXP); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } tree->token.opr.idx = cur_nsub; return tree; } /* This function parse repetition operators like "*", "+", "{1,3}" etc. */ static bin_tree_t * parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) { bin_tree_t *tree = NULL, *old_tree = NULL; int i, start, end, start_idx = re_string_cur_idx (regexp); re_token_t start_token = *token; if (token->type == OP_OPEN_DUP_NUM) { end = 0; start = fetch_number (regexp, token, syntax); if (start == -1) { if (token->type == CHARACTER && token->opr.c == ',') start = 0; /* We treat "{,m}" as "{0,m}". */ else { *err = REG_BADBR; /* {} is invalid. */ return NULL; } } if (BE (start != -2, 1)) { /* We treat "{n}" as "{n,n}". */ end = ((token->type == OP_CLOSE_DUP_NUM) ? start : ((token->type == CHARACTER && token->opr.c == ',') ? fetch_number (regexp, token, syntax) : -2)); } if (BE (start == -2 || end == -2, 0)) { /* Invalid sequence. */ if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0)) { if (token->type == END_OF_RE) *err = REG_EBRACE; else *err = REG_BADBR; return NULL; } /* If the syntax bit is set, rollback. */ re_string_set_index (regexp, start_idx); *token = start_token; token->type = CHARACTER; /* mb_partial and word_char bits should be already initialized by peek_token. */ return elem; } if (BE (end != -1 && start > end, 0)) { /* First number greater than second. */ *err = REG_BADBR; return NULL; } } else { start = (token->type == OP_DUP_PLUS) ? 1 : 0; end = (token->type == OP_DUP_QUESTION) ? 1 : -1; } fetch_token (token, regexp, syntax); if (BE (elem == NULL, 0)) return NULL; if (BE (start == 0 && end == 0, 0)) { postorder (elem, free_tree, NULL); return NULL; } /* Extract "{n,m}" to "...{0,}". */ if (BE (start > 0, 0)) { tree = elem; for (i = 2; i <= start; ++i) { elem = duplicate_tree (elem, dfa); tree = create_tree (dfa, tree, elem, CONCAT); if (BE (elem == NULL || tree == NULL, 0)) goto parse_dup_op_espace; } if (start == end) return tree; /* Duplicate ELEM before it is marked optional. */ elem = duplicate_tree (elem, dfa); old_tree = tree; } else old_tree = NULL; if (elem->token.type == SUBEXP) postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx); tree = create_tree (dfa, elem, NULL, (end == -1 ? OP_DUP_ASTERISK : OP_ALT)); if (BE (tree == NULL, 0)) goto parse_dup_op_espace; /* This loop is actually executed only when end != -1, to rewrite {0,n} as ((...?)?)?... We have already created the start+1-th copy. */ for (i = start + 2; i <= end; ++i) { elem = duplicate_tree (elem, dfa); tree = create_tree (dfa, tree, elem, CONCAT); if (BE (elem == NULL || tree == NULL, 0)) goto parse_dup_op_espace; tree = create_tree (dfa, tree, NULL, OP_ALT); if (BE (tree == NULL, 0)) goto parse_dup_op_espace; } if (old_tree) tree = create_tree (dfa, old_tree, tree, CONCAT); return tree; parse_dup_op_espace: *err = REG_ESPACE; return NULL; } /* Size of the names for collating symbol/equivalence_class/character_class. I'm not sure, but maybe enough. */ #define BRACKET_NAME_BUF_SIZE 32 #ifndef _LIBC /* Local function for parse_bracket_exp only used in case of NOT _LIBC. Build the range expression which starts from START_ELEM, and ends at END_ELEM. The result are written to MBCSET and SBCSET. RANGE_ALLOC is the allocated size of mbcset->range_starts, and mbcset->range_ends, is a pointer argument sinse we may update it. */ static reg_errcode_t internal_function # ifdef RE_ENABLE_I18N build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc, bracket_elem_t *start_elem, bracket_elem_t *end_elem) # else /* not RE_ENABLE_I18N */ build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem, bracket_elem_t *end_elem) # endif /* not RE_ENABLE_I18N */ { unsigned int start_ch, end_ch; /* Equivalence Classes and Character Classes can't be a range start/end. */ if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, 0)) return REG_ERANGE; /* We can handle no multi character collating elements without libc support. */ if (BE ((start_elem->type == COLL_SYM && strlen ((char *) start_elem->opr.name) > 1) || (end_elem->type == COLL_SYM && strlen ((char *) end_elem->opr.name) > 1), 0)) return REG_ECOLLATE; # ifdef RE_ENABLE_I18N { wchar_t wc; wint_t start_wc; wint_t end_wc; wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] : 0)); end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] : 0)); start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM) ? __btowc (start_ch) : start_elem->opr.wch); end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM) ? __btowc (end_ch) : end_elem->opr.wch); if (start_wc == WEOF || end_wc == WEOF) return REG_ECOLLATE; cmp_buf[0] = start_wc; cmp_buf[4] = end_wc; if (wcscoll (cmp_buf, cmp_buf + 4) > 0) return REG_ERANGE; /* Got valid collation sequence values, add them as a new entry. However, for !_LIBC we have no collation elements: if the character set is single byte, the single byte character set that we build below suffices. parse_bracket_exp passes no MBCSET if dfa->mb_cur_max == 1. */ if (mbcset) { /* Check the space of the arrays. */ if (BE (*range_alloc == mbcset->nranges, 0)) { /* There is not enough space, need realloc. */ wchar_t *new_array_start, *new_array_end; int new_nranges; /* +1 in case of mbcset->nranges is 0. */ new_nranges = 2 * mbcset->nranges + 1; /* Use realloc since mbcset->range_starts and mbcset->range_ends are NULL if *range_alloc == 0. */ new_array_start = re_realloc (mbcset->range_starts, wchar_t, new_nranges); new_array_end = re_realloc (mbcset->range_ends, wchar_t, new_nranges); if (BE (new_array_start == NULL || new_array_end == NULL, 0)) return REG_ESPACE; mbcset->range_starts = new_array_start; mbcset->range_ends = new_array_end; *range_alloc = new_nranges; } mbcset->range_starts[mbcset->nranges] = start_wc; mbcset->range_ends[mbcset->nranges++] = end_wc; } /* Build the table for single byte characters. */ for (wc = 0; wc < SBC_MAX; ++wc) { cmp_buf[2] = wc; if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) bitset_set (sbcset, wc); } } # else /* not RE_ENABLE_I18N */ { unsigned int ch; start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] : 0)); end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] : 0)); if (start_ch > end_ch) return REG_ERANGE; /* Build the table for single byte characters. */ for (ch = 0; ch < SBC_MAX; ++ch) if (start_ch <= ch && ch <= end_ch) bitset_set (sbcset, ch); } # endif /* not RE_ENABLE_I18N */ return REG_NOERROR; } #endif /* not _LIBC */ #ifndef _LIBC /* Helper function for parse_bracket_exp only used in case of NOT _LIBC.. Build the collating element which is represented by NAME. The result are written to MBCSET and SBCSET. COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a pointer argument since we may update it. */ static reg_errcode_t internal_function # ifdef RE_ENABLE_I18N build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, int *coll_sym_alloc, const unsigned char *name) # else /* not RE_ENABLE_I18N */ build_collating_symbol (bitset_t sbcset, const unsigned char *name) # endif /* not RE_ENABLE_I18N */ { size_t name_len = strlen ((const char *) name); if (BE (name_len != 1, 0)) return REG_ECOLLATE; else { bitset_set (sbcset, name[0]); return REG_NOERROR; } } #endif /* not _LIBC */ /* This function parse bracket expression like "[abc]", "[a-c]", "[[.a-a.]]" etc. */ static bin_tree_t * parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) { #ifdef _LIBC const unsigned char *collseqmb; const char *collseqwc; uint32_t nrules; int32_t table_size; const int32_t *symb_table; const unsigned char *extra; /* Local function for parse_bracket_exp used in _LIBC environement. Seek the collating symbol entry correspondings to NAME. Return the index of the symbol in the SYMB_TABLE. */ auto inline int32_t __attribute ((always_inline)) seek_collating_symbol_entry (name, name_len) const unsigned char *name; size_t name_len; { int32_t hash = elem_hash ((const char *) name, name_len); int32_t elem = hash % table_size; if (symb_table[2 * elem] != 0) { int32_t second = hash % (table_size - 2) + 1; do { /* First compare the hashing value. */ if (symb_table[2 * elem] == hash /* Compare the length of the name. */ && name_len == extra[symb_table[2 * elem + 1]] /* Compare the name. */ && memcmp (name, &extra[symb_table[2 * elem + 1] + 1], name_len) == 0) { /* Yep, this is the entry. */ break; } /* Next entry. */ elem += second; } while (symb_table[2 * elem] != 0); } return elem; } /* Local function for parse_bracket_exp used in _LIBC environement. Look up the collation sequence value of BR_ELEM. Return the value if succeeded, UINT_MAX otherwise. */ auto inline unsigned int __attribute ((always_inline)) lookup_collation_sequence_value (br_elem) bracket_elem_t *br_elem; { if (br_elem->type == SB_CHAR) { /* if (MB_CUR_MAX == 1) */ if (nrules == 0) return collseqmb[br_elem->opr.ch]; else { wint_t wc = __btowc (br_elem->opr.ch); return __collseq_table_lookup (collseqwc, wc); } } else if (br_elem->type == MB_CHAR) { return __collseq_table_lookup (collseqwc, br_elem->opr.wch); } else if (br_elem->type == COLL_SYM) { size_t sym_name_len = strlen ((char *) br_elem->opr.name); if (nrules != 0) { int32_t elem, idx; elem = seek_collating_symbol_entry (br_elem->opr.name, sym_name_len); if (symb_table[2 * elem] != 0) { /* We found the entry. */ idx = symb_table[2 * elem + 1]; /* Skip the name of collating element name. */ idx += 1 + extra[idx]; /* Skip the byte sequence of the collating element. */ idx += 1 + extra[idx]; /* Adjust for the alignment. */ idx = (idx + 3) & ~3; /* Skip the multibyte collation sequence value. */ idx += sizeof (unsigned int); /* Skip the wide char sequence of the collating element. */ idx += sizeof (unsigned int) * (1 + *(unsigned int *) (extra + idx)); /* Return the collation sequence value. */ return *(unsigned int *) (extra + idx); } else if (symb_table[2 * elem] == 0 && sym_name_len == 1) { /* No valid character. Match it as a single byte character. */ return collseqmb[br_elem->opr.name[0]]; } } else if (sym_name_len == 1) return collseqmb[br_elem->opr.name[0]]; } return UINT_MAX; } /* Local function for parse_bracket_exp used in _LIBC environement. Build the range expression which starts from START_ELEM, and ends at END_ELEM. The result are written to MBCSET and SBCSET. RANGE_ALLOC is the allocated size of mbcset->range_starts, and mbcset->range_ends, is a pointer argument sinse we may update it. */ auto inline reg_errcode_t __attribute ((always_inline)) build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem) re_charset_t *mbcset; int *range_alloc; bitset_t sbcset; bracket_elem_t *start_elem, *end_elem; { unsigned int ch; uint32_t start_collseq; uint32_t end_collseq; /* Equivalence Classes and Character Classes can't be a range start/end. */ if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, 0)) return REG_ERANGE; start_collseq = lookup_collation_sequence_value (start_elem); end_collseq = lookup_collation_sequence_value (end_elem); /* Check start/end collation sequence values. */ if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0)) return REG_ECOLLATE; if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0)) return REG_ERANGE; /* Got valid collation sequence values, add them as a new entry. However, if we have no collation elements, and the character set is single byte, the single byte character set that we build below suffices. */ if (nrules > 0 || dfa->mb_cur_max > 1) { /* Check the space of the arrays. */ if (BE (*range_alloc == mbcset->nranges, 0)) { /* There is not enough space, need realloc. */ uint32_t *new_array_start; uint32_t *new_array_end; int new_nranges; /* +1 in case of mbcset->nranges is 0. */ new_nranges = 2 * mbcset->nranges + 1; new_array_start = re_realloc (mbcset->range_starts, uint32_t, new_nranges); new_array_end = re_realloc (mbcset->range_ends, uint32_t, new_nranges); if (BE (new_array_start == NULL || new_array_end == NULL, 0)) return REG_ESPACE; mbcset->range_starts = new_array_start; mbcset->range_ends = new_array_end; *range_alloc = new_nranges; } mbcset->range_starts[mbcset->nranges] = start_collseq; mbcset->range_ends[mbcset->nranges++] = end_collseq; } /* Build the table for single byte characters. */ for (ch = 0; ch < SBC_MAX; ch++) { uint32_t ch_collseq; /* if (MB_CUR_MAX == 1) */ if (nrules == 0) ch_collseq = collseqmb[ch]; else ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) bitset_set (sbcset, ch); } return REG_NOERROR; } /* Local function for parse_bracket_exp used in _LIBC environement. Build the collating element which is represented by NAME. The result are written to MBCSET and SBCSET. COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a pointer argument sinse we may update it. */ auto inline reg_errcode_t __attribute ((always_inline)) build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name) re_charset_t *mbcset; int *coll_sym_alloc; bitset_t sbcset; const unsigned char *name; { int32_t elem, idx; size_t name_len = strlen ((const char *) name); if (nrules != 0) { elem = seek_collating_symbol_entry (name, name_len); if (symb_table[2 * elem] != 0) { /* We found the entry. */ idx = symb_table[2 * elem + 1]; /* Skip the name of collating element name. */ idx += 1 + extra[idx]; } else if (symb_table[2 * elem] == 0 && name_len == 1) { /* No valid character, treat it as a normal character. */ bitset_set (sbcset, name[0]); return REG_NOERROR; } else return REG_ECOLLATE; /* Got valid collation sequence, add it as a new entry. */ /* Check the space of the arrays. */ if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0)) { /* Not enough, realloc it. */ /* +1 in case of mbcset->ncoll_syms is 0. */ int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; /* Use realloc since mbcset->coll_syms is NULL if *alloc == 0. */ int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, new_coll_sym_alloc); if (BE (new_coll_syms == NULL, 0)) return REG_ESPACE; mbcset->coll_syms = new_coll_syms; *coll_sym_alloc = new_coll_sym_alloc; } mbcset->coll_syms[mbcset->ncoll_syms++] = idx; return REG_NOERROR; } else { if (BE (name_len != 1, 0)) return REG_ECOLLATE; else { bitset_set (sbcset, name[0]); return REG_NOERROR; } } } #endif re_token_t br_token; re_bitset_ptr_t sbcset; #ifdef RE_ENABLE_I18N re_charset_t *mbcset; int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; int equiv_class_alloc = 0, char_class_alloc = 0; #endif /* not RE_ENABLE_I18N */ int non_match = 0; bin_tree_t *work_tree; int token_len; int first_round = 1; #ifdef _LIBC collseqmb = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules) { /* if (MB_CUR_MAX > 1) */ collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_TABLEMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); } #endif sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); #ifdef RE_ENABLE_I18N mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); #endif /* RE_ENABLE_I18N */ #ifdef RE_ENABLE_I18N if (BE (sbcset == NULL || mbcset == NULL, 0)) #else if (BE (sbcset == NULL, 0)) #endif /* RE_ENABLE_I18N */ { *err = REG_ESPACE; return NULL; } token_len = peek_token_bracket (token, regexp, syntax); if (BE (token->type == END_OF_RE, 0)) { *err = REG_BADPAT; goto parse_bracket_exp_free_return; } if (token->type == OP_NON_MATCH_LIST) { #ifdef RE_ENABLE_I18N mbcset->non_match = 1; #endif /* not RE_ENABLE_I18N */ non_match = 1; if (syntax & RE_HAT_LISTS_NOT_NEWLINE) bitset_set (sbcset, '\0'); re_string_skip_bytes (regexp, token_len); /* Skip a token. */ token_len = peek_token_bracket (token, regexp, syntax); if (BE (token->type == END_OF_RE, 0)) { *err = REG_BADPAT; goto parse_bracket_exp_free_return; } } /* We treat the first ']' as a normal character. */ if (token->type == OP_CLOSE_BRACKET) token->type = CHARACTER; while (1) { bracket_elem_t start_elem, end_elem; unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE]; unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE]; reg_errcode_t ret; int token_len2 = 0, is_range_exp = 0; re_token_t token2; start_elem.opr.name = start_name_buf; ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa, syntax, first_round); if (BE (ret != REG_NOERROR, 0)) { *err = ret; goto parse_bracket_exp_free_return; } first_round = 0; /* Get information about the next token. We need it in any case. */ token_len = peek_token_bracket (token, regexp, syntax); /* Do not check for ranges if we know they are not allowed. */ if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS) { if (BE (token->type == END_OF_RE, 0)) { *err = REG_EBRACK; goto parse_bracket_exp_free_return; } if (token->type == OP_CHARSET_RANGE) { re_string_skip_bytes (regexp, token_len); /* Skip '-'. */ token_len2 = peek_token_bracket (&token2, regexp, syntax); if (BE (token2.type == END_OF_RE, 0)) { *err = REG_EBRACK; goto parse_bracket_exp_free_return; } if (token2.type == OP_CLOSE_BRACKET) { /* We treat the last '-' as a normal character. */ re_string_skip_bytes (regexp, -token_len); token->type = CHARACTER; } else is_range_exp = 1; } } if (is_range_exp == 1) { end_elem.opr.name = end_name_buf; ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2, dfa, syntax, 1); if (BE (ret != REG_NOERROR, 0)) { *err = ret; goto parse_bracket_exp_free_return; } token_len = peek_token_bracket (token, regexp, syntax); #ifdef _LIBC *err = build_range_exp (sbcset, mbcset, &range_alloc, &start_elem, &end_elem); #else # ifdef RE_ENABLE_I18N *err = build_range_exp (sbcset, dfa->mb_cur_max > 1 ? mbcset : NULL, &range_alloc, &start_elem, &end_elem); # else *err = build_range_exp (sbcset, &start_elem, &end_elem); # endif #endif /* RE_ENABLE_I18N */ if (BE (*err != REG_NOERROR, 0)) goto parse_bracket_exp_free_return; } else { switch (start_elem.type) { case SB_CHAR: bitset_set (sbcset, start_elem.opr.ch); break; #ifdef RE_ENABLE_I18N case MB_CHAR: /* Check whether the array has enough space. */ if (BE (mbchar_alloc == mbcset->nmbchars, 0)) { wchar_t *new_mbchars; /* Not enough, realloc it. */ /* +1 in case of mbcset->nmbchars is 0. */ mbchar_alloc = 2 * mbcset->nmbchars + 1; /* Use realloc since array is NULL if *alloc == 0. */ new_mbchars = re_realloc (mbcset->mbchars, wchar_t, mbchar_alloc); if (BE (new_mbchars == NULL, 0)) goto parse_bracket_exp_espace; mbcset->mbchars = new_mbchars; } mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; break; #endif /* RE_ENABLE_I18N */ case EQUIV_CLASS: *err = build_equiv_class (sbcset, #ifdef RE_ENABLE_I18N mbcset, &equiv_class_alloc, #endif /* RE_ENABLE_I18N */ start_elem.opr.name); if (BE (*err != REG_NOERROR, 0)) goto parse_bracket_exp_free_return; break; case COLL_SYM: *err = build_collating_symbol (sbcset, #ifdef RE_ENABLE_I18N mbcset, &coll_sym_alloc, #endif /* RE_ENABLE_I18N */ start_elem.opr.name); if (BE (*err != REG_NOERROR, 0)) goto parse_bracket_exp_free_return; break; case CHAR_CLASS: *err = build_charclass (regexp->trans, sbcset, #ifdef RE_ENABLE_I18N mbcset, &char_class_alloc, #endif /* RE_ENABLE_I18N */ start_elem.opr.name, syntax); if (BE (*err != REG_NOERROR, 0)) goto parse_bracket_exp_free_return; break; default: assert (0); break; } } if (BE (token->type == END_OF_RE, 0)) { *err = REG_EBRACK; goto parse_bracket_exp_free_return; } if (token->type == OP_CLOSE_BRACKET) break; } re_string_skip_bytes (regexp, token_len); /* Skip a token. */ /* If it is non-matching list. */ if (non_match) bitset_not (sbcset); #ifdef RE_ENABLE_I18N /* Ensure only single byte characters are set. */ if (dfa->mb_cur_max > 1) bitset_mask (sbcset, dfa->sb_char); if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes || mbcset->non_match))) { bin_tree_t *mbc_tree; int sbc_idx; /* Build a tree for complex bracket. */ dfa->has_mb_node = 1; br_token.type = COMPLEX_BRACKET; br_token.opr.mbcset = mbcset; mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); if (BE (mbc_tree == NULL, 0)) goto parse_bracket_exp_espace; for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx) if (sbcset[sbc_idx]) break; /* If there are no bits set in sbcset, there is no point of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */ if (sbc_idx < BITSET_WORDS) { /* Build a tree for simple bracket. */ br_token.type = SIMPLE_BRACKET; br_token.opr.sbcset = sbcset; work_tree = create_token_tree (dfa, NULL, NULL, &br_token); if (BE (work_tree == NULL, 0)) goto parse_bracket_exp_espace; /* Then join them by ALT node. */ work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT); if (BE (work_tree == NULL, 0)) goto parse_bracket_exp_espace; } else { re_free (sbcset); work_tree = mbc_tree; } } else #endif /* not RE_ENABLE_I18N */ { #ifdef RE_ENABLE_I18N free_charset (mbcset); #endif /* Build a tree for simple bracket. */ br_token.type = SIMPLE_BRACKET; br_token.opr.sbcset = sbcset; work_tree = create_token_tree (dfa, NULL, NULL, &br_token); if (BE (work_tree == NULL, 0)) goto parse_bracket_exp_espace; } return work_tree; parse_bracket_exp_espace: *err = REG_ESPACE; parse_bracket_exp_free_return: re_free (sbcset); #ifdef RE_ENABLE_I18N free_charset (mbcset); #endif /* RE_ENABLE_I18N */ return NULL; } /* Parse an element in the bracket expression. */ static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, re_token_t *token, int token_len, re_dfa_t *dfa, reg_syntax_t syntax, int accept_hyphen) { #ifdef RE_ENABLE_I18N int cur_char_size; cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); if (cur_char_size > 1) { elem->type = MB_CHAR; elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp)); re_string_skip_bytes (regexp, cur_char_size); return REG_NOERROR; } #endif /* RE_ENABLE_I18N */ re_string_skip_bytes (regexp, token_len); /* Skip a token. */ if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS || token->type == OP_OPEN_EQUIV_CLASS) return parse_bracket_symbol (elem, regexp, token); if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen) { /* A '-' must only appear as anything but a range indicator before the closing bracket. Everything else is an error. */ re_token_t token2; (void) peek_token_bracket (&token2, regexp, syntax); if (token2.type != OP_CLOSE_BRACKET) /* The actual error value is not standardized since this whole case is undefined. But ERANGE makes good sense. */ return REG_ERANGE; } elem->type = SB_CHAR; elem->opr.ch = token->opr.c; return REG_NOERROR; } /* Parse a bracket symbol in the bracket expression. Bracket symbols are such as [::], [..], and [==]. */ static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, re_token_t *token) { unsigned char ch, delim = token->opr.c; int i = 0; if (re_string_eoi(regexp)) return REG_EBRACK; for (;; ++i) { if (i >= BRACKET_NAME_BUF_SIZE) return REG_EBRACK; if (token->type == OP_OPEN_CHAR_CLASS) ch = re_string_fetch_byte_case (regexp); else ch = re_string_fetch_byte (regexp); if (re_string_eoi(regexp)) return REG_EBRACK; if (ch == delim && re_string_peek_byte (regexp, 0) == ']') break; elem->opr.name[i] = ch; } re_string_skip_bytes (regexp, 1); elem->opr.name[i] = '\0'; switch (token->type) { case OP_OPEN_COLL_ELEM: elem->type = COLL_SYM; break; case OP_OPEN_EQUIV_CLASS: elem->type = EQUIV_CLASS; break; case OP_OPEN_CHAR_CLASS: elem->type = CHAR_CLASS; break; default: break; } return REG_NOERROR; } /* Helper function for parse_bracket_exp. Build the equivalence class which is represented by NAME. The result are written to MBCSET and SBCSET. EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, is a pointer argument sinse we may update it. */ static reg_errcode_t #ifdef RE_ENABLE_I18N build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, int *equiv_class_alloc, const unsigned char *name) #else /* not RE_ENABLE_I18N */ build_equiv_class (bitset_t sbcset, const unsigned char *name) #endif /* not RE_ENABLE_I18N */ { #ifdef _LIBC uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules != 0) { const int32_t *table, *indirect; const unsigned char *weights, *extra, *cp; unsigned char char_buf[2]; int32_t idx1, idx2; unsigned int ch; size_t len; /* This #include defines a local function! */ # include /* Calculate the index for equivalence class. */ cp = name; table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); idx1 = findidx (&cp); if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0)) /* This isn't a valid character. */ return REG_ECOLLATE; /* Build single byte matcing table for this equivalence class. */ char_buf[1] = (unsigned char) '\0'; len = weights[idx1]; for (ch = 0; ch < SBC_MAX; ++ch) { char_buf[0] = ch; cp = char_buf; idx2 = findidx (&cp); /* idx2 = table[ch]; */ if (idx2 == 0) /* This isn't a valid character. */ continue; if (len == weights[idx2]) { int cnt = 0; while (cnt <= len && weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt]) ++cnt; if (cnt > len) bitset_set (sbcset, ch); } } /* Check whether the array has enough space. */ if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0)) { /* Not enough, realloc it. */ /* +1 in case of mbcset->nequiv_classes is 0. */ int new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1; /* Use realloc since the array is NULL if *alloc == 0. */ int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes, int32_t, new_equiv_class_alloc); if (BE (new_equiv_classes == NULL, 0)) return REG_ESPACE; mbcset->equiv_classes = new_equiv_classes; *equiv_class_alloc = new_equiv_class_alloc; } mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; } else #endif /* _LIBC */ { if (BE (strlen ((const char *) name) != 1, 0)) return REG_ECOLLATE; bitset_set (sbcset, *name); } return REG_NOERROR; } /* Helper function for parse_bracket_exp. Build the character class which is represented by NAME. The result are written to MBCSET and SBCSET. CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, is a pointer argument sinse we may update it. */ static reg_errcode_t #ifdef RE_ENABLE_I18N build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, re_charset_t *mbcset, int *char_class_alloc, const unsigned char *class_name, reg_syntax_t syntax) #else /* not RE_ENABLE_I18N */ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, const unsigned char *class_name, reg_syntax_t syntax) #endif /* not RE_ENABLE_I18N */ { int i; const char *name = (const char *) class_name; /* In case of REG_ICASE "upper" and "lower" match the both of upper and lower cases. */ if ((syntax & RE_ICASE) && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) name = "alpha"; #ifdef RE_ENABLE_I18N /* Check the space of the arrays. */ if (BE (*char_class_alloc == mbcset->nchar_classes, 0)) { /* Not enough, realloc it. */ /* +1 in case of mbcset->nchar_classes is 0. */ int new_char_class_alloc = 2 * mbcset->nchar_classes + 1; /* Use realloc since array is NULL if *alloc == 0. */ wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t, new_char_class_alloc); if (BE (new_char_classes == NULL, 0)) return REG_ESPACE; mbcset->char_classes = new_char_classes; *char_class_alloc = new_char_class_alloc; } mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); #endif /* RE_ENABLE_I18N */ #define BUILD_CHARCLASS_LOOP(ctype_func) \ do { \ if (BE (trans != NULL, 0)) \ { \ for (i = 0; i < SBC_MAX; ++i) \ if (ctype_func (i)) \ bitset_set (sbcset, trans[i]); \ } \ else \ { \ for (i = 0; i < SBC_MAX; ++i) \ if (ctype_func (i)) \ bitset_set (sbcset, i); \ } \ } while (0) if (strcmp (name, "alnum") == 0) BUILD_CHARCLASS_LOOP (isalnum); else if (strcmp (name, "cntrl") == 0) BUILD_CHARCLASS_LOOP (iscntrl); else if (strcmp (name, "lower") == 0) BUILD_CHARCLASS_LOOP (islower); else if (strcmp (name, "space") == 0) BUILD_CHARCLASS_LOOP (isspace); else if (strcmp (name, "alpha") == 0) BUILD_CHARCLASS_LOOP (isalpha); else if (strcmp (name, "digit") == 0) BUILD_CHARCLASS_LOOP (isdigit); else if (strcmp (name, "print") == 0) BUILD_CHARCLASS_LOOP (isprint); else if (strcmp (name, "upper") == 0) BUILD_CHARCLASS_LOOP (isupper); else if (strcmp (name, "blank") == 0) BUILD_CHARCLASS_LOOP (isblank); else if (strcmp (name, "graph") == 0) BUILD_CHARCLASS_LOOP (isgraph); else if (strcmp (name, "punct") == 0) BUILD_CHARCLASS_LOOP (ispunct); else if (strcmp (name, "xdigit") == 0) BUILD_CHARCLASS_LOOP (isxdigit); else return REG_ECTYPE; return REG_NOERROR; } static bin_tree_t * build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, const unsigned char *class_name, const unsigned char *extra, int non_match, reg_errcode_t *err) { re_bitset_ptr_t sbcset; #ifdef RE_ENABLE_I18N re_charset_t *mbcset; int alloc = 0; #endif /* not RE_ENABLE_I18N */ reg_errcode_t ret; re_token_t br_token; bin_tree_t *tree; sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); #ifdef RE_ENABLE_I18N mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); #endif /* RE_ENABLE_I18N */ #ifdef RE_ENABLE_I18N if (BE (sbcset == NULL || mbcset == NULL, 0)) #else /* not RE_ENABLE_I18N */ if (BE (sbcset == NULL, 0)) #endif /* not RE_ENABLE_I18N */ { *err = REG_ESPACE; return NULL; } if (non_match) { #ifdef RE_ENABLE_I18N /* if (syntax & RE_HAT_LISTS_NOT_NEWLINE) bitset_set(cset->sbcset, '\0'); */ mbcset->non_match = 1; #endif /* not RE_ENABLE_I18N */ } /* We don't care the syntax in this case. */ ret = build_charclass (trans, sbcset, #ifdef RE_ENABLE_I18N mbcset, &alloc, #endif /* RE_ENABLE_I18N */ class_name, 0); if (BE (ret != REG_NOERROR, 0)) { re_free (sbcset); #ifdef RE_ENABLE_I18N free_charset (mbcset); #endif /* RE_ENABLE_I18N */ *err = ret; return NULL; } /* \w match '_' also. */ for (; *extra; extra++) bitset_set (sbcset, *extra); /* If it is non-matching list. */ if (non_match) bitset_not (sbcset); #ifdef RE_ENABLE_I18N /* Ensure only single byte characters are set. */ if (dfa->mb_cur_max > 1) bitset_mask (sbcset, dfa->sb_char); #endif /* Build a tree for simple bracket. */ br_token.type = SIMPLE_BRACKET; br_token.opr.sbcset = sbcset; tree = create_token_tree (dfa, NULL, NULL, &br_token); if (BE (tree == NULL, 0)) goto build_word_op_espace; #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { bin_tree_t *mbc_tree; /* Build a tree for complex bracket. */ br_token.type = COMPLEX_BRACKET; br_token.opr.mbcset = mbcset; dfa->has_mb_node = 1; mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); if (BE (mbc_tree == NULL, 0)) goto build_word_op_espace; /* Then join them by ALT node. */ tree = create_tree (dfa, tree, mbc_tree, OP_ALT); if (BE (mbc_tree != NULL, 1)) return tree; } else { free_charset (mbcset); return tree; } #else /* not RE_ENABLE_I18N */ return tree; #endif /* not RE_ENABLE_I18N */ build_word_op_espace: re_free (sbcset); #ifdef RE_ENABLE_I18N free_charset (mbcset); #endif /* RE_ENABLE_I18N */ *err = REG_ESPACE; return NULL; } /* This is intended for the expressions like "a{1,3}". Fetch a number from `input', and return the number. Return -1, if the number field is empty like "{,1}". Return -2, If an error is occured. */ static int fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) { int num = -1; unsigned char c; while (1) { fetch_token (token, input, syntax); c = token->opr.c; if (BE (token->type == END_OF_RE, 0)) return -2; if (token->type == OP_CLOSE_DUP_NUM || c == ',') break; num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2) ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0')); num = (num > RE_DUP_MAX) ? -2 : num; } return num; } #ifdef RE_ENABLE_I18N static void free_charset (re_charset_t *cset) { re_free (cset->mbchars); # ifdef _LIBC re_free (cset->coll_syms); re_free (cset->equiv_classes); re_free (cset->range_starts); re_free (cset->range_ends); # endif re_free (cset->char_classes); re_free (cset); } #endif /* RE_ENABLE_I18N */ /* Functions for binary tree operation. */ /* Create a tree node. */ static bin_tree_t * create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, re_token_type_t type) { re_token_t t; t.type = type; return create_token_tree (dfa, left, right, &t); } static bin_tree_t * create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, const re_token_t *token) { bin_tree_t *tree; if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0)) { bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1); if (storage == NULL) return NULL; storage->next = dfa->str_tree_storage; dfa->str_tree_storage = storage; dfa->str_tree_storage_idx = 0; } tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++]; tree->parent = NULL; tree->left = left; tree->right = right; tree->token = *token; tree->token.duplicated = 0; tree->token.opt_subexp = 0; tree->first = NULL; tree->next = NULL; tree->node_idx = -1; if (left != NULL) left->parent = tree; if (right != NULL) right->parent = tree; return tree; } /* Mark the tree SRC as an optional subexpression. To be called from preorder or postorder. */ static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node) { int idx = (int) (long) extra; if (node->token.type == SUBEXP && node->token.opr.idx == idx) node->token.opt_subexp = 1; return REG_NOERROR; } /* Free the allocated memory inside NODE. */ static void free_token (re_token_t *node) { #ifdef RE_ENABLE_I18N if (node->type == COMPLEX_BRACKET && node->duplicated == 0) free_charset (node->opr.mbcset); else #endif /* RE_ENABLE_I18N */ if (node->type == SIMPLE_BRACKET && node->duplicated == 0) re_free (node->opr.sbcset); } /* Worker function for tree walking. Free the allocated memory inside NODE and its children. */ static reg_errcode_t free_tree (void *extra, bin_tree_t *node) { free_token (&node->token); return REG_NOERROR; } /* Duplicate the node SRC, and return new node. This is a preorder visit similar to the one implemented by the generic visitor, but we need more infrastructure to maintain two parallel trees --- so, it's easier to duplicate. */ static bin_tree_t * duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa) { const bin_tree_t *node; bin_tree_t *dup_root; bin_tree_t **p_new = &dup_root, *dup_node = root->parent; for (node = root; ; ) { /* Create a new tree and link it back to the current parent. */ *p_new = create_token_tree (dfa, NULL, NULL, &node->token); if (*p_new == NULL) return NULL; (*p_new)->parent = dup_node; (*p_new)->token.duplicated = 1; dup_node = *p_new; /* Go to the left node, or up and to the right. */ if (node->left) { node = node->left; p_new = &dup_node->left; } else { const bin_tree_t *prev = NULL; while (node->right == prev || node->right == NULL) { prev = node; node = node->parent; dup_node = dup_node->parent; if (!node) return dup_root; } node = node->right; p_new = &dup_node->right; } } } kbuild-3686/src/oldsed/lib/regex_internal.c0000664000175000017500000012776615053010105020706 0ustar locutuslocutus/* Extended regular expression matching and search library. Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ static void re_string_construct_common (const char *str, int len, re_string_t *pstr, RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) internal_function; static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, unsigned int hash) internal_function; static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, unsigned int context, unsigned int hash) internal_function; /* Functions for string operation. */ /* This function allocate the buffers. It is necessary to call re_string_reconstruct before using the object. */ static reg_errcode_t internal_function re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len, RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) { reg_errcode_t ret; int init_buf_len; /* Ensure at least one character fits into the buffers. */ if (init_len < dfa->mb_cur_max) init_len = dfa->mb_cur_max; init_buf_len = (len + 1 < init_len) ? len + 1: init_len; re_string_construct_common (str, len, pstr, trans, icase, dfa); ret = re_string_realloc_buffers (pstr, init_buf_len); if (BE (ret != REG_NOERROR, 0)) return ret; pstr->word_char = dfa->word_char; pstr->word_ops_used = dfa->word_ops_used; pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; pstr->valid_raw_len = pstr->valid_len; return REG_NOERROR; } /* This function allocate the buffers, and initialize them. */ static reg_errcode_t internal_function re_string_construct (re_string_t *pstr, const char *str, int len, RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) { reg_errcode_t ret; memset (pstr, '\0', sizeof (re_string_t)); re_string_construct_common (str, len, pstr, trans, icase, dfa); if (len > 0) { ret = re_string_realloc_buffers (pstr, len + 1); if (BE (ret != REG_NOERROR, 0)) return ret; } pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; if (icase) { #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { while (1) { ret = build_wcs_upper_buffer (pstr); if (BE (ret != REG_NOERROR, 0)) return ret; if (pstr->valid_raw_len >= len) break; if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) break; ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); if (BE (ret != REG_NOERROR, 0)) return ret; } } else #endif /* RE_ENABLE_I18N */ build_upper_buffer (pstr); } else { #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) build_wcs_buffer (pstr); else #endif /* RE_ENABLE_I18N */ { if (trans != NULL) re_string_translate_buffer (pstr); else { pstr->valid_len = pstr->bufs_len; pstr->valid_raw_len = pstr->bufs_len; } } } return REG_NOERROR; } /* Helper functions for re_string_allocate, and re_string_construct. */ static reg_errcode_t internal_function re_string_realloc_buffers (re_string_t *pstr, int new_buf_len) { #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); if (BE (new_wcs == NULL, 0)) return REG_ESPACE; pstr->wcs = new_wcs; if (pstr->offsets != NULL) { int *new_offsets = re_realloc (pstr->offsets, int, new_buf_len); if (BE (new_offsets == NULL, 0)) return REG_ESPACE; pstr->offsets = new_offsets; } } #endif /* RE_ENABLE_I18N */ if (pstr->mbs_allocated) { unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char, new_buf_len); if (BE (new_mbs == NULL, 0)) return REG_ESPACE; pstr->mbs = new_mbs; } pstr->bufs_len = new_buf_len; return REG_NOERROR; } static void internal_function re_string_construct_common (const char *str, int len, re_string_t *pstr, RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) { pstr->raw_mbs = (const unsigned char *) str; pstr->len = len; pstr->raw_len = len; pstr->trans = trans; pstr->icase = icase ? 1 : 0; pstr->mbs_allocated = (trans != NULL || icase); pstr->mb_cur_max = dfa->mb_cur_max; pstr->is_utf8 = dfa->is_utf8; pstr->map_notascii = dfa->map_notascii; pstr->stop = pstr->len; pstr->raw_stop = pstr->stop; } #ifdef RE_ENABLE_I18N /* Build wide character buffer PSTR->WCS. If the byte sequence of the string are: (0), (1), (0), (1), Then wide character buffer will be: , WEOF , , WEOF , We use WEOF for padding, they indicate that the position isn't a first byte of a multibyte character. Note that this function assumes PSTR->VALID_LEN elements are already built and starts from PSTR->VALID_LEN. */ static void internal_function build_wcs_buffer (re_string_t *pstr) { #ifdef _LIBC unsigned char buf[MB_LEN_MAX]; assert (MB_LEN_MAX >= pstr->mb_cur_max); #else unsigned char buf[64]; #endif mbstate_t prev_st; int byte_idx, end_idx, remain_len; size_t mbclen; /* Build the buffers from pstr->valid_len to either pstr->len or pstr->bufs_len. */ end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; for (byte_idx = pstr->valid_len; byte_idx < end_idx;) { wchar_t wc; const char *p; remain_len = end_idx - byte_idx; prev_st = pstr->cur_state; /* Apply the translation if we need. */ if (BE (pstr->trans != NULL, 0)) { int i, ch; for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) { ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; } p = (const char *) buf; } else p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); if (BE (mbclen == (size_t) -2, 0)) { /* The buffer doesn't have enough space, finish to build. */ pstr->cur_state = prev_st; break; } else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0)) { /* We treat these cases as a singlebyte character. */ mbclen = 1; wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; if (BE (pstr->trans != NULL, 0)) wc = pstr->trans[wc]; pstr->cur_state = prev_st; } /* Write wide character and padding. */ pstr->wcs[byte_idx++] = wc; /* Write paddings. */ for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } pstr->valid_len = byte_idx; pstr->valid_raw_len = byte_idx; } /* Build wide character buffer PSTR->WCS like build_wcs_buffer, but for REG_ICASE. */ static int internal_function build_wcs_upper_buffer (re_string_t *pstr) { mbstate_t prev_st; int src_idx, byte_idx, end_idx, remain_len; size_t mbclen; #ifdef _LIBC char buf[MB_LEN_MAX]; assert (MB_LEN_MAX >= pstr->mb_cur_max); #else char buf[64]; #endif byte_idx = pstr->valid_len; end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; /* The following optimization assumes that ASCII characters can be mapped to wide characters with a simple cast. */ if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed) { while (byte_idx < end_idx) { wchar_t wc; if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]) && mbsinit (&pstr->cur_state)) { /* In case of a singlebyte character. */ pstr->mbs[byte_idx] = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]); /* The next step uses the assumption that wchar_t is encoded ASCII-safe: all ASCII values can be converted like this. */ pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx]; ++byte_idx; continue; } remain_len = end_idx - byte_idx; prev_st = pstr->cur_state; mbclen = mbrtowc (&wc, ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx), remain_len, &pstr->cur_state); if (BE (mbclen + 2 > 2, 1)) { wchar_t wcu = wc; if (iswlower (wc)) { size_t mbcdlen; wcu = towupper (wc); mbcdlen = wcrtomb (buf, wcu, &prev_st); if (BE (mbclen == mbcdlen, 1)) memcpy (pstr->mbs + byte_idx, buf, mbclen); else { src_idx = byte_idx; goto offsets_needed; } } else memcpy (pstr->mbs + byte_idx, pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen); pstr->wcs[byte_idx++] = wcu; /* Write paddings. */ for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } else if (mbclen == (size_t) -1 || mbclen == 0) { /* It is an invalid character or '\0'. Just use the byte. */ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; pstr->mbs[byte_idx] = ch; /* And also cast it to wide char. */ pstr->wcs[byte_idx++] = (wchar_t) ch; if (BE (mbclen == (size_t) -1, 0)) pstr->cur_state = prev_st; } else { /* The buffer doesn't have enough space, finish to build. */ pstr->cur_state = prev_st; break; } } pstr->valid_len = byte_idx; pstr->valid_raw_len = byte_idx; return REG_NOERROR; } else for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;) { wchar_t wc; const char *p; offsets_needed: remain_len = end_idx - byte_idx; prev_st = pstr->cur_state; if (BE (pstr->trans != NULL, 0)) { int i, ch; for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) { ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; buf[i] = pstr->trans[ch]; } p = (const char *) buf; } else p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); if (BE (mbclen + 2 > 2, 1)) { wchar_t wcu = wc; if (iswlower (wc)) { size_t mbcdlen; wcu = towupper (wc); mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st); if (BE (mbclen == mbcdlen, 1)) memcpy (pstr->mbs + byte_idx, buf, mbclen); else if (mbcdlen != (size_t) -1) { size_t i; if (byte_idx + mbcdlen > pstr->bufs_len) { pstr->cur_state = prev_st; break; } if (pstr->offsets == NULL) { pstr->offsets = re_malloc (int, pstr->bufs_len); if (pstr->offsets == NULL) return REG_ESPACE; } if (!pstr->offsets_needed) { for (i = 0; i < (size_t) byte_idx; ++i) pstr->offsets[i] = i; pstr->offsets_needed = 1; } memcpy (pstr->mbs + byte_idx, buf, mbcdlen); pstr->wcs[byte_idx] = wcu; pstr->offsets[byte_idx] = src_idx; for (i = 1; i < mbcdlen; ++i) { pstr->offsets[byte_idx + i] = src_idx + (i < mbclen ? i : mbclen - 1); pstr->wcs[byte_idx + i] = WEOF; } pstr->len += mbcdlen - mbclen; if (pstr->raw_stop > src_idx) pstr->stop += mbcdlen - mbclen; end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; byte_idx += mbcdlen; src_idx += mbclen; continue; } else memcpy (pstr->mbs + byte_idx, p, mbclen); } else memcpy (pstr->mbs + byte_idx, p, mbclen); if (BE (pstr->offsets_needed != 0, 0)) { size_t i; for (i = 0; i < mbclen; ++i) pstr->offsets[byte_idx + i] = src_idx + i; } src_idx += mbclen; pstr->wcs[byte_idx++] = wcu; /* Write paddings. */ for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } else if (mbclen == (size_t) -1 || mbclen == 0) { /* It is an invalid character or '\0'. Just use the byte. */ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; if (BE (pstr->trans != NULL, 0)) ch = pstr->trans [ch]; pstr->mbs[byte_idx] = ch; if (BE (pstr->offsets_needed != 0, 0)) pstr->offsets[byte_idx] = src_idx; ++src_idx; /* And also cast it to wide char. */ pstr->wcs[byte_idx++] = (wchar_t) ch; if (BE (mbclen == (size_t) -1, 0)) pstr->cur_state = prev_st; } else { /* The buffer doesn't have enough space, finish to build. */ pstr->cur_state = prev_st; break; } } pstr->valid_len = byte_idx; pstr->valid_raw_len = src_idx; return REG_NOERROR; } /* Skip characters until the index becomes greater than NEW_RAW_IDX. Return the index. */ static int internal_function re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc) { mbstate_t prev_st; int rawbuf_idx; size_t mbclen; wchar_t wc = 0; /* Skip the characters which are not necessary to check. */ for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len; rawbuf_idx < new_raw_idx;) { int remain_len; remain_len = pstr->len - rawbuf_idx; prev_st = pstr->cur_state; mbclen = mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx, remain_len, &pstr->cur_state); if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0)) { /* We treat these cases as a singlebyte character. */ mbclen = 1; pstr->cur_state = prev_st; } /* Then proceed the next character. */ rawbuf_idx += mbclen; } *last_wc = (wint_t) wc; return rawbuf_idx; } #endif /* RE_ENABLE_I18N */ /* Build the buffer PSTR->MBS, and apply the translation if we need. This function is used in case of REG_ICASE. */ static void internal_function build_upper_buffer (re_string_t *pstr) { int char_idx, end_idx; end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx) { int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx]; if (BE (pstr->trans != NULL, 0)) ch = pstr->trans[ch]; if (islower (ch)) pstr->mbs[char_idx] = toupper (ch); else pstr->mbs[char_idx] = ch; } pstr->valid_len = char_idx; pstr->valid_raw_len = char_idx; } /* Apply TRANS to the buffer in PSTR. */ static void internal_function re_string_translate_buffer (re_string_t *pstr) { int buf_idx, end_idx; end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx) { int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx]; pstr->mbs[buf_idx] = pstr->trans[ch]; } pstr->valid_len = buf_idx; pstr->valid_raw_len = buf_idx; } /* This function re-construct the buffers. Concretely, convert to wide character in case of pstr->mb_cur_max > 1, convert to upper case in case of REG_ICASE, apply translation. */ static reg_errcode_t internal_function re_string_reconstruct (re_string_t *pstr, int idx, int eflags) { int offset = idx - pstr->raw_mbs_idx; if (BE (offset < 0, 0)) { /* Reset buffer. */ #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); #endif /* RE_ENABLE_I18N */ pstr->len = pstr->raw_len; pstr->stop = pstr->raw_stop; pstr->valid_len = 0; pstr->raw_mbs_idx = 0; pstr->valid_raw_len = 0; pstr->offsets_needed = 0; pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF : CONTEXT_NEWLINE | CONTEXT_BEGBUF); if (!pstr->mbs_allocated) pstr->mbs = (unsigned char *) pstr->raw_mbs; offset = idx; } if (BE (offset != 0, 1)) { /* Are the characters which are already checked remain? */ if (BE (offset < pstr->valid_raw_len, 1) #ifdef RE_ENABLE_I18N /* Handling this would enlarge the code too much. Accept a slowdown in that case. */ && pstr->offsets_needed == 0 #endif ) { /* Yes, move them to the front of the buffer. */ pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags); #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) memmove (pstr->wcs, pstr->wcs + offset, (pstr->valid_len - offset) * sizeof (wint_t)); #endif /* RE_ENABLE_I18N */ if (BE (pstr->mbs_allocated, 0)) memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset); pstr->valid_len -= offset; pstr->valid_raw_len -= offset; #if DEBUG assert (pstr->valid_len > 0); #endif } else { /* No, skip all characters until IDX. */ #ifdef RE_ENABLE_I18N if (BE (pstr->offsets_needed, 0)) { pstr->len = pstr->raw_len - idx + offset; pstr->stop = pstr->raw_stop - idx + offset; pstr->offsets_needed = 0; } #endif pstr->valid_len = 0; pstr->valid_raw_len = 0; #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { int wcs_idx; wint_t wc = WEOF; if (pstr->is_utf8) { const unsigned char *raw, *p, *q, *end; /* Special case UTF-8. Multi-byte chars start with any byte other than 0x80 - 0xbf. */ raw = pstr->raw_mbs + pstr->raw_mbs_idx; end = raw + (offset - pstr->mb_cur_max); p = raw + offset - 1; #ifdef _LIBC /* We know the wchar_t encoding is UCS4, so for the simple case, ASCII characters, skip the conversion step. */ if (isascii (*p) && BE (pstr->trans == NULL, 1)) { memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); pstr->valid_len = 0; wc = (wchar_t) *p; } else #endif for (; p >= end; --p) if ((*p & 0xc0) != 0x80) { mbstate_t cur_state; wchar_t wc2; int mlen = raw + pstr->len - p; unsigned char buf[6]; size_t mbclen; q = p; if (BE (pstr->trans != NULL, 0)) { int i = mlen < 6 ? mlen : 6; while (--i >= 0) buf[i] = pstr->trans[p[i]]; q = buf; } /* XXX Don't use mbrtowc, we know which conversion to use (UTF-8 -> UCS4). */ memset (&cur_state, 0, sizeof (cur_state)); mbclen = mbrtowc (&wc2, (const char *) p, mlen, &cur_state); if (raw + offset - p <= mbclen && mbclen < (size_t) -2) { memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); pstr->valid_len = mbclen - (raw + offset - p); wc = wc2; } break; } } if (wc == WEOF) pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; if (BE (pstr->valid_len, 0)) { for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx) pstr->wcs[wcs_idx] = WEOF; if (pstr->mbs_allocated) memset (pstr->mbs, 255, pstr->valid_len); } pstr->valid_raw_len = pstr->valid_len; pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc)) ? CONTEXT_WORD : ((IS_WIDE_NEWLINE (wc) && pstr->newline_anchor) ? CONTEXT_NEWLINE : 0)); } else #endif /* RE_ENABLE_I18N */ { int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; if (pstr->trans) c = pstr->trans[c]; pstr->tip_context = (bitset_contain (pstr->word_char, c) ? CONTEXT_WORD : ((IS_NEWLINE (c) && pstr->newline_anchor) ? CONTEXT_NEWLINE : 0)); } } if (!BE (pstr->mbs_allocated, 0)) pstr->mbs += offset; } pstr->raw_mbs_idx = idx; pstr->len -= offset; pstr->stop -= offset; /* Then build the buffers. */ #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { if (pstr->icase) { int ret = build_wcs_upper_buffer (pstr); if (BE (ret != REG_NOERROR, 0)) return ret; } else build_wcs_buffer (pstr); } else #endif /* RE_ENABLE_I18N */ if (BE (pstr->mbs_allocated, 0)) { if (pstr->icase) build_upper_buffer (pstr); else if (pstr->trans != NULL) re_string_translate_buffer (pstr); } else pstr->valid_len = pstr->len; pstr->cur_idx = 0; return REG_NOERROR; } static unsigned char internal_function __attribute ((pure)) re_string_peek_byte_case (const re_string_t *pstr, int idx) { int ch, off; /* Handle the common (easiest) cases first. */ if (BE (!pstr->mbs_allocated, 1)) return re_string_peek_byte (pstr, idx); #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1 && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) return re_string_peek_byte (pstr, idx); #endif off = pstr->cur_idx + idx; #ifdef RE_ENABLE_I18N if (pstr->offsets_needed) off = pstr->offsets[off]; #endif ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; #ifdef RE_ENABLE_I18N /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I this function returns CAPITAL LETTER I instead of first byte of DOTLESS SMALL LETTER I. The latter would confuse the parser, since peek_byte_case doesn't advance cur_idx in any way. */ if (pstr->offsets_needed && !isascii (ch)) return re_string_peek_byte (pstr, idx); #endif return ch; } static unsigned char internal_function re_string_fetch_byte_case (re_string_t *pstr) { if (BE (!pstr->mbs_allocated, 1)) return re_string_fetch_byte (pstr); #ifdef RE_ENABLE_I18N if (pstr->offsets_needed) { int off, ch; /* For tr_TR.UTF-8 [[:islower:]] there is [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip in that case the whole multi-byte character and return the original letter. On the other side, with [[: DOTLESS SMALL LETTER I return [[:I, as doing anything else would complicate things too much. */ if (!re_string_first_byte (pstr, pstr->cur_idx)) return re_string_fetch_byte (pstr); off = pstr->offsets[pstr->cur_idx]; ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; if (! isascii (ch)) return re_string_fetch_byte (pstr); re_string_skip_bytes (pstr, re_string_char_size_at (pstr, pstr->cur_idx)); return ch; } #endif return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; } static void internal_function re_string_destruct (re_string_t *pstr) { #ifdef RE_ENABLE_I18N re_free (pstr->wcs); re_free (pstr->offsets); #endif /* RE_ENABLE_I18N */ if (pstr->mbs_allocated) re_free (pstr->mbs); } /* Return the context at IDX in INPUT. */ static unsigned int internal_function re_string_context_at (const re_string_t *input, int idx, int eflags) { int c; if (BE (idx < 0, 0)) /* In this case, we use the value stored in input->tip_context, since we can't know the character in input->mbs[-1] here. */ return input->tip_context; if (BE (idx == input->len, 0)) return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF : CONTEXT_NEWLINE | CONTEXT_ENDBUF); #ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1) { wint_t wc; int wc_idx = idx; while(input->wcs[wc_idx] == WEOF) { #ifdef DEBUG /* It must not happen. */ assert (wc_idx >= 0); #endif --wc_idx; if (wc_idx < 0) return input->tip_context; } wc = input->wcs[wc_idx]; if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc)) return CONTEXT_WORD; return (IS_WIDE_NEWLINE (wc) && input->newline_anchor ? CONTEXT_NEWLINE : 0); } else #endif { c = re_string_byte_at (input, idx); if (bitset_contain (input->word_char, c)) return CONTEXT_WORD; return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0; } } /* Functions for set operation. */ static reg_errcode_t internal_function re_node_set_alloc (re_node_set *set, int size) { set->alloc = size; set->nelem = 0; set->elems = re_malloc (int, size); if (BE (set->elems == NULL, 0)) return REG_ESPACE; return REG_NOERROR; } static reg_errcode_t internal_function re_node_set_init_1 (re_node_set *set, int elem) { set->alloc = 1; set->nelem = 1; set->elems = re_malloc (int, 1); if (BE (set->elems == NULL, 0)) { set->alloc = set->nelem = 0; return REG_ESPACE; } set->elems[0] = elem; return REG_NOERROR; } static reg_errcode_t internal_function re_node_set_init_2 (re_node_set *set, int elem1, int elem2) { set->alloc = 2; set->elems = re_malloc (int, 2); if (BE (set->elems == NULL, 0)) return REG_ESPACE; if (elem1 == elem2) { set->nelem = 1; set->elems[0] = elem1; } else { set->nelem = 2; if (elem1 < elem2) { set->elems[0] = elem1; set->elems[1] = elem2; } else { set->elems[0] = elem2; set->elems[1] = elem1; } } return REG_NOERROR; } static reg_errcode_t internal_function re_node_set_init_copy (re_node_set *dest, const re_node_set *src) { dest->nelem = src->nelem; if (src->nelem > 0) { dest->alloc = dest->nelem; dest->elems = re_malloc (int, dest->alloc); if (BE (dest->elems == NULL, 0)) { dest->alloc = dest->nelem = 0; return REG_ESPACE; } memcpy (dest->elems, src->elems, src->nelem * sizeof (int)); } else re_node_set_init_empty (dest); return REG_NOERROR; } /* Calculate the intersection of the sets SRC1 and SRC2. And merge it to DEST. Return value indicate the error code or REG_NOERROR if succeeded. Note: We assume dest->elems is NULL, when dest->alloc is 0. */ static reg_errcode_t internal_function re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, const re_node_set *src2) { int i1, i2, is, id, delta, sbase; if (src1->nelem == 0 || src2->nelem == 0) return REG_NOERROR; /* We need dest->nelem + 2 * elems_in_intersection; this is a conservative estimate. */ if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) { int new_alloc = src1->nelem + src2->nelem + dest->alloc; int *new_elems = re_realloc (dest->elems, int, new_alloc); if (BE (new_elems == NULL, 0)) return REG_ESPACE; dest->elems = new_elems; dest->alloc = new_alloc; } /* Find the items in the intersection of SRC1 and SRC2, and copy into the top of DEST those that are not already in DEST itself. */ sbase = dest->nelem + src1->nelem + src2->nelem; i1 = src1->nelem - 1; i2 = src2->nelem - 1; id = dest->nelem - 1; for (;;) { if (src1->elems[i1] == src2->elems[i2]) { /* Try to find the item in DEST. Maybe we could binary search? */ while (id >= 0 && dest->elems[id] > src1->elems[i1]) --id; if (id < 0 || dest->elems[id] != src1->elems[i1]) dest->elems[--sbase] = src1->elems[i1]; if (--i1 < 0 || --i2 < 0) break; } /* Lower the highest of the two items. */ else if (src1->elems[i1] < src2->elems[i2]) { if (--i2 < 0) break; } else { if (--i1 < 0) break; } } id = dest->nelem - 1; is = dest->nelem + src1->nelem + src2->nelem - 1; delta = is - sbase + 1; /* Now copy. When DELTA becomes zero, the remaining DEST elements are already in place; this is more or less the same loop that is in re_node_set_merge. */ dest->nelem += delta; if (delta > 0 && id >= 0) for (;;) { if (dest->elems[is] > dest->elems[id]) { /* Copy from the top. */ dest->elems[id + delta--] = dest->elems[is--]; if (delta == 0) break; } else { /* Slide from the bottom. */ dest->elems[id + delta] = dest->elems[id]; if (--id < 0) break; } } /* Copy remaining SRC elements. */ memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int)); return REG_NOERROR; } /* Calculate the union set of the sets SRC1 and SRC2. And store it to DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ static reg_errcode_t internal_function re_node_set_init_union (re_node_set *dest, const re_node_set *src1, const re_node_set *src2) { int i1, i2, id; if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) { dest->alloc = src1->nelem + src2->nelem; dest->elems = re_malloc (int, dest->alloc); if (BE (dest->elems == NULL, 0)) return REG_ESPACE; } else { if (src1 != NULL && src1->nelem > 0) return re_node_set_init_copy (dest, src1); else if (src2 != NULL && src2->nelem > 0) return re_node_set_init_copy (dest, src2); else re_node_set_init_empty (dest); return REG_NOERROR; } for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;) { if (src1->elems[i1] > src2->elems[i2]) { dest->elems[id++] = src2->elems[i2++]; continue; } if (src1->elems[i1] == src2->elems[i2]) ++i2; dest->elems[id++] = src1->elems[i1++]; } if (i1 < src1->nelem) { memcpy (dest->elems + id, src1->elems + i1, (src1->nelem - i1) * sizeof (int)); id += src1->nelem - i1; } else if (i2 < src2->nelem) { memcpy (dest->elems + id, src2->elems + i2, (src2->nelem - i2) * sizeof (int)); id += src2->nelem - i2; } dest->nelem = id; return REG_NOERROR; } /* Calculate the union set of the sets DEST and SRC. And store it to DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ static reg_errcode_t internal_function re_node_set_merge (re_node_set *dest, const re_node_set *src) { int is, id, sbase, delta; if (src == NULL || src->nelem == 0) return REG_NOERROR; if (dest->alloc < 2 * src->nelem + dest->nelem) { int new_alloc = 2 * (src->nelem + dest->alloc); int *new_buffer = re_realloc (dest->elems, int, new_alloc); if (BE (new_buffer == NULL, 0)) return REG_ESPACE; dest->elems = new_buffer; dest->alloc = new_alloc; } if (BE (dest->nelem == 0, 0)) { dest->nelem = src->nelem; memcpy (dest->elems, src->elems, src->nelem * sizeof (int)); return REG_NOERROR; } /* Copy into the top of DEST the items of SRC that are not found in DEST. Maybe we could binary search in DEST? */ for (sbase = dest->nelem + 2 * src->nelem, is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; ) { if (dest->elems[id] == src->elems[is]) is--, id--; else if (dest->elems[id] < src->elems[is]) dest->elems[--sbase] = src->elems[is--]; else /* if (dest->elems[id] > src->elems[is]) */ --id; } if (is >= 0) { /* If DEST is exhausted, the remaining items of SRC must be unique. */ sbase -= is + 1; memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (int)); } id = dest->nelem - 1; is = dest->nelem + 2 * src->nelem - 1; delta = is - sbase + 1; if (delta == 0) return REG_NOERROR; /* Now copy. When DELTA becomes zero, the remaining DEST elements are already in place. */ dest->nelem += delta; for (;;) { if (dest->elems[is] > dest->elems[id]) { /* Copy from the top. */ dest->elems[id + delta--] = dest->elems[is--]; if (delta == 0) break; } else { /* Slide from the bottom. */ dest->elems[id + delta] = dest->elems[id]; if (--id < 0) { /* Copy remaining SRC elements. */ memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int)); break; } } } return REG_NOERROR; } /* Insert the new element ELEM to the re_node_set* SET. SET should not already have ELEM. return -1 if an error is occured, return 1 otherwise. */ static int internal_function re_node_set_insert (re_node_set *set, int elem) { int idx; /* In case the set is empty. */ if (set->alloc == 0) { if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1)) return 1; else return -1; } if (BE (set->nelem, 0) == 0) { /* We already guaranteed above that set->alloc != 0. */ set->elems[0] = elem; ++set->nelem; return 1; } /* Realloc if we need. */ if (set->alloc == set->nelem) { int *new_elems; set->alloc = set->alloc * 2; new_elems = re_realloc (set->elems, int, set->alloc); if (BE (new_elems == NULL, 0)) return -1; set->elems = new_elems; } /* Move the elements which follows the new element. Test the first element separately to skip a check in the inner loop. */ if (elem < set->elems[0]) { idx = 0; for (idx = set->nelem; idx > 0; idx--) set->elems[idx] = set->elems[idx - 1]; } else { for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) set->elems[idx] = set->elems[idx - 1]; } /* Insert the new element. */ set->elems[idx] = elem; ++set->nelem; return 1; } /* Insert the new element ELEM to the re_node_set* SET. SET should not already have any element greater than or equal to ELEM. Return -1 if an error is occured, return 1 otherwise. */ static int internal_function re_node_set_insert_last (re_node_set *set, int elem) { /* Realloc if we need. */ if (set->alloc == set->nelem) { int *new_elems; set->alloc = (set->alloc + 1) * 2; new_elems = re_realloc (set->elems, int, set->alloc); if (BE (new_elems == NULL, 0)) return -1; set->elems = new_elems; } /* Insert the new element. */ set->elems[set->nelem++] = elem; return 1; } /* Compare two node sets SET1 and SET2. return 1 if SET1 and SET2 are equivalent, return 0 otherwise. */ static int internal_function __attribute ((pure)) re_node_set_compare (const re_node_set *set1, const re_node_set *set2) { int i; if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem) return 0; for (i = set1->nelem ; --i >= 0 ; ) if (set1->elems[i] != set2->elems[i]) return 0; return 1; } /* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ static int internal_function __attribute ((pure)) re_node_set_contains (const re_node_set *set, int elem) { unsigned int idx, right, mid; if (set->nelem <= 0) return 0; /* Binary search the element. */ idx = 0; right = set->nelem - 1; while (idx < right) { mid = (idx + right) / 2; if (set->elems[mid] < elem) idx = mid + 1; else right = mid; } return set->elems[idx] == elem ? idx + 1 : 0; } static void internal_function re_node_set_remove_at (re_node_set *set, int idx) { if (idx < 0 || idx >= set->nelem) return; --set->nelem; for (; idx < set->nelem; idx++) set->elems[idx] = set->elems[idx + 1]; } /* Add the token TOKEN to dfa->nodes, and return the index of the token. Or return -1, if an error will be occured. */ static int internal_function re_dfa_add_node (re_dfa_t *dfa, re_token_t token) { int type = token.type; if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0)) { size_t new_nodes_alloc = dfa->nodes_alloc * 2; int *new_nexts, *new_indices; re_node_set *new_edests, *new_eclosures; re_token_t *new_nodes; /* Avoid overflows. */ if (BE (new_nodes_alloc < dfa->nodes_alloc, 0)) return -1; new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); if (BE (new_nodes == NULL, 0)) return -1; dfa->nodes = new_nodes; new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc); new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc); new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); if (BE (new_nexts == NULL || new_indices == NULL || new_edests == NULL || new_eclosures == NULL, 0)) return -1; dfa->nexts = new_nexts; dfa->org_indices = new_indices; dfa->edests = new_edests; dfa->eclosures = new_eclosures; dfa->nodes_alloc = new_nodes_alloc; } dfa->nodes[dfa->nodes_len] = token; dfa->nodes[dfa->nodes_len].constraint = 0; #ifdef RE_ENABLE_I18N dfa->nodes[dfa->nodes_len].accept_mb = (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET; #endif dfa->nexts[dfa->nodes_len] = -1; re_node_set_init_empty (dfa->edests + dfa->nodes_len); re_node_set_init_empty (dfa->eclosures + dfa->nodes_len); return dfa->nodes_len++; } static inline unsigned int internal_function calc_state_hash (const re_node_set *nodes, unsigned int context) { unsigned int hash = nodes->nelem + context; int i; for (i = 0 ; i < nodes->nelem ; i++) hash += nodes->elems[i]; return hash; } /* Search for the state whose node_set is equivalent to NODES. Return the pointer to the state, if we found it in the DFA. Otherwise create the new one and return it. In case of an error return NULL and set the error code in ERR. Note: - We assume NULL as the invalid state, then it is possible that return value is NULL and ERR is REG_NOERROR. - We never return non-NULL value in case of any errors, it is for optimization. */ static re_dfastate_t * internal_function re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, const re_node_set *nodes) { unsigned int hash; re_dfastate_t *new_state; struct re_state_table_entry *spot; int i; if (BE (nodes->nelem == 0, 0)) { *err = REG_NOERROR; return NULL; } hash = calc_state_hash (nodes, 0); spot = dfa->state_table + (hash & dfa->state_hash_mask); for (i = 0 ; i < spot->num ; i++) { re_dfastate_t *state = spot->array[i]; if (hash != state->hash) continue; if (re_node_set_compare (&state->nodes, nodes)) return state; } /* There are no appropriate state in the dfa, create the new one. */ new_state = create_ci_newstate (dfa, nodes, hash); if (BE (new_state == NULL, 0)) *err = REG_ESPACE; return new_state; } /* Search for the state whose node_set is equivalent to NODES and whose context is equivalent to CONTEXT. Return the pointer to the state, if we found it in the DFA. Otherwise create the new one and return it. In case of an error return NULL and set the error code in ERR. Note: - We assume NULL as the invalid state, then it is possible that return value is NULL and ERR is REG_NOERROR. - We never return non-NULL value in case of any errors, it is for optimization. */ static re_dfastate_t * internal_function re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, const re_node_set *nodes, unsigned int context) { unsigned int hash; re_dfastate_t *new_state; struct re_state_table_entry *spot; int i; if (nodes->nelem == 0) { *err = REG_NOERROR; return NULL; } hash = calc_state_hash (nodes, context); spot = dfa->state_table + (hash & dfa->state_hash_mask); for (i = 0 ; i < spot->num ; i++) { re_dfastate_t *state = spot->array[i]; if (state->hash == hash && state->context == context && re_node_set_compare (state->entrance_nodes, nodes)) return state; } /* There are no appropriate state in `dfa', create the new one. */ new_state = create_cd_newstate (dfa, nodes, context, hash); if (BE (new_state == NULL, 0)) *err = REG_ESPACE; return new_state; } /* Finish initialization of the new state NEWSTATE, and using its hash value HASH put in the appropriate bucket of DFA's state table. Return value indicates the error code if failed. */ static reg_errcode_t register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, unsigned int hash) { struct re_state_table_entry *spot; reg_errcode_t err; int i; newstate->hash = hash; err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem); if (BE (err != REG_NOERROR, 0)) return REG_ESPACE; for (i = 0; i < newstate->nodes.nelem; i++) { int elem = newstate->nodes.elems[i]; if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) re_node_set_insert_last (&newstate->non_eps_nodes, elem); } spot = dfa->state_table + (hash & dfa->state_hash_mask); if (BE (spot->alloc <= spot->num, 0)) { int new_alloc = 2 * spot->num + 2; re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, new_alloc); if (BE (new_array == NULL, 0)) return REG_ESPACE; spot->array = new_array; spot->alloc = new_alloc; } spot->array[spot->num++] = newstate; return REG_NOERROR; } static void free_state (re_dfastate_t *state) { re_node_set_free (&state->non_eps_nodes); re_node_set_free (&state->inveclosure); if (state->entrance_nodes != &state->nodes) { re_node_set_free (state->entrance_nodes); re_free (state->entrance_nodes); } re_node_set_free (&state->nodes); re_free (state->word_trtable); re_free (state->trtable); re_free (state); } /* Create the new state which is independ of contexts. Return the new state if succeeded, otherwise return NULL. */ static re_dfastate_t * internal_function create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, unsigned int hash) { int i; reg_errcode_t err; re_dfastate_t *newstate; newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); if (BE (newstate == NULL, 0)) return NULL; err = re_node_set_init_copy (&newstate->nodes, nodes); if (BE (err != REG_NOERROR, 0)) { re_free (newstate); return NULL; } newstate->entrance_nodes = &newstate->nodes; for (i = 0 ; i < nodes->nelem ; i++) { re_token_t *node = dfa->nodes + nodes->elems[i]; re_token_type_t type = node->type; if (type == CHARACTER && !node->constraint) continue; #ifdef RE_ENABLE_I18N newstate->accept_mb |= node->accept_mb; #endif /* RE_ENABLE_I18N */ /* If the state has the halt node, the state is a halt state. */ if (type == END_OF_RE) newstate->halt = 1; else if (type == OP_BACK_REF) newstate->has_backref = 1; else if (type == ANCHOR || node->constraint) newstate->has_constraint = 1; } err = register_state (dfa, newstate, hash); if (BE (err != REG_NOERROR, 0)) { free_state (newstate); newstate = NULL; } return newstate; } /* Create the new state which is depend on the context CONTEXT. Return the new state if succeeded, otherwise return NULL. */ static re_dfastate_t * internal_function create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, unsigned int context, unsigned int hash) { int i, nctx_nodes = 0; reg_errcode_t err; re_dfastate_t *newstate; newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); if (BE (newstate == NULL, 0)) return NULL; err = re_node_set_init_copy (&newstate->nodes, nodes); if (BE (err != REG_NOERROR, 0)) { re_free (newstate); return NULL; } newstate->context = context; newstate->entrance_nodes = &newstate->nodes; for (i = 0 ; i < nodes->nelem ; i++) { unsigned int constraint = 0; re_token_t *node = dfa->nodes + nodes->elems[i]; re_token_type_t type = node->type; if (node->constraint) constraint = node->constraint; if (type == CHARACTER && !constraint) continue; #ifdef RE_ENABLE_I18N newstate->accept_mb |= node->accept_mb; #endif /* RE_ENABLE_I18N */ /* If the state has the halt node, the state is a halt state. */ if (type == END_OF_RE) newstate->halt = 1; else if (type == OP_BACK_REF) newstate->has_backref = 1; else if (type == ANCHOR) constraint = node->opr.ctx_type; if (constraint) { if (newstate->entrance_nodes == &newstate->nodes) { newstate->entrance_nodes = re_malloc (re_node_set, 1); if (BE (newstate->entrance_nodes == NULL, 0)) { free_state (newstate); return NULL; } re_node_set_init_copy (newstate->entrance_nodes, nodes); nctx_nodes = 0; newstate->has_constraint = 1; } if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context)) { re_node_set_remove_at (&newstate->nodes, i - nctx_nodes); ++nctx_nodes; } } } err = register_state (dfa, newstate, hash); if (BE (err != REG_NOERROR, 0)) { free_state (newstate); newstate = NULL; } return newstate; } kbuild-3686/src/oldsed/lib/Makefile.in0000664000175000017500000003455715053010104017573 0ustar locutuslocutus# Makefile.in generated by automake 1.9.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SOURCES = $(libsed_a_SOURCES) srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/regex_.h $(srcdir)/stdbool_.h \ alloca.c getline.c memchr.c memcmp.c memmove.c mkstemp.c \ obstack.c obstack.h regex.c strerror.c strverscmp.c ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/codeset.m4 \ $(top_srcdir)/config/getline.m4 \ $(top_srcdir)/config/gettext-ver.m4 \ $(top_srcdir)/config/gettext.m4 \ $(top_srcdir)/config/glibc21.m4 $(top_srcdir)/config/iconv.m4 \ $(top_srcdir)/config/lcmessage.m4 \ $(top_srcdir)/config/lib-ld.m4 \ $(top_srcdir)/config/lib-link.m4 \ $(top_srcdir)/config/lib-prefix.m4 \ $(top_srcdir)/config/progtest.m4 \ $(top_srcdir)/config/stdbool.m4 \ $(top_srcdir)/config/strverscmp.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = stdbool.h regex.h LIBRARIES = $(noinst_LIBRARIES) AR = ar ARFLAGS = cru libsed_a_AR = $(AR) $(ARFLAGS) am_libsed_a_OBJECTS = getopt1.$(OBJEXT) getopt.$(OBJEXT) \ utils.$(OBJEXT) libsed_a_OBJECTS = $(am_libsed_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(libsed_a_SOURCES) DIST_SOURCES = $(libsed_a_SOURCES) HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_HTML_FALSE = @BUILD_HTML_FALSE@ BUILD_HTML_TRUE = @BUILD_HTML_TRUE@ BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GENCAT = @GENCAT@ GLIBC21 = @GLIBC21@ GMSGFMT = @GMSGFMT@ HAVE__BOOL = @HAVE__BOOL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLBISON = @INTLBISON@ INTLLIBS = @INTLLIBS@ INTLOBJS = @INTLOBJS@ INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MAKEINFO_HTML_FALSE = @MAKEINFO_HTML_FALSE@ MAKEINFO_HTML_TRUE = @MAKEINFO_HTML_TRUE@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ RANLIB = @RANLIB@ SED_FEATURE_VERSION = @SED_FEATURE_VERSION@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TEST_REGEX_FALSE = @TEST_REGEX_FALSE@ TEST_REGEX_TRUE = @TEST_REGEX_TRUE@ TEXI2HTML = @TEXI2HTML@ TEXI2HTML_HTML_FALSE = @TEXI2HTML_HTML_FALSE@ TEXI2HTML_HTML_TRUE = @TEXI2HTML_HTML_TRUE@ USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ noinst_LIBRARIES = libsed.a noinst_HEADERS = getopt.h utils.h obstack.h regex_.h regex_internal.h \ strverscmp.h stdbool_.h libsed_a_SOURCES = getopt1.c getopt.c utils.c EXTRA_DIST = memmove.c strerror.c regcomp.c regexec.c regex_internal.c AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/intl -I$(top_srcdir) \ -I$(top_builddir)/lib -I$(top_builddir)/intl libsed_a_LIBADD = @LIBOBJS@ @ALLOCA@ libsed_a_DEPENDENCIES = $(libsed_a_LIBADD) DISTCLEANFILES = regex.h stdbool.h all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits lib/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnits lib/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh stdbool.h: $(top_builddir)/config.status $(srcdir)/stdbool_.h cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libsed.a: $(libsed_a_OBJECTS) $(libsed_a_DEPENDENCIES) -rm -f libsed.a $(libsed_a_AR) libsed.a $(libsed_a_OBJECTS) $(libsed_a_LIBADD) $(RANLIB) libsed.a mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/alloca.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/getline.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/memchr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/memcmp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/memmove.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/mkstemp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/obstack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/regex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strerror.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strverscmp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` uninstall-info-am: ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf $(DEPDIR) ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf $(DEPDIR) ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: kbuild-3686/src/oldsed/lib/regexec.c0000664000175000017500000037254415053010105017316 0ustar locutuslocutus/* Extended regular expression matching and search library. Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, int n) internal_function; static void match_ctx_clean (re_match_context_t *mctx) internal_function; static void match_ctx_free (re_match_context_t *cache) internal_function; static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node, int str_idx, int from, int to) internal_function; static int search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx) internal_function; static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx) internal_function; static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx) internal_function; static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, re_dfastate_t **limited_sts, int last_node, int last_str_idx) internal_function; static reg_errcode_t re_search_internal (const regex_t *preg, const char *string, int length, int start, int range, int stop, size_t nmatch, regmatch_t pmatch[], int eflags) internal_function; static int re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1, int length1, const char *string2, int length2, int start, int range, struct re_registers *regs, int stop, int ret_len) internal_function; static int re_search_stub (struct re_pattern_buffer *bufp, const char *string, int length, int start, int range, int stop, struct re_registers *regs, int ret_len) internal_function; static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, int nregs, int regs_allocated) internal_function; static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx) internal_function; static int check_matching (re_match_context_t *mctx, int fl_longest_match, int *p_match_first) internal_function; static int check_halt_state_context (const re_match_context_t *mctx, const re_dfastate_t *state, int idx) internal_function; static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch) internal_function; static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node, int nregs, regmatch_t *regs, re_node_set *eps_via_nodes) internal_function; static reg_errcode_t set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, regmatch_t *pmatch, int fl_backtrack) internal_function; static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs) internal_function; #ifdef RE_ENABLE_I18N static int sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, int node_idx, int str_idx, int max_str_idx) internal_function; #endif /* RE_ENABLE_I18N */ static reg_errcode_t sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx) internal_function; static reg_errcode_t build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, re_node_set *cur_dest) internal_function; static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, re_node_set *dest_nodes) internal_function; static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, const re_node_set *candidates) internal_function; static int check_dst_limits (const re_match_context_t *mctx, re_node_set *limits, int dst_node, int dst_idx, int src_node, int src_idx) internal_function; static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries, int subexp_idx, int from_node, int bkref_idx) internal_function; static int check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit, int subexp_idx, int node, int str_idx, int bkref_idx) internal_function; static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes, const re_node_set *candidates, re_node_set *limits, struct re_backref_cache_entry *bkref_ents, int str_idx) internal_function; static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, const re_node_set *candidates) internal_function; static reg_errcode_t merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst, re_dfastate_t **src, int num) internal_function; static re_dfastate_t *find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) internal_function; static re_dfastate_t *transit_state (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *state) internal_function; static re_dfastate_t *merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *next_state) internal_function; static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, int str_idx) internal_function; #if 0 static re_dfastate_t *transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *pstate) internal_function; #endif #ifdef RE_ENABLE_I18N static reg_errcode_t transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) internal_function; #endif /* RE_ENABLE_I18N */ static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) internal_function; static reg_errcode_t get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx) internal_function; static reg_errcode_t get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, re_sub_match_last_t *sub_last, int bkref_node, int bkref_str) internal_function; static int find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, int subexp_idx, int type) internal_function; static reg_errcode_t check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node, int top_str, int last_node, int last_str, int type) internal_function; static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx, re_node_set *cur_nodes, re_node_set *next_nodes) internal_function; static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes, int ex_subexp, int type) internal_function; static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, int target, int ex_subexp, int type) internal_function; static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, int cur_str, int subexp_num, int type) internal_function; static int build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) internal_function; #ifdef RE_ENABLE_I18N static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, const re_string_t *input, int idx) internal_function; # ifdef _LIBC static unsigned int find_collation_sequence_value (const unsigned char *mbs, size_t name_len) internal_function; # endif /* _LIBC */ #endif /* RE_ENABLE_I18N */ static int group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, re_node_set *states_node, bitset_t *states_ch) internal_function; static int check_node_accept (const re_match_context_t *mctx, const re_token_t *node, int idx) internal_function; static reg_errcode_t extend_buffers (re_match_context_t *mctx) internal_function; /* Entry point for POSIX code. */ /* regexec searches for a given pattern, specified by PREG, in the string STRING. If NMATCH is zero or REG_NOSUB was set in the cflags argument to `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at least NMATCH elements, and we set them to the offsets of the corresponding matched substrings. EFLAGS specifies `execution flags' which affect matching: if REG_NOTBOL is set, then ^ does not match at the beginning of the string; if REG_NOTEOL is set, then $ does not match at the end. We return 0 if we find a match and REG_NOMATCH if not. */ int regexec (preg, string, nmatch, pmatch, eflags) const regex_t *__restrict preg; const char *__restrict string; size_t nmatch; regmatch_t pmatch[]; int eflags; { reg_errcode_t err; int start, length; re_dfa_t *dfa = (re_dfa_t *) preg->buffer; if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) return REG_BADPAT; if (eflags & REG_STARTEND) { start = pmatch[0].rm_so; length = pmatch[0].rm_eo; } else { start = 0; length = strlen (string); } __libc_lock_lock (dfa->lock); if (preg->no_sub) err = re_search_internal (preg, string, length, start, length - start, length, 0, NULL, eflags); else err = re_search_internal (preg, string, length, start, length - start, length, nmatch, pmatch, eflags); __libc_lock_unlock (dfa->lock); return err != REG_NOERROR; } #ifdef _LIBC # include versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); # if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) __typeof__ (__regexec) __compat_regexec; int attribute_compat_text_section __compat_regexec (const regex_t *__restrict preg, const char *__restrict string, size_t nmatch, regmatch_t pmatch[], int eflags) { return regexec (preg, string, nmatch, pmatch, eflags & (REG_NOTBOL | REG_NOTEOL)); } compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); # endif #endif /* Entry points for GNU code. */ /* re_match, re_search, re_match_2, re_search_2 The former two functions operate on STRING with length LENGTH, while the later two operate on concatenation of STRING1 and STRING2 with lengths LENGTH1 and LENGTH2, respectively. re_match() matches the compiled pattern in BUFP against the string, starting at index START. re_search() first tries matching at index START, then it tries to match starting from index START + 1, and so on. The last start position tried is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same way as re_match().) The parameter STOP of re_{match,search}_2 specifies that no match exceeding the first STOP characters of the concatenation of the strings should be concerned. If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match and all groups is stroed in REGS. (For the "_2" variants, the offsets are computed relative to the concatenation, not relative to the individual strings.) On success, re_match* functions return the length of the match, re_search* return the position of the start of the match. Return value -1 means no match was found and -2 indicates an internal error. */ int re_match (bufp, string, length, start, regs) struct re_pattern_buffer *bufp; const char *string; int length, start; struct re_registers *regs; { return re_search_stub (bufp, string, length, start, 0, length, regs, 1); } #ifdef _LIBC weak_alias (__re_match, re_match) #endif int re_search (bufp, string, length, start, range, regs) struct re_pattern_buffer *bufp; const char *string; int length, start, range; struct re_registers *regs; { return re_search_stub (bufp, string, length, start, range, length, regs, 0); } #ifdef _LIBC weak_alias (__re_search, re_search) #endif int re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop) struct re_pattern_buffer *bufp; const char *string1, *string2; int length1, length2, start, stop; struct re_registers *regs; { return re_search_2_stub (bufp, string1, length1, string2, length2, start, 0, regs, stop, 1); } #ifdef _LIBC weak_alias (__re_match_2, re_match_2) #endif int re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop) struct re_pattern_buffer *bufp; const char *string1, *string2; int length1, length2, start, range, stop; struct re_registers *regs; { return re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs, stop, 0); } #ifdef _LIBC weak_alias (__re_search_2, re_search_2) #endif static int re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs, stop, ret_len) struct re_pattern_buffer *bufp; const char *string1, *string2; int length1, length2, start, range, stop, ret_len; struct re_registers *regs; { const char *str; int rval; int len = length1 + length2; int free_str = 0; if (BE (length1 < 0 || length2 < 0 || stop < 0, 0)) return -2; /* Concatenate the strings. */ if (length2 > 0) if (length1 > 0) { char *s = re_malloc (char, len); if (BE (s == NULL, 0)) return -2; #ifdef _LIBC memcpy (__mempcpy (s, string1, length1), string2, length2); #else memcpy (s, string1, length1); memcpy (s + length1, string2, length2); #endif str = s; free_str = 1; } else str = string2; else str = string1; rval = re_search_stub (bufp, str, len, start, range, stop, regs, ret_len); if (free_str) re_free ((char *) str); return rval; } /* The parameters have the same meaning as those of re_search. Additional parameters: If RET_LEN is nonzero the length of the match is returned (re_match style); otherwise the position of the match is returned. */ static int re_search_stub (bufp, string, length, start, range, stop, regs, ret_len) struct re_pattern_buffer *bufp; const char *string; int length, start, range, stop, ret_len; struct re_registers *regs; { reg_errcode_t result; regmatch_t *pmatch; int nregs, rval; int eflags = 0; re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; /* Check for out-of-range. */ if (BE (start < 0 || start > length, 0)) return -1; if (BE (start + range > length, 0)) range = length - start; else if (BE (start + range < 0, 0)) range = -start; __libc_lock_lock (dfa->lock); eflags |= (bufp->not_bol) ? REG_NOTBOL : 0; eflags |= (bufp->not_eol) ? REG_NOTEOL : 0; /* Compile fastmap if we haven't yet. */ if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate) re_compile_fastmap (bufp); if (BE (bufp->no_sub, 0)) regs = NULL; /* We need at least 1 register. */ if (regs == NULL) nregs = 1; else if (BE (bufp->regs_allocated == REGS_FIXED && regs->num_regs < bufp->re_nsub + 1, 0)) { nregs = regs->num_regs; if (BE (nregs < 1, 0)) { /* Nothing can be copied to regs. */ regs = NULL; nregs = 1; } } else nregs = bufp->re_nsub + 1; pmatch = re_malloc (regmatch_t, nregs); if (BE (pmatch == NULL, 0)) { rval = -2; goto out; } result = re_search_internal (bufp, string, length, start, range, stop, nregs, pmatch, eflags); rval = 0; /* I hope we needn't fill ther regs with -1's when no match was found. */ if (result != REG_NOERROR) rval = -1; else if (regs != NULL) { /* If caller wants register contents data back, copy them. */ bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs, bufp->regs_allocated); if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0)) rval = -2; } if (BE (rval == 0, 1)) { if (ret_len) { assert (pmatch[0].rm_so == start); rval = pmatch[0].rm_eo - start; } else rval = pmatch[0].rm_so; } re_free (pmatch); out: __libc_lock_unlock (dfa->lock); return rval; } static unsigned re_copy_regs (regs, pmatch, nregs, regs_allocated) struct re_registers *regs; regmatch_t *pmatch; int nregs, regs_allocated; { int rval = REGS_REALLOCATE; int i; int need_regs = nregs + 1; /* We need one extra element beyond `num_regs' for the `-1' marker GNU code uses. */ /* Have the register data arrays been allocated? */ if (regs_allocated == REGS_UNALLOCATED) { /* No. So allocate them with malloc. */ regs->start = re_malloc (regoff_t, need_regs); regs->end = re_malloc (regoff_t, need_regs); if (BE (regs->start == NULL, 0) || BE (regs->end == NULL, 0)) return REGS_UNALLOCATED; regs->num_regs = need_regs; } else if (regs_allocated == REGS_REALLOCATE) { /* Yes. If we need more elements than were already allocated, reallocate them. If we need fewer, just leave it alone. */ if (BE (need_regs > regs->num_regs, 0)) { regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs); regoff_t *new_end = re_realloc (regs->end, regoff_t, need_regs); if (BE (new_start == NULL, 0) || BE (new_end == NULL, 0)) return REGS_UNALLOCATED; regs->start = new_start; regs->end = new_end; regs->num_regs = need_regs; } } else { assert (regs_allocated == REGS_FIXED); /* This function may not be called with REGS_FIXED and nregs too big. */ assert (regs->num_regs >= nregs); rval = REGS_FIXED; } /* Copy the regs. */ for (i = 0; i < nregs; ++i) { regs->start[i] = pmatch[i].rm_so; regs->end[i] = pmatch[i].rm_eo; } for ( ; i < regs->num_regs; ++i) regs->start[i] = regs->end[i] = -1; return rval; } /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be allocated using the malloc library routine, and must each be at least NUM_REGS * sizeof (regoff_t) bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using PATTERN_BUFFER will allocate its own register data, without freeing the old data. */ void re_set_registers (bufp, regs, num_regs, starts, ends) struct re_pattern_buffer *bufp; struct re_registers *regs; unsigned num_regs; regoff_t *starts, *ends; { if (num_regs) { bufp->regs_allocated = REGS_REALLOCATE; regs->num_regs = num_regs; regs->start = starts; regs->end = ends; } else { bufp->regs_allocated = REGS_UNALLOCATED; regs->num_regs = 0; regs->start = regs->end = (regoff_t *) 0; } } #ifdef _LIBC weak_alias (__re_set_registers, re_set_registers) #endif /* Entry points compatible with 4.2 BSD regex library. We don't define them unless specifically requested. */ #if defined _REGEX_RE_COMP || defined _LIBC int # ifdef _LIBC weak_function # endif re_exec (s) const char *s; { return 0 == regexec (&re_comp_buf, s, 0, NULL, 0); } #endif /* _REGEX_RE_COMP */ /* Internal entry point. */ /* Searches for a compiled pattern PREG in the string STRING, whose length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same mingings with regexec. START, and RANGE have the same meanings with re_search. Return REG_NOERROR if we find a match, and REG_NOMATCH if not, otherwise return the error code. Note: We assume front end functions already check ranges. (START + RANGE >= 0 && START + RANGE <= LENGTH) */ static reg_errcode_t re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch, eflags) const regex_t *preg; const char *string; int length, start, range, stop, eflags; size_t nmatch; regmatch_t pmatch[]; { reg_errcode_t err; const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; int left_lim, right_lim, incr; int fl_longest_match, match_first, match_kind, match_last = -1; int extra_nmatch; int sb, ch; #if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) re_match_context_t mctx = { .dfa = dfa }; #else re_match_context_t mctx; #endif char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate && range && !preg->can_be_null) ? preg->fastmap : NULL; RE_TRANSLATE_TYPE t = preg->translate; #if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) memset (&mctx, '\0', sizeof (re_match_context_t)); mctx.dfa = dfa; #endif extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0; nmatch -= extra_nmatch; /* Check if the DFA haven't been compiled. */ if (BE (preg->used == 0 || dfa->init_state == NULL || dfa->init_state_word == NULL || dfa->init_state_nl == NULL || dfa->init_state_begbuf == NULL, 0)) return REG_NOMATCH; #ifdef DEBUG /* We assume front-end functions already check them. */ assert (start + range >= 0 && start + range <= length); #endif /* If initial states with non-begbuf contexts have no elements, the regex must be anchored. If preg->newline_anchor is set, we'll never use init_state_nl, so do not check it. */ if (dfa->init_state->nodes.nelem == 0 && dfa->init_state_word->nodes.nelem == 0 && (dfa->init_state_nl->nodes.nelem == 0 || !preg->newline_anchor)) { if (start != 0 && start + range != 0) return REG_NOMATCH; start = range = 0; } /* We must check the longest matching, if nmatch > 0. */ fl_longest_match = (nmatch != 0 || dfa->nbackref); err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1, preg->translate, preg->syntax & RE_ICASE, dfa); if (BE (err != REG_NOERROR, 0)) goto free_return; mctx.input.stop = stop; mctx.input.raw_stop = stop; mctx.input.newline_anchor = preg->newline_anchor; err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2); if (BE (err != REG_NOERROR, 0)) goto free_return; /* We will log all the DFA states through which the dfa pass, if nmatch > 1, or this dfa has "multibyte node", which is a back-reference or a node which can accept multibyte character or multi character collating element. */ if (nmatch > 1 || dfa->has_mb_node) { mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); if (BE (mctx.state_log == NULL, 0)) { err = REG_ESPACE; goto free_return; } } else mctx.state_log = NULL; match_first = start; mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF : CONTEXT_NEWLINE | CONTEXT_BEGBUF; /* Check incrementally whether of not the input string match. */ incr = (range < 0) ? -1 : 1; left_lim = (range < 0) ? start + range : start; right_lim = (range < 0) ? start : start + range; sb = dfa->mb_cur_max == 1; match_kind = (fastmap ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) | (range >= 0 ? 2 : 0) | (t != NULL ? 1 : 0)) : 8); for (;; match_first += incr) { err = REG_NOMATCH; if (match_first < left_lim || right_lim < match_first) goto free_return; /* Advance as rapidly as possible through the string, until we find a plausible place to start matching. This may be done with varying efficiency, so there are various possibilities: only the most common of them are specialized, in order to save on code size. We use a switch statement for speed. */ switch (match_kind) { case 8: /* No fastmap. */ break; case 7: /* Fastmap with single-byte translation, match forward. */ while (BE (match_first < right_lim, 1) && !fastmap[t[(unsigned char) string[match_first]]]) ++match_first; goto forward_match_found_start_or_reached_end; case 6: /* Fastmap without translation, match forward. */ while (BE (match_first < right_lim, 1) && !fastmap[(unsigned char) string[match_first]]) ++match_first; forward_match_found_start_or_reached_end: if (BE (match_first == right_lim, 0)) { ch = match_first >= length ? 0 : (unsigned char) string[match_first]; if (!fastmap[t ? t[ch] : ch]) goto free_return; } break; case 4: case 5: /* Fastmap without multi-byte translation, match backwards. */ while (match_first >= left_lim) { ch = match_first >= length ? 0 : (unsigned char) string[match_first]; if (fastmap[t ? t[ch] : ch]) break; --match_first; } if (match_first < left_lim) goto free_return; break; default: /* In this case, we can't determine easily the current byte, since it might be a component byte of a multibyte character. Then we use the constructed buffer instead. */ for (;;) { /* If MATCH_FIRST is out of the valid range, reconstruct the buffers. */ unsigned int offset = match_first - mctx.input.raw_mbs_idx; if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0)) { err = re_string_reconstruct (&mctx.input, match_first, eflags); if (BE (err != REG_NOERROR, 0)) goto free_return; offset = match_first - mctx.input.raw_mbs_idx; } /* If MATCH_FIRST is out of the buffer, leave it as '\0'. Note that MATCH_FIRST must not be smaller than 0. */ ch = (match_first >= length ? 0 : re_string_byte_at (&mctx.input, offset)); if (fastmap[ch]) break; match_first += incr; if (match_first < left_lim || match_first > right_lim) { err = REG_NOMATCH; goto free_return; } } break; } /* Reconstruct the buffers so that the matcher can assume that the matching starts from the beginning of the buffer. */ err = re_string_reconstruct (&mctx.input, match_first, eflags); if (BE (err != REG_NOERROR, 0)) goto free_return; #ifdef RE_ENABLE_I18N /* Don't consider this char as a possible match start if it part, yet isn't the head, of a multibyte character. */ if (!sb && !re_string_first_byte (&mctx.input, 0)) continue; #endif /* It seems to be appropriate one, then use the matcher. */ /* We assume that the matching starts from 0. */ mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; match_last = check_matching (&mctx, fl_longest_match, range >= 0 ? &match_first : NULL); if (match_last != -1) { if (BE (match_last == -2, 0)) { err = REG_ESPACE; goto free_return; } else { mctx.match_last = match_last; if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) { re_dfastate_t *pstate = mctx.state_log[match_last]; mctx.last_node = check_halt_state_context (&mctx, pstate, match_last); } if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) || dfa->nbackref) { err = prune_impossible_nodes (&mctx); if (err == REG_NOERROR) break; if (BE (err != REG_NOMATCH, 0)) goto free_return; match_last = -1; } else break; /* We found a match. */ } } match_ctx_clean (&mctx); } #ifdef DEBUG assert (match_last != -1); assert (err == REG_NOERROR); #endif /* Set pmatch[] if we need. */ if (nmatch > 0) { int reg_idx; /* Initialize registers. */ for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; /* Set the points where matching start/end. */ pmatch[0].rm_so = 0; pmatch[0].rm_eo = mctx.match_last; if (!preg->no_sub && nmatch > 1) { err = set_regs (preg, &mctx, nmatch, pmatch, dfa->has_plural_match && dfa->nbackref > 0); if (BE (err != REG_NOERROR, 0)) goto free_return; } /* At last, add the offset to the each registers, since we slided the buffers so that we could assume that the matching starts from 0. */ for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) if (pmatch[reg_idx].rm_so != -1) { #ifdef RE_ENABLE_I18N if (BE (mctx.input.offsets_needed != 0, 0)) { pmatch[reg_idx].rm_so = (pmatch[reg_idx].rm_so == mctx.input.valid_len ? mctx.input.valid_raw_len : mctx.input.offsets[pmatch[reg_idx].rm_so]); pmatch[reg_idx].rm_eo = (pmatch[reg_idx].rm_eo == mctx.input.valid_len ? mctx.input.valid_raw_len : mctx.input.offsets[pmatch[reg_idx].rm_eo]); } #else assert (mctx.input.offsets_needed == 0); #endif pmatch[reg_idx].rm_so += match_first; pmatch[reg_idx].rm_eo += match_first; } for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx) { pmatch[nmatch + reg_idx].rm_so = -1; pmatch[nmatch + reg_idx].rm_eo = -1; } if (dfa->subexp_map) for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++) if (dfa->subexp_map[reg_idx] != reg_idx) { pmatch[reg_idx + 1].rm_so = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so; pmatch[reg_idx + 1].rm_eo = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo; } } free_return: re_free (mctx.state_log); if (dfa->nbackref) match_ctx_free (&mctx); re_string_destruct (&mctx.input); return err; } static reg_errcode_t prune_impossible_nodes (mctx) re_match_context_t *mctx; { const re_dfa_t *const dfa = mctx->dfa; int halt_node, match_last; reg_errcode_t ret; re_dfastate_t **sifted_states; re_dfastate_t **lim_states = NULL; re_sift_context_t sctx; #ifdef DEBUG assert (mctx->state_log != NULL); #endif match_last = mctx->match_last; halt_node = mctx->last_node; sifted_states = re_malloc (re_dfastate_t *, match_last + 1); if (BE (sifted_states == NULL, 0)) { ret = REG_ESPACE; goto free_return; } if (dfa->nbackref) { lim_states = re_malloc (re_dfastate_t *, match_last + 1); if (BE (lim_states == NULL, 0)) { ret = REG_ESPACE; goto free_return; } while (1) { memset (lim_states, '\0', sizeof (re_dfastate_t *) * (match_last + 1)); sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); ret = sift_states_backward (mctx, &sctx); re_node_set_free (&sctx.limits); if (BE (ret != REG_NOERROR, 0)) goto free_return; if (sifted_states[0] != NULL || lim_states[0] != NULL) break; do { --match_last; if (match_last < 0) { ret = REG_NOMATCH; goto free_return; } } while (mctx->state_log[match_last] == NULL || !mctx->state_log[match_last]->halt); halt_node = check_halt_state_context (mctx, mctx->state_log[match_last], match_last); } ret = merge_state_array (dfa, sifted_states, lim_states, match_last + 1); re_free (lim_states); lim_states = NULL; if (BE (ret != REG_NOERROR, 0)) goto free_return; } else { sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); ret = sift_states_backward (mctx, &sctx); re_node_set_free (&sctx.limits); if (BE (ret != REG_NOERROR, 0)) goto free_return; } re_free (mctx->state_log); mctx->state_log = sifted_states; sifted_states = NULL; mctx->last_node = halt_node; mctx->match_last = match_last; ret = REG_NOERROR; free_return: re_free (sifted_states); re_free (lim_states); return ret; } /* Acquire an initial state and return it. We must select appropriate initial state depending on the context, since initial states may have constraints like "\<", "^", etc.. */ static inline re_dfastate_t * __attribute ((always_inline)) internal_function acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, int idx) { const re_dfa_t *const dfa = mctx->dfa; if (dfa->init_state->has_constraint) { unsigned int context; context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags); if (IS_WORD_CONTEXT (context)) return dfa->init_state_word; else if (IS_ORDINARY_CONTEXT (context)) return dfa->init_state; else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context)) return dfa->init_state_begbuf; else if (IS_NEWLINE_CONTEXT (context)) return dfa->init_state_nl; else if (IS_BEGBUF_CONTEXT (context)) { /* It is relatively rare case, then calculate on demand. */ return re_acquire_state_context (err, dfa, dfa->init_state->entrance_nodes, context); } else /* Must not happen? */ return dfa->init_state; } else return dfa->init_state; } /* Check whether the regular expression match input string INPUT or not, and return the index where the matching end, return -1 if not match, or return -2 in case of an error. FL_LONGEST_MATCH means we want the POSIX longest matching. If P_MATCH_FIRST is not NULL, and the match fails, it is set to the next place where we may want to try matching. Note that the matcher assume that the maching starts from the current index of the buffer. */ static int internal_function check_matching (re_match_context_t *mctx, int fl_longest_match, int *p_match_first) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int match = 0; int match_last = -1; int cur_str_idx = re_string_cur_idx (&mctx->input); re_dfastate_t *cur_state; int at_init_state = p_match_first != NULL; int next_start_idx = cur_str_idx; err = REG_NOERROR; cur_state = acquire_init_state_context (&err, mctx, cur_str_idx); /* An initial state must not be NULL (invalid). */ if (BE (cur_state == NULL, 0)) { assert (err == REG_ESPACE); return -2; } if (mctx->state_log != NULL) { mctx->state_log[cur_str_idx] = cur_state; /* Check OP_OPEN_SUBEXP in the initial state in case that we use them later. E.g. Processing back references. */ if (BE (dfa->nbackref, 0)) { at_init_state = 0; err = check_subexp_matching_top (mctx, &cur_state->nodes, 0); if (BE (err != REG_NOERROR, 0)) return err; if (cur_state->has_backref) { err = transit_state_bkref (mctx, &cur_state->nodes); if (BE (err != REG_NOERROR, 0)) return err; } } } /* If the RE accepts NULL string. */ if (BE (cur_state->halt, 0)) { if (!cur_state->has_constraint || check_halt_state_context (mctx, cur_state, cur_str_idx)) { if (!fl_longest_match) return cur_str_idx; else { match_last = cur_str_idx; match = 1; } } } while (!re_string_eoi (&mctx->input)) { re_dfastate_t *old_state = cur_state; int next_char_idx = re_string_cur_idx (&mctx->input) + 1; if (BE (next_char_idx >= mctx->input.bufs_len, 0) || (BE (next_char_idx >= mctx->input.valid_len, 0) && mctx->input.valid_len < mctx->input.len)) { err = extend_buffers (mctx); if (BE (err != REG_NOERROR, 0)) { assert (err == REG_ESPACE); return -2; } } cur_state = transit_state (&err, mctx, cur_state); if (mctx->state_log != NULL) cur_state = merge_state_with_log (&err, mctx, cur_state); if (cur_state == NULL) { /* Reached the invalid state or an error. Try to recover a valid state using the state log, if available and if we have not already found a valid (even if not the longest) match. */ if (BE (err != REG_NOERROR, 0)) return -2; if (mctx->state_log == NULL || (match && !fl_longest_match) || (cur_state = find_recover_state (&err, mctx)) == NULL) break; } if (BE (at_init_state, 0)) { if (old_state == cur_state) next_start_idx = next_char_idx; else at_init_state = 0; } if (cur_state->halt) { /* Reached a halt state. Check the halt state can satisfy the current context. */ if (!cur_state->has_constraint || check_halt_state_context (mctx, cur_state, re_string_cur_idx (&mctx->input))) { /* We found an appropriate halt state. */ match_last = re_string_cur_idx (&mctx->input); match = 1; /* We found a match, do not modify match_first below. */ p_match_first = NULL; if (!fl_longest_match) break; } } } if (p_match_first) *p_match_first += next_start_idx; return match_last; } /* Check NODE match the current context. */ static int internal_function check_halt_node_context (const re_dfa_t *dfa, int node, unsigned int context) { re_token_type_t type = dfa->nodes[node].type; unsigned int constraint = dfa->nodes[node].constraint; if (type != END_OF_RE) return 0; if (!constraint) return 1; if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context)) return 0; return 1; } /* Check the halt state STATE match the current context. Return 0 if not match, if the node, STATE has, is a halt node and match the context, return the node. */ static int internal_function check_halt_state_context (const re_match_context_t *mctx, const re_dfastate_t *state, int idx) { int i; unsigned int context; #ifdef DEBUG assert (state->halt); #endif context = re_string_context_at (&mctx->input, idx, mctx->eflags); for (i = 0; i < state->nodes.nelem; ++i) if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context)) return state->nodes.elems[i]; return 0; } /* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA corresponding to the DFA). Return the destination node, and update EPS_VIA_NODES, return -1 in case of errors. */ static int internal_function proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs, int *pidx, int node, re_node_set *eps_via_nodes, struct re_fail_stack_t *fs) { const re_dfa_t *const dfa = mctx->dfa; int i, err; if (IS_EPSILON_NODE (dfa->nodes[node].type)) { re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; re_node_set *edests = &dfa->edests[node]; int dest_node; err = re_node_set_insert (eps_via_nodes, node); if (BE (err < 0, 0)) return -2; /* Pick up a valid destination, or return -1 if none is found. */ for (dest_node = -1, i = 0; i < edests->nelem; ++i) { int candidate = edests->elems[i]; if (!re_node_set_contains (cur_nodes, candidate)) continue; if (dest_node == -1) dest_node = candidate; else { /* In order to avoid infinite loop like "(a*)*", return the second epsilon-transition if the first was already considered. */ if (re_node_set_contains (eps_via_nodes, dest_node)) return candidate; /* Otherwise, push the second epsilon-transition on the fail stack. */ else if (fs != NULL && push_fail_stack (fs, *pidx, candidate, nregs, regs, eps_via_nodes)) return -2; /* We know we are going to exit. */ break; } } return dest_node; } else { int naccepted = 0; re_token_type_t type = dfa->nodes[node].type; #ifdef RE_ENABLE_I18N if (dfa->nodes[node].accept_mb) naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); else #endif /* RE_ENABLE_I18N */ if (type == OP_BACK_REF) { int subexp_idx = dfa->nodes[node].opr.idx + 1; naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so; if (fs != NULL) { if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1) return -1; else if (naccepted) { char *buf = (char *) re_string_get_buffer (&mctx->input); if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, naccepted) != 0) return -1; } } if (naccepted == 0) { int dest_node; err = re_node_set_insert (eps_via_nodes, node); if (BE (err < 0, 0)) return -2; dest_node = dfa->edests[node].elems[0]; if (re_node_set_contains (&mctx->state_log[*pidx]->nodes, dest_node)) return dest_node; } } if (naccepted != 0 || check_node_accept (mctx, dfa->nodes + node, *pidx)) { int dest_node = dfa->nexts[node]; *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted; if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL || !re_node_set_contains (&mctx->state_log[*pidx]->nodes, dest_node))) return -1; re_node_set_empty (eps_via_nodes); return dest_node; } } return -1; } static reg_errcode_t internal_function push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node, int nregs, regmatch_t *regs, re_node_set *eps_via_nodes) { reg_errcode_t err; int num = fs->num++; if (fs->num == fs->alloc) { struct re_fail_stack_ent_t *new_array; new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t) * fs->alloc * 2)); if (new_array == NULL) return REG_ESPACE; fs->alloc *= 2; fs->stack = new_array; } fs->stack[num].idx = str_idx; fs->stack[num].node = dest_node; fs->stack[num].regs = re_malloc (regmatch_t, nregs); if (fs->stack[num].regs == NULL) return REG_ESPACE; memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes); return err; } static int internal_function pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs, regmatch_t *regs, re_node_set *eps_via_nodes) { int num = --fs->num; assert (num >= 0); *pidx = fs->stack[num].idx; memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs); re_node_set_free (eps_via_nodes); re_free (fs->stack[num].regs); *eps_via_nodes = fs->stack[num].eps_via_nodes; return fs->stack[num].node; } /* Set the positions where the subexpressions are starts/ends to registers PMATCH. Note: We assume that pmatch[0] is already set, and pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */ static reg_errcode_t internal_function set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, regmatch_t *pmatch, int fl_backtrack) { const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; int idx, cur_node; re_node_set eps_via_nodes; struct re_fail_stack_t *fs; struct re_fail_stack_t fs_body = { 0, 2, NULL }; regmatch_t *prev_idx_match; int prev_idx_match_malloced = 0; #ifdef DEBUG assert (nmatch > 1); assert (mctx->state_log != NULL); #endif if (fl_backtrack) { fs = &fs_body; fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc); if (fs->stack == NULL) return REG_ESPACE; } else fs = NULL; cur_node = dfa->init_node; re_node_set_init_empty (&eps_via_nodes); if (__libc_use_alloca (nmatch * sizeof (regmatch_t))) prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t)); else { prev_idx_match = re_malloc (regmatch_t, nmatch); if (prev_idx_match == NULL) { free_fail_stack_return (fs); return REG_ESPACE; } prev_idx_match_malloced = 1; } memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) { update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node) { int reg_idx; if (fs) { for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1) break; if (reg_idx == nmatch) { re_node_set_free (&eps_via_nodes); if (prev_idx_match_malloced) re_free (prev_idx_match); return free_fail_stack_return (fs); } cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, &eps_via_nodes); } else { re_node_set_free (&eps_via_nodes); if (prev_idx_match_malloced) re_free (prev_idx_match); return REG_NOERROR; } } /* Proceed to next node. */ cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node, &eps_via_nodes, fs); if (BE (cur_node < 0, 0)) { if (BE (cur_node == -2, 0)) { re_node_set_free (&eps_via_nodes); if (prev_idx_match_malloced) re_free (prev_idx_match); free_fail_stack_return (fs); return REG_ESPACE; } if (fs) cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, &eps_via_nodes); else { re_node_set_free (&eps_via_nodes); if (prev_idx_match_malloced) re_free (prev_idx_match); return REG_NOMATCH; } } } re_node_set_free (&eps_via_nodes); if (prev_idx_match_malloced) re_free (prev_idx_match); return free_fail_stack_return (fs); } static reg_errcode_t internal_function free_fail_stack_return (struct re_fail_stack_t *fs) { if (fs) { int fs_idx; for (fs_idx = 0; fs_idx < fs->num; ++fs_idx) { re_node_set_free (&fs->stack[fs_idx].eps_via_nodes); re_free (fs->stack[fs_idx].regs); } re_free (fs->stack); } return REG_NOERROR; } static void internal_function update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch) { int type = dfa->nodes[cur_node].type; if (type == OP_OPEN_SUBEXP) { int reg_num = dfa->nodes[cur_node].opr.idx + 1; /* We are at the first node of this sub expression. */ if (reg_num < nmatch) { pmatch[reg_num].rm_so = cur_idx; pmatch[reg_num].rm_eo = -1; } } else if (type == OP_CLOSE_SUBEXP) { int reg_num = dfa->nodes[cur_node].opr.idx + 1; if (reg_num < nmatch) { /* We are at the last node of this sub expression. */ if (pmatch[reg_num].rm_so < cur_idx) { pmatch[reg_num].rm_eo = cur_idx; /* This is a non-empty match or we are not inside an optional subexpression. Accept this right away. */ memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); } else { if (dfa->nodes[cur_node].opt_subexp && prev_idx_match[reg_num].rm_so != -1) /* We transited through an empty match for an optional subexpression, like (a?)*, and this is not the subexp's first match. Copy back the old content of the registers so that matches of an inner subexpression are undone as well, like in ((a?))*. */ memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch); else /* We completed a subexpression, but it may be part of an optional one, so do not update PREV_IDX_MATCH. */ pmatch[reg_num].rm_eo = cur_idx; } } } } /* This function checks the STATE_LOG from the SCTX->last_str_idx to 0 and sift the nodes in each states according to the following rules. Updated state_log will be wrote to STATE_LOG. Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if... 1. When STR_IDX == MATCH_LAST(the last index in the state_log): If `a' isn't the LAST_NODE and `a' can't epsilon transit to the LAST_NODE, we throw away the node `a'. 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts string `s' and transit to `b': i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw away the node `a'. ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is thrown away, we throw away the node `a'. 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the node `a'. ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, we throw away the node `a'. */ #define STATE_NODE_CONTAINS(state,node) \ ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) static reg_errcode_t internal_function sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx) { reg_errcode_t err; int null_cnt = 0; int str_idx = sctx->last_str_idx; re_node_set cur_dest; #ifdef DEBUG assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL); #endif /* Build sifted state_log[str_idx]. It has the nodes which can epsilon transit to the last_node and the last_node itself. */ err = re_node_set_init_1 (&cur_dest, sctx->last_node); if (BE (err != REG_NOERROR, 0)) return err; err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); if (BE (err != REG_NOERROR, 0)) goto free_return; /* Then check each states in the state_log. */ while (str_idx > 0) { /* Update counters. */ null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0; if (null_cnt > mctx->max_mb_elem_len) { memset (sctx->sifted_states, '\0', sizeof (re_dfastate_t *) * str_idx); re_node_set_free (&cur_dest); return REG_NOERROR; } re_node_set_empty (&cur_dest); --str_idx; if (mctx->state_log[str_idx]) { err = build_sifted_states (mctx, sctx, str_idx, &cur_dest); if (BE (err != REG_NOERROR, 0)) goto free_return; } /* Add all the nodes which satisfy the following conditions: - It can epsilon transit to a node in CUR_DEST. - It is in CUR_SRC. And update state_log. */ err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); if (BE (err != REG_NOERROR, 0)) goto free_return; } err = REG_NOERROR; free_return: re_node_set_free (&cur_dest); return err; } static reg_errcode_t internal_function build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, re_node_set *cur_dest) { const re_dfa_t *const dfa = mctx->dfa; const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes; int i; /* Then build the next sifted state. We build the next sifted state on `cur_dest', and update `sifted_states[str_idx]' with `cur_dest'. Note: `cur_dest' is the sifted state from `state_log[str_idx + 1]'. `cur_src' points the node_set of the old `state_log[str_idx]' (with the epsilon nodes pre-filtered out). */ for (i = 0; i < cur_src->nelem; i++) { int prev_node = cur_src->elems[i]; int naccepted = 0; int ret; #ifdef DEBUG re_token_type_t type = dfa->nodes[prev_node].type; assert (!IS_EPSILON_NODE (type)); #endif #ifdef RE_ENABLE_I18N /* If the node may accept `multi byte'. */ if (dfa->nodes[prev_node].accept_mb) naccepted = sift_states_iter_mb (mctx, sctx, prev_node, str_idx, sctx->last_str_idx); #endif /* RE_ENABLE_I18N */ /* We don't check backreferences here. See update_cur_sifted_state(). */ if (!naccepted && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], dfa->nexts[prev_node])) naccepted = 1; if (naccepted == 0) continue; if (sctx->limits.nelem) { int to_idx = str_idx + naccepted; if (check_dst_limits (mctx, &sctx->limits, dfa->nexts[prev_node], to_idx, prev_node, str_idx)) continue; } ret = re_node_set_insert (cur_dest, prev_node); if (BE (ret == -1, 0)) return REG_ESPACE; } return REG_NOERROR; } /* Helper functions. */ static reg_errcode_t internal_function clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx) { int top = mctx->state_log_top; if (next_state_log_idx >= mctx->input.bufs_len || (next_state_log_idx >= mctx->input.valid_len && mctx->input.valid_len < mctx->input.len)) { reg_errcode_t err; err = extend_buffers (mctx); if (BE (err != REG_NOERROR, 0)) return err; } if (top < next_state_log_idx) { memset (mctx->state_log + top + 1, '\0', sizeof (re_dfastate_t *) * (next_state_log_idx - top)); mctx->state_log_top = next_state_log_idx; } return REG_NOERROR; } static reg_errcode_t internal_function merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst, re_dfastate_t **src, int num) { int st_idx; reg_errcode_t err; for (st_idx = 0; st_idx < num; ++st_idx) { if (dst[st_idx] == NULL) dst[st_idx] = src[st_idx]; else if (src[st_idx] != NULL) { re_node_set merged_set; err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes, &src[st_idx]->nodes); if (BE (err != REG_NOERROR, 0)) return err; dst[st_idx] = re_acquire_state (&err, dfa, &merged_set); re_node_set_free (&merged_set); if (BE (err != REG_NOERROR, 0)) return err; } } return REG_NOERROR; } static reg_errcode_t internal_function update_cur_sifted_state (const re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, re_node_set *dest_nodes) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err = REG_NOERROR; const re_node_set *candidates; candidates = ((mctx->state_log[str_idx] == NULL) ? NULL : &mctx->state_log[str_idx]->nodes); if (dest_nodes->nelem == 0) sctx->sifted_states[str_idx] = NULL; else { if (candidates) { /* At first, add the nodes which can epsilon transit to a node in DEST_NODE. */ err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); if (BE (err != REG_NOERROR, 0)) return err; /* Then, check the limitations in the current sift_context. */ if (sctx->limits.nelem) { err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, mctx->bkref_ents, str_idx); if (BE (err != REG_NOERROR, 0)) return err; } } sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); if (BE (err != REG_NOERROR, 0)) return err; } if (candidates && mctx->state_log[str_idx]->has_backref) { err = sift_states_bkref (mctx, sctx, str_idx, candidates); if (BE (err != REG_NOERROR, 0)) return err; } return REG_NOERROR; } static reg_errcode_t internal_function add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, const re_node_set *candidates) { reg_errcode_t err = REG_NOERROR; int i; re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes); if (BE (err != REG_NOERROR, 0)) return err; if (!state->inveclosure.alloc) { err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem); if (BE (err != REG_NOERROR, 0)) return REG_ESPACE; for (i = 0; i < dest_nodes->nelem; i++) re_node_set_merge (&state->inveclosure, dfa->inveclosures + dest_nodes->elems[i]); } return re_node_set_add_intersect (dest_nodes, candidates, &state->inveclosure); } static reg_errcode_t internal_function sub_epsilon_src_nodes (const re_dfa_t *dfa, int node, re_node_set *dest_nodes, const re_node_set *candidates) { int ecl_idx; reg_errcode_t err; re_node_set *inv_eclosure = dfa->inveclosures + node; re_node_set except_nodes; re_node_set_init_empty (&except_nodes); for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) { int cur_node = inv_eclosure->elems[ecl_idx]; if (cur_node == node) continue; if (IS_EPSILON_NODE (dfa->nodes[cur_node].type)) { int edst1 = dfa->edests[cur_node].elems[0]; int edst2 = ((dfa->edests[cur_node].nelem > 1) ? dfa->edests[cur_node].elems[1] : -1); if ((!re_node_set_contains (inv_eclosure, edst1) && re_node_set_contains (dest_nodes, edst1)) || (edst2 > 0 && !re_node_set_contains (inv_eclosure, edst2) && re_node_set_contains (dest_nodes, edst2))) { err = re_node_set_add_intersect (&except_nodes, candidates, dfa->inveclosures + cur_node); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&except_nodes); return err; } } } } for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) { int cur_node = inv_eclosure->elems[ecl_idx]; if (!re_node_set_contains (&except_nodes, cur_node)) { int idx = re_node_set_contains (dest_nodes, cur_node) - 1; re_node_set_remove_at (dest_nodes, idx); } } re_node_set_free (&except_nodes); return REG_NOERROR; } static int internal_function check_dst_limits (const re_match_context_t *mctx, re_node_set *limits, int dst_node, int dst_idx, int src_node, int src_idx) { const re_dfa_t *const dfa = mctx->dfa; int lim_idx, src_pos, dst_pos; int dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx); int src_bkref_idx = search_cur_bkref_entry (mctx, src_idx); for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) { int subexp_idx; struct re_backref_cache_entry *ent; ent = mctx->bkref_ents + limits->elems[lim_idx]; subexp_idx = dfa->nodes[ent->node].opr.idx; dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], subexp_idx, dst_node, dst_idx, dst_bkref_idx); src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], subexp_idx, src_node, src_idx, src_bkref_idx); /* In case of: ( ) ( ) ( ) */ if (src_pos == dst_pos) continue; /* This is unrelated limitation. */ else return 1; } return 0; } static int internal_function check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries, int subexp_idx, int from_node, int bkref_idx) { const re_dfa_t *const dfa = mctx->dfa; const re_node_set *eclosures = dfa->eclosures + from_node; int node_idx; /* Else, we are on the boundary: examine the nodes on the epsilon closure. */ for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx) { int node = eclosures->elems[node_idx]; switch (dfa->nodes[node].type) { case OP_BACK_REF: if (bkref_idx != -1) { struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx; do { int dst, cpos; if (ent->node != node) continue; if (subexp_idx < BITSET_WORD_BITS && !(ent->eps_reachable_subexps_map & ((bitset_word_t) 1 << subexp_idx))) continue; /* Recurse trying to reach the OP_OPEN_SUBEXP and OP_CLOSE_SUBEXP cases below. But, if the destination node is the same node as the source node, don't recurse because it would cause an infinite loop: a regex that exhibits this behavior is ()\1*\1* */ dst = dfa->edests[node].elems[0]; if (dst == from_node) { if (boundaries & 1) return -1; else /* if (boundaries & 2) */ return 0; } cpos = check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, dst, bkref_idx); if (cpos == -1 /* && (boundaries & 1) */) return -1; if (cpos == 0 && (boundaries & 2)) return 0; if (subexp_idx < BITSET_WORD_BITS) ent->eps_reachable_subexps_map &= ~((bitset_word_t) 1 << subexp_idx); } while (ent++->more); } break; case OP_OPEN_SUBEXP: if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx) return -1; break; case OP_CLOSE_SUBEXP: if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx) return 0; break; default: break; } } return (boundaries & 2) ? 1 : 0; } static int internal_function check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit, int subexp_idx, int from_node, int str_idx, int bkref_idx) { struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; int boundaries; /* If we are outside the range of the subexpression, return -1 or 1. */ if (str_idx < lim->subexp_from) return -1; if (lim->subexp_to < str_idx) return 1; /* If we are within the subexpression, return 0. */ boundaries = (str_idx == lim->subexp_from); boundaries |= (str_idx == lim->subexp_to) << 1; if (boundaries == 0) return 0; /* Else, examine epsilon closure. */ return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, from_node, bkref_idx); } /* Check the limitations of sub expressions LIMITS, and remove the nodes which are against limitations from DEST_NODES. */ static reg_errcode_t internal_function check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes, const re_node_set *candidates, re_node_set *limits, struct re_backref_cache_entry *bkref_ents, int str_idx) { reg_errcode_t err; int node_idx, lim_idx; for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) { int subexp_idx; struct re_backref_cache_entry *ent; ent = bkref_ents + limits->elems[lim_idx]; if (str_idx <= ent->subexp_from || ent->str_idx < str_idx) continue; /* This is unrelated limitation. */ subexp_idx = dfa->nodes[ent->node].opr.idx; if (ent->subexp_to == str_idx) { int ops_node = -1; int cls_node = -1; for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) { int node = dest_nodes->elems[node_idx]; re_token_type_t type = dfa->nodes[node].type; if (type == OP_OPEN_SUBEXP && subexp_idx == dfa->nodes[node].opr.idx) ops_node = node; else if (type == OP_CLOSE_SUBEXP && subexp_idx == dfa->nodes[node].opr.idx) cls_node = node; } /* Check the limitation of the open subexpression. */ /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */ if (ops_node >= 0) { err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes, candidates); if (BE (err != REG_NOERROR, 0)) return err; } /* Check the limitation of the close subexpression. */ if (cls_node >= 0) for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) { int node = dest_nodes->elems[node_idx]; if (!re_node_set_contains (dfa->inveclosures + node, cls_node) && !re_node_set_contains (dfa->eclosures + node, cls_node)) { /* It is against this limitation. Remove it form the current sifted state. */ err = sub_epsilon_src_nodes (dfa, node, dest_nodes, candidates); if (BE (err != REG_NOERROR, 0)) return err; --node_idx; } } } else /* (ent->subexp_to != str_idx) */ { for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) { int node = dest_nodes->elems[node_idx]; re_token_type_t type = dfa->nodes[node].type; if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP) { if (subexp_idx != dfa->nodes[node].opr.idx) continue; /* It is against this limitation. Remove it form the current sifted state. */ err = sub_epsilon_src_nodes (dfa, node, dest_nodes, candidates); if (BE (err != REG_NOERROR, 0)) return err; } } } } return REG_NOERROR; } static reg_errcode_t internal_function sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, const re_node_set *candidates) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int node_idx, node; re_sift_context_t local_sctx; int first_idx = search_cur_bkref_entry (mctx, str_idx); if (first_idx == -1) return REG_NOERROR; local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */ for (node_idx = 0; node_idx < candidates->nelem; ++node_idx) { int enabled_idx; re_token_type_t type; struct re_backref_cache_entry *entry; node = candidates->elems[node_idx]; type = dfa->nodes[node].type; /* Avoid infinite loop for the REs like "()\1+". */ if (node == sctx->last_node && str_idx == sctx->last_str_idx) continue; if (type != OP_BACK_REF) continue; entry = mctx->bkref_ents + first_idx; enabled_idx = first_idx; do { int subexp_len; int to_idx; int dst_node; int ret; re_dfastate_t *cur_state; if (entry->node != node) continue; subexp_len = entry->subexp_to - entry->subexp_from; to_idx = str_idx + subexp_len; dst_node = (subexp_len ? dfa->nexts[node] : dfa->edests[node].elems[0]); if (to_idx > sctx->last_str_idx || sctx->sifted_states[to_idx] == NULL || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node) || check_dst_limits (mctx, &sctx->limits, node, str_idx, dst_node, to_idx)) continue; if (local_sctx.sifted_states == NULL) { local_sctx = *sctx; err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits); if (BE (err != REG_NOERROR, 0)) goto free_return; } local_sctx.last_node = node; local_sctx.last_str_idx = str_idx; ret = re_node_set_insert (&local_sctx.limits, enabled_idx); if (BE (ret < 0, 0)) { err = REG_ESPACE; goto free_return; } cur_state = local_sctx.sifted_states[str_idx]; err = sift_states_backward (mctx, &local_sctx); if (BE (err != REG_NOERROR, 0)) goto free_return; if (sctx->limited_states != NULL) { err = merge_state_array (dfa, sctx->limited_states, local_sctx.sifted_states, str_idx + 1); if (BE (err != REG_NOERROR, 0)) goto free_return; } local_sctx.sifted_states[str_idx] = cur_state; re_node_set_remove (&local_sctx.limits, enabled_idx); /* mctx->bkref_ents may have changed, reload the pointer. */ entry = mctx->bkref_ents + enabled_idx; } while (enabled_idx++, entry++->more); } err = REG_NOERROR; free_return: if (local_sctx.sifted_states != NULL) { re_node_set_free (&local_sctx.limits); } return err; } #ifdef RE_ENABLE_I18N static int internal_function sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, int node_idx, int str_idx, int max_str_idx) { const re_dfa_t *const dfa = mctx->dfa; int naccepted; /* Check the node can accept `multi byte'. */ naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); if (naccepted > 0 && str_idx + naccepted <= max_str_idx && !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], dfa->nexts[node_idx])) /* The node can't accept the `multi byte', or the destination was already thrown away, then the node could't accept the current input `multi byte'. */ naccepted = 0; /* Otherwise, it is sure that the node could accept `naccepted' bytes input. */ return naccepted; } #endif /* RE_ENABLE_I18N */ /* Functions for state transition. */ /* Return the next state to which the current state STATE will transit by accepting the current input byte, and update STATE_LOG if necessary. If STATE can accept a multibyte char/collating element/back reference update the destination of STATE_LOG. */ static re_dfastate_t * internal_function transit_state (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *state) { re_dfastate_t **trtable; unsigned char ch; #ifdef RE_ENABLE_I18N /* If the current state can accept multibyte. */ if (BE (state->accept_mb, 0)) { *err = transit_state_mb (mctx, state); if (BE (*err != REG_NOERROR, 0)) return NULL; } #endif /* RE_ENABLE_I18N */ /* Then decide the next state with the single byte. */ #if 0 if (0) /* don't use transition table */ return transit_state_sb (err, mctx, state); #endif /* Use transition table */ ch = re_string_fetch_byte (&mctx->input); for (;;) { trtable = state->trtable; if (BE (trtable != NULL, 1)) return trtable[ch]; trtable = state->word_trtable; if (BE (trtable != NULL, 1)) { unsigned int context; context = re_string_context_at (&mctx->input, re_string_cur_idx (&mctx->input) - 1, mctx->eflags); if (IS_WORD_CONTEXT (context)) return trtable[ch + SBC_MAX]; else return trtable[ch]; } if (!build_trtable (mctx->dfa, state)) { *err = REG_ESPACE; return NULL; } /* Retry, we now have a transition table. */ } } /* Update the state_log if we need */ re_dfastate_t * internal_function merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *next_state) { const re_dfa_t *const dfa = mctx->dfa; int cur_idx = re_string_cur_idx (&mctx->input); if (cur_idx > mctx->state_log_top) { mctx->state_log[cur_idx] = next_state; mctx->state_log_top = cur_idx; } else if (mctx->state_log[cur_idx] == 0) { mctx->state_log[cur_idx] = next_state; } else { re_dfastate_t *pstate; unsigned int context; re_node_set next_nodes, *log_nodes, *table_nodes = NULL; /* If (state_log[cur_idx] != 0), it implies that cur_idx is the destination of a multibyte char/collating element/ back reference. Then the next state is the union set of these destinations and the results of the transition table. */ pstate = mctx->state_log[cur_idx]; log_nodes = pstate->entrance_nodes; if (next_state != NULL) { table_nodes = next_state->entrance_nodes; *err = re_node_set_init_union (&next_nodes, table_nodes, log_nodes); if (BE (*err != REG_NOERROR, 0)) return NULL; } else next_nodes = *log_nodes; /* Note: We already add the nodes of the initial state, then we don't need to add them here. */ context = re_string_context_at (&mctx->input, re_string_cur_idx (&mctx->input) - 1, mctx->eflags); next_state = mctx->state_log[cur_idx] = re_acquire_state_context (err, dfa, &next_nodes, context); /* We don't need to check errors here, since the return value of this function is next_state and ERR is already set. */ if (table_nodes != NULL) re_node_set_free (&next_nodes); } if (BE (dfa->nbackref, 0) && next_state != NULL) { /* Check OP_OPEN_SUBEXP in the current state in case that we use them later. We must check them here, since the back references in the next state might use them. */ *err = check_subexp_matching_top (mctx, &next_state->nodes, cur_idx); if (BE (*err != REG_NOERROR, 0)) return NULL; /* If the next state has back references. */ if (next_state->has_backref) { *err = transit_state_bkref (mctx, &next_state->nodes); if (BE (*err != REG_NOERROR, 0)) return NULL; next_state = mctx->state_log[cur_idx]; } } return next_state; } /* Skip bytes in the input that correspond to part of a multi-byte match, then look in the log for a state from which to restart matching. */ re_dfastate_t * internal_function find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) { re_dfastate_t *cur_state; do { int max = mctx->state_log_top; int cur_str_idx = re_string_cur_idx (&mctx->input); do { if (++cur_str_idx > max) return NULL; re_string_skip_bytes (&mctx->input, 1); } while (mctx->state_log[cur_str_idx] == NULL); cur_state = merge_state_with_log (err, mctx, NULL); } while (*err == REG_NOERROR && cur_state == NULL); return cur_state; } /* Helper functions for transit_state. */ /* From the node set CUR_NODES, pick up the nodes whose types are OP_OPEN_SUBEXP and which have corresponding back references in the regular expression. And register them to use them later for evaluating the correspoding back references. */ static reg_errcode_t internal_function check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, int str_idx) { const re_dfa_t *const dfa = mctx->dfa; int node_idx; reg_errcode_t err; /* TODO: This isn't efficient. Because there might be more than one nodes whose types are OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all nodes. E.g. RE: (a){2} */ for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx) { int node = cur_nodes->elems[node_idx]; if (dfa->nodes[node].type == OP_OPEN_SUBEXP && dfa->nodes[node].opr.idx < BITSET_WORD_BITS && (dfa->used_bkref_map & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx))) { err = match_ctx_add_subtop (mctx, node, str_idx); if (BE (err != REG_NOERROR, 0)) return err; } } return REG_NOERROR; } #if 0 /* Return the next state to which the current state STATE will transit by accepting the current input byte. */ static re_dfastate_t * transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *state) { const re_dfa_t *const dfa = mctx->dfa; re_node_set next_nodes; re_dfastate_t *next_state; int node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input); unsigned int context; *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1); if (BE (*err != REG_NOERROR, 0)) return NULL; for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt) { int cur_node = state->nodes.elems[node_cnt]; if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx)) { *err = re_node_set_merge (&next_nodes, dfa->eclosures + dfa->nexts[cur_node]); if (BE (*err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return NULL; } } } context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); next_state = re_acquire_state_context (err, dfa, &next_nodes, context); /* We don't need to check errors here, since the return value of this function is next_state and ERR is already set. */ re_node_set_free (&next_nodes); re_string_skip_bytes (&mctx->input, 1); return next_state; } #endif #ifdef RE_ENABLE_I18N static reg_errcode_t internal_function transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int i; for (i = 0; i < pstate->nodes.nelem; ++i) { re_node_set dest_nodes, *new_nodes; int cur_node_idx = pstate->nodes.elems[i]; int naccepted, dest_idx; unsigned int context; re_dfastate_t *dest_state; if (!dfa->nodes[cur_node_idx].accept_mb) continue; if (dfa->nodes[cur_node_idx].constraint) { context = re_string_context_at (&mctx->input, re_string_cur_idx (&mctx->input), mctx->eflags); if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint, context)) continue; } /* How many bytes the node can accept? */ naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input, re_string_cur_idx (&mctx->input)); if (naccepted == 0) continue; /* The node can accepts `naccepted' bytes. */ dest_idx = re_string_cur_idx (&mctx->input) + naccepted; mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted : mctx->max_mb_elem_len); err = clean_state_log_if_needed (mctx, dest_idx); if (BE (err != REG_NOERROR, 0)) return err; #ifdef DEBUG assert (dfa->nexts[cur_node_idx] != -1); #endif new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx]; dest_state = mctx->state_log[dest_idx]; if (dest_state == NULL) dest_nodes = *new_nodes; else { err = re_node_set_init_union (&dest_nodes, dest_state->entrance_nodes, new_nodes); if (BE (err != REG_NOERROR, 0)) return err; } context = re_string_context_at (&mctx->input, dest_idx - 1, mctx->eflags); mctx->state_log[dest_idx] = re_acquire_state_context (&err, dfa, &dest_nodes, context); if (dest_state != NULL) re_node_set_free (&dest_nodes); if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0)) return err; } return REG_NOERROR; } #endif /* RE_ENABLE_I18N */ static reg_errcode_t internal_function transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int i; int cur_str_idx = re_string_cur_idx (&mctx->input); for (i = 0; i < nodes->nelem; ++i) { int dest_str_idx, prev_nelem, bkc_idx; int node_idx = nodes->elems[i]; unsigned int context; const re_token_t *node = dfa->nodes + node_idx; re_node_set *new_dest_nodes; /* Check whether `node' is a backreference or not. */ if (node->type != OP_BACK_REF) continue; if (node->constraint) { context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) continue; } /* `node' is a backreference. Check the substring which the substring matched. */ bkc_idx = mctx->nbkref_ents; err = get_subexp (mctx, node_idx, cur_str_idx); if (BE (err != REG_NOERROR, 0)) goto free_return; /* And add the epsilon closures (which is `new_dest_nodes') of the backreference to appropriate state_log. */ #ifdef DEBUG assert (dfa->nexts[node_idx] != -1); #endif for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx) { int subexp_len; re_dfastate_t *dest_state; struct re_backref_cache_entry *bkref_ent; bkref_ent = mctx->bkref_ents + bkc_idx; if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx) continue; subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from; new_dest_nodes = (subexp_len == 0 ? dfa->eclosures + dfa->edests[node_idx].elems[0] : dfa->eclosures + dfa->nexts[node_idx]); dest_str_idx = (cur_str_idx + bkref_ent->subexp_to - bkref_ent->subexp_from); context = re_string_context_at (&mctx->input, dest_str_idx - 1, mctx->eflags); dest_state = mctx->state_log[dest_str_idx]; prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 : mctx->state_log[cur_str_idx]->nodes.nelem); /* Add `new_dest_node' to state_log. */ if (dest_state == NULL) { mctx->state_log[dest_str_idx] = re_acquire_state_context (&err, dfa, new_dest_nodes, context); if (BE (mctx->state_log[dest_str_idx] == NULL && err != REG_NOERROR, 0)) goto free_return; } else { re_node_set dest_nodes; err = re_node_set_init_union (&dest_nodes, dest_state->entrance_nodes, new_dest_nodes); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&dest_nodes); goto free_return; } mctx->state_log[dest_str_idx] = re_acquire_state_context (&err, dfa, &dest_nodes, context); re_node_set_free (&dest_nodes); if (BE (mctx->state_log[dest_str_idx] == NULL && err != REG_NOERROR, 0)) goto free_return; } /* We need to check recursively if the backreference can epsilon transit. */ if (subexp_len == 0 && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem) { err = check_subexp_matching_top (mctx, new_dest_nodes, cur_str_idx); if (BE (err != REG_NOERROR, 0)) goto free_return; err = transit_state_bkref (mctx, new_dest_nodes); if (BE (err != REG_NOERROR, 0)) goto free_return; } } } err = REG_NOERROR; free_return: return err; } /* Enumerate all the candidates which the backreference BKREF_NODE can match at BKREF_STR_IDX, and register them by match_ctx_add_entry(). Note that we might collect inappropriate candidates here. However, the cost of checking them strictly here is too high, then we delay these checking for prune_impossible_nodes(). */ static reg_errcode_t internal_function get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx) { const re_dfa_t *const dfa = mctx->dfa; int subexp_num, sub_top_idx; const char *buf = (const char *) re_string_get_buffer (&mctx->input); /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */ int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx); if (cache_idx != -1) { const struct re_backref_cache_entry *entry = mctx->bkref_ents + cache_idx; do if (entry->node == bkref_node) return REG_NOERROR; /* We already checked it. */ while (entry++->more); } subexp_num = dfa->nodes[bkref_node].opr.idx; /* For each sub expression */ for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx) { reg_errcode_t err; re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx]; re_sub_match_last_t *sub_last; int sub_last_idx, sl_str, bkref_str_off; if (dfa->nodes[sub_top->node].opr.idx != subexp_num) continue; /* It isn't related. */ sl_str = sub_top->str_idx; bkref_str_off = bkref_str_idx; /* At first, check the last node of sub expressions we already evaluated. */ for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx) { int sl_str_diff; sub_last = sub_top->lasts[sub_last_idx]; sl_str_diff = sub_last->str_idx - sl_str; /* The matched string by the sub expression match with the substring at the back reference? */ if (sl_str_diff > 0) { if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0)) { /* Not enough chars for a successful match. */ if (bkref_str_off + sl_str_diff > mctx->input.len) break; err = clean_state_log_if_needed (mctx, bkref_str_off + sl_str_diff); if (BE (err != REG_NOERROR, 0)) return err; buf = (const char *) re_string_get_buffer (&mctx->input); } if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) /* We don't need to search this sub expression any more. */ break; } bkref_str_off += sl_str_diff; sl_str += sl_str_diff; err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, bkref_str_idx); /* Reload buf, since the preceding call might have reallocated the buffer. */ buf = (const char *) re_string_get_buffer (&mctx->input); if (err == REG_NOMATCH) continue; if (BE (err != REG_NOERROR, 0)) return err; } if (sub_last_idx < sub_top->nlasts) continue; if (sub_last_idx > 0) ++sl_str; /* Then, search for the other last nodes of the sub expression. */ for (; sl_str <= bkref_str_idx; ++sl_str) { int cls_node, sl_str_off; const re_node_set *nodes; sl_str_off = sl_str - sub_top->str_idx; /* The matched string by the sub expression match with the substring at the back reference? */ if (sl_str_off > 0) { if (BE (bkref_str_off >= mctx->input.valid_len, 0)) { /* If we are at the end of the input, we cannot match. */ if (bkref_str_off >= mctx->input.len) break; err = extend_buffers (mctx); if (BE (err != REG_NOERROR, 0)) return err; buf = (const char *) re_string_get_buffer (&mctx->input); } if (buf [bkref_str_off++] != buf[sl_str - 1]) break; /* We don't need to search this sub expression any more. */ } if (mctx->state_log[sl_str] == NULL) continue; /* Does this state have a ')' of the sub expression? */ nodes = &mctx->state_log[sl_str]->nodes; cls_node = find_subexp_node (dfa, nodes, subexp_num, OP_CLOSE_SUBEXP); if (cls_node == -1) continue; /* No. */ if (sub_top->path == NULL) { sub_top->path = calloc (sizeof (state_array_t), sl_str - sub_top->str_idx + 1); if (sub_top->path == NULL) return REG_ESPACE; } /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node in the current context? */ err = check_arrival (mctx, sub_top->path, sub_top->node, sub_top->str_idx, cls_node, sl_str, OP_CLOSE_SUBEXP); if (err == REG_NOMATCH) continue; if (BE (err != REG_NOERROR, 0)) return err; sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str); if (BE (sub_last == NULL, 0)) return REG_ESPACE; err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, bkref_str_idx); if (err == REG_NOMATCH) continue; } } return REG_NOERROR; } /* Helper functions for get_subexp(). */ /* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR. If it can arrive, register the sub expression expressed with SUB_TOP and SUB_LAST. */ static reg_errcode_t internal_function get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, re_sub_match_last_t *sub_last, int bkref_node, int bkref_str) { reg_errcode_t err; int to_idx; /* Can the subexpression arrive the back reference? */ err = check_arrival (mctx, &sub_last->path, sub_last->node, sub_last->str_idx, bkref_node, bkref_str, OP_OPEN_SUBEXP); if (err != REG_NOERROR) return err; err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx, sub_last->str_idx); if (BE (err != REG_NOERROR, 0)) return err; to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx; return clean_state_log_if_needed (mctx, to_idx); } /* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX. Search '(' if FL_OPEN, or search ')' otherwise. TODO: This function isn't efficient... Because there might be more than one nodes whose types are OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all nodes. E.g. RE: (a){2} */ static int internal_function find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, int subexp_idx, int type) { int cls_idx; for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx) { int cls_node = nodes->elems[cls_idx]; const re_token_t *node = dfa->nodes + cls_node; if (node->type == type && node->opr.idx == subexp_idx) return cls_node; } return -1; } /* Check whether the node TOP_NODE at TOP_STR can arrive to the node LAST_NODE at LAST_STR. We record the path onto PATH since it will be heavily reused. Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */ static reg_errcode_t internal_function check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node, int top_str, int last_node, int last_str, int type) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err = REG_NOERROR; int subexp_num, backup_cur_idx, str_idx, null_cnt; re_dfastate_t *cur_state = NULL; re_node_set *cur_nodes, next_nodes; re_dfastate_t **backup_state_log; unsigned int context; subexp_num = dfa->nodes[top_node].opr.idx; /* Extend the buffer if we need. */ if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0)) { re_dfastate_t **new_array; int old_alloc = path->alloc; path->alloc += last_str + mctx->max_mb_elem_len + 1; new_array = re_realloc (path->array, re_dfastate_t *, path->alloc); if (BE (new_array == NULL, 0)) { path->alloc = old_alloc; return REG_ESPACE; } path->array = new_array; memset (new_array + old_alloc, '\0', sizeof (re_dfastate_t *) * (path->alloc - old_alloc)); } #ifdef __GNUC__ /* silly buggers. */ str_idx = path->next_idx ?: top_str; #else str_idx = path->next_idx ? path->next_idx : top_str; #endif /* Temporary modify MCTX. */ backup_state_log = mctx->state_log; backup_cur_idx = mctx->input.cur_idx; mctx->state_log = path->array; mctx->input.cur_idx = str_idx; /* Setup initial node set. */ context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); if (str_idx == top_str) { err = re_node_set_init_1 (&next_nodes, top_node); if (BE (err != REG_NOERROR, 0)) return err; err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } else { cur_state = mctx->state_log[str_idx]; if (cur_state && cur_state->has_backref) { err = re_node_set_init_copy (&next_nodes, &cur_state->nodes); if (BE (err != REG_NOERROR, 0)) return err; } else re_node_set_init_empty (&next_nodes); } if (str_idx == top_str || (cur_state && cur_state->has_backref)) { if (next_nodes.nelem) { err = expand_bkref_cache (mctx, &next_nodes, str_idx, subexp_num, type); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); if (BE (cur_state == NULL && err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } mctx->state_log[str_idx] = cur_state; } for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) { re_node_set_empty (&next_nodes); if (mctx->state_log[str_idx + 1]) { err = re_node_set_merge (&next_nodes, &mctx->state_log[str_idx + 1]->nodes); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } if (cur_state) { err = check_arrival_add_next_nodes (mctx, str_idx, &cur_state->non_eps_nodes, &next_nodes); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } ++str_idx; if (next_nodes.nelem) { err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } err = expand_bkref_cache (mctx, &next_nodes, str_idx, subexp_num, type); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); if (BE (cur_state == NULL && err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } mctx->state_log[str_idx] = cur_state; null_cnt = cur_state == NULL ? null_cnt + 1 : 0; } re_node_set_free (&next_nodes); cur_nodes = (mctx->state_log[last_str] == NULL ? NULL : &mctx->state_log[last_str]->nodes); path->next_idx = str_idx; /* Fix MCTX. */ mctx->state_log = backup_state_log; mctx->input.cur_idx = backup_cur_idx; /* Then check the current node set has the node LAST_NODE. */ if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node)) return REG_NOERROR; return REG_NOMATCH; } /* Helper functions for check_arrival. */ /* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them to NEXT_NODES. TODO: This function is similar to the functions transit_state*(), however this function has many additional works. Can't we unify them? */ static reg_errcode_t internal_function check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx, re_node_set *cur_nodes, re_node_set *next_nodes) { const re_dfa_t *const dfa = mctx->dfa; int result; int cur_idx; reg_errcode_t err = REG_NOERROR; re_node_set union_set; re_node_set_init_empty (&union_set); for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx) { int naccepted = 0; int cur_node = cur_nodes->elems[cur_idx]; #ifdef DEBUG re_token_type_t type = dfa->nodes[cur_node].type; assert (!IS_EPSILON_NODE (type)); #endif #ifdef RE_ENABLE_I18N /* If the node may accept `multi byte'. */ if (dfa->nodes[cur_node].accept_mb) { naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, str_idx); if (naccepted > 1) { re_dfastate_t *dest_state; int next_node = dfa->nexts[cur_node]; int next_idx = str_idx + naccepted; dest_state = mctx->state_log[next_idx]; re_node_set_empty (&union_set); if (dest_state) { err = re_node_set_merge (&union_set, &dest_state->nodes); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&union_set); return err; } } result = re_node_set_insert (&union_set, next_node); if (BE (result < 0, 0)) { re_node_set_free (&union_set); return REG_ESPACE; } mctx->state_log[next_idx] = re_acquire_state (&err, dfa, &union_set); if (BE (mctx->state_log[next_idx] == NULL && err != REG_NOERROR, 0)) { re_node_set_free (&union_set); return err; } } } #endif /* RE_ENABLE_I18N */ if (naccepted || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) { result = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); if (BE (result < 0, 0)) { re_node_set_free (&union_set); return REG_ESPACE; } } } re_node_set_free (&union_set); return REG_NOERROR; } /* For all the nodes in CUR_NODES, add the epsilon closures of them to CUR_NODES, however exclude the nodes which are: - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN. - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN. */ static reg_errcode_t internal_function check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes, int ex_subexp, int type) { reg_errcode_t err; int idx, outside_node; re_node_set new_nodes; #ifdef DEBUG assert (cur_nodes->nelem); #endif err = re_node_set_alloc (&new_nodes, cur_nodes->nelem); if (BE (err != REG_NOERROR, 0)) return err; /* Create a new node set NEW_NODES with the nodes which are epsilon closures of the node in CUR_NODES. */ for (idx = 0; idx < cur_nodes->nelem; ++idx) { int cur_node = cur_nodes->elems[idx]; const re_node_set *eclosure = dfa->eclosures + cur_node; outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type); if (outside_node == -1) { /* There are no problematic nodes, just merge them. */ err = re_node_set_merge (&new_nodes, eclosure); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&new_nodes); return err; } } else { /* There are problematic nodes, re-calculate incrementally. */ err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node, ex_subexp, type); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&new_nodes); return err; } } } re_node_set_free (cur_nodes); *cur_nodes = new_nodes; return REG_NOERROR; } /* Helper function for check_arrival_expand_ecl. Check incrementally the epsilon closure of TARGET, and if it isn't problematic append it to DST_NODES. */ static reg_errcode_t internal_function check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, int target, int ex_subexp, int type) { int cur_node; for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);) { int err; if (dfa->nodes[cur_node].type == type && dfa->nodes[cur_node].opr.idx == ex_subexp) { if (type == OP_CLOSE_SUBEXP) { err = re_node_set_insert (dst_nodes, cur_node); if (BE (err == -1, 0)) return REG_ESPACE; } break; } err = re_node_set_insert (dst_nodes, cur_node); if (BE (err == -1, 0)) return REG_ESPACE; if (dfa->edests[cur_node].nelem == 0) break; if (dfa->edests[cur_node].nelem == 2) { err = check_arrival_expand_ecl_sub (dfa, dst_nodes, dfa->edests[cur_node].elems[1], ex_subexp, type); if (BE (err != REG_NOERROR, 0)) return err; } cur_node = dfa->edests[cur_node].elems[0]; } return REG_NOERROR; } /* For all the back references in the current state, calculate the destination of the back references by the appropriate entry in MCTX->BKREF_ENTS. */ static reg_errcode_t internal_function expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, int cur_str, int subexp_num, int type) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int cache_idx_start = search_cur_bkref_entry (mctx, cur_str); struct re_backref_cache_entry *ent; if (cache_idx_start == -1) return REG_NOERROR; restart: ent = mctx->bkref_ents + cache_idx_start; do { int to_idx, next_node; /* Is this entry ENT is appropriate? */ if (!re_node_set_contains (cur_nodes, ent->node)) continue; /* No. */ to_idx = cur_str + ent->subexp_to - ent->subexp_from; /* Calculate the destination of the back reference, and append it to MCTX->STATE_LOG. */ if (to_idx == cur_str) { /* The backreference did epsilon transit, we must re-check all the node in the current state. */ re_node_set new_dests; reg_errcode_t err2, err3; next_node = dfa->edests[ent->node].elems[0]; if (re_node_set_contains (cur_nodes, next_node)) continue; err = re_node_set_init_1 (&new_dests, next_node); err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type); err3 = re_node_set_merge (cur_nodes, &new_dests); re_node_set_free (&new_dests); if (BE (err != REG_NOERROR || err2 != REG_NOERROR || err3 != REG_NOERROR, 0)) { err = (err != REG_NOERROR ? err : (err2 != REG_NOERROR ? err2 : err3)); return err; } /* TODO: It is still inefficient... */ goto restart; } else { re_node_set union_set; next_node = dfa->nexts[ent->node]; if (mctx->state_log[to_idx]) { int ret; if (re_node_set_contains (&mctx->state_log[to_idx]->nodes, next_node)) continue; err = re_node_set_init_copy (&union_set, &mctx->state_log[to_idx]->nodes); ret = re_node_set_insert (&union_set, next_node); if (BE (err != REG_NOERROR || ret < 0, 0)) { re_node_set_free (&union_set); err = err != REG_NOERROR ? err : REG_ESPACE; return err; } } else { err = re_node_set_init_1 (&union_set, next_node); if (BE (err != REG_NOERROR, 0)) return err; } mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set); re_node_set_free (&union_set); if (BE (mctx->state_log[to_idx] == NULL && err != REG_NOERROR, 0)) return err; } } while (ent++->more); return REG_NOERROR; } /* Build transition table for the state. Return 1 if succeeded, otherwise return NULL. */ static int internal_function build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) { reg_errcode_t err; int i, j, ch, need_word_trtable = 0; bitset_word_t elem, mask; bool dests_node_malloced = false; bool dest_states_malloced = false; int ndests; /* Number of the destination states from `state'. */ re_dfastate_t **trtable; re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl; re_node_set follows, *dests_node; bitset_t *dests_ch; bitset_t acceptable; struct dests_alloc { re_node_set dests_node[SBC_MAX]; bitset_t dests_ch[SBC_MAX]; } *dests_alloc; /* We build DFA states which corresponds to the destination nodes from `state'. `dests_node[i]' represents the nodes which i-th destination state contains, and `dests_ch[i]' represents the characters which i-th destination state accepts. */ if (__libc_use_alloca (sizeof (struct dests_alloc))) dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc)); else { dests_alloc = re_malloc (struct dests_alloc, 1); if (BE (dests_alloc == NULL, 0)) return 0; dests_node_malloced = true; } dests_node = dests_alloc->dests_node; dests_ch = dests_alloc->dests_ch; /* Initialize transiton table. */ state->word_trtable = state->trtable = NULL; /* At first, group all nodes belonging to `state' into several destinations. */ ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); if (BE (ndests <= 0, 0)) { if (dests_node_malloced) free (dests_alloc); /* Return 0 in case of an error, 1 otherwise. */ if (ndests == 0) { state->trtable = (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); return 1; } return 0; } err = re_node_set_alloc (&follows, ndests + 1); if (BE (err != REG_NOERROR, 0)) goto out_free; if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX + ndests * 3 * sizeof (re_dfastate_t *))) dest_states = (re_dfastate_t **) alloca (ndests * 3 * sizeof (re_dfastate_t *)); else { dest_states = (re_dfastate_t **) malloc (ndests * 3 * sizeof (re_dfastate_t *)); if (BE (dest_states == NULL, 0)) { out_free: if (dest_states_malloced) free (dest_states); re_node_set_free (&follows); for (i = 0; i < ndests; ++i) re_node_set_free (dests_node + i); if (dests_node_malloced) free (dests_alloc); return 0; } dest_states_malloced = true; } dest_states_word = dest_states + ndests; dest_states_nl = dest_states_word + ndests; bitset_empty (acceptable); /* Then build the states for all destinations. */ for (i = 0; i < ndests; ++i) { int next_node; re_node_set_empty (&follows); /* Merge the follows of this destination states. */ for (j = 0; j < dests_node[i].nelem; ++j) { next_node = dfa->nexts[dests_node[i].elems[j]]; if (next_node != -1) { err = re_node_set_merge (&follows, dfa->eclosures + next_node); if (BE (err != REG_NOERROR, 0)) goto out_free; } } dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0); if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0)) goto out_free; /* If the new state has context constraint, build appropriate states for these contexts. */ if (dest_states[i]->has_constraint) { dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows, CONTEXT_WORD); if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0)) goto out_free; if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) need_word_trtable = 1; dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, CONTEXT_NEWLINE); if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0)) goto out_free; } else { dest_states_word[i] = dest_states[i]; dest_states_nl[i] = dest_states[i]; } bitset_merge (acceptable, dests_ch[i]); } if (!BE (need_word_trtable, 0)) { /* We don't care about whether the following character is a word character, or we are in a single-byte character set so we can discern by looking at the character code: allocate a 256-entry transition table. */ trtable = state->trtable = (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); if (BE (trtable == NULL, 0)) goto out_free; /* For all characters ch...: */ for (i = 0; i < BITSET_WORDS; ++i) for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; elem; mask <<= 1, elem >>= 1, ++ch) if (BE (elem & 1, 0)) { /* There must be exactly one destination which accepts character ch. See group_nodes_into_DFAstates. */ for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) ; /* j-th destination accepts the word character ch. */ if (dfa->word_char[i] & mask) trtable[ch] = dest_states_word[j]; else trtable[ch] = dest_states[j]; } } else { /* We care about whether the following character is a word character, and we are in a multi-byte character set: discern by looking at the character code: build two 256-entry transition tables, one starting at trtable[0] and one starting at trtable[SBC_MAX]. */ trtable = state->word_trtable = (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX); if (BE (trtable == NULL, 0)) goto out_free; /* For all characters ch...: */ for (i = 0; i < BITSET_WORDS; ++i) for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; elem; mask <<= 1, elem >>= 1, ++ch) if (BE (elem & 1, 0)) { /* There must be exactly one destination which accepts character ch. See group_nodes_into_DFAstates. */ for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) ; /* j-th destination accepts the word character ch. */ trtable[ch] = dest_states[j]; trtable[ch + SBC_MAX] = dest_states_word[j]; } } /* new line */ if (bitset_contain (acceptable, NEWLINE_CHAR)) { /* The current state accepts newline character. */ for (j = 0; j < ndests; ++j) if (bitset_contain (dests_ch[j], NEWLINE_CHAR)) { /* k-th destination accepts newline character. */ trtable[NEWLINE_CHAR] = dest_states_nl[j]; if (need_word_trtable) trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j]; /* There must be only one destination which accepts newline. See group_nodes_into_DFAstates. */ break; } } if (dest_states_malloced) free (dest_states); re_node_set_free (&follows); for (i = 0; i < ndests; ++i) re_node_set_free (dests_node + i); if (dests_node_malloced) free (dests_alloc); return 1; } /* Group all nodes belonging to STATE into several destinations. Then for all destinations, set the nodes belonging to the destination to DESTS_NODE[i] and set the characters accepted by the destination to DEST_CH[i]. This function return the number of destinations. */ static int internal_function group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, re_node_set *dests_node, bitset_t *dests_ch) { reg_errcode_t err; int result; int i, j, k; int ndests; /* Number of the destinations from `state'. */ bitset_t accepts; /* Characters a node can accept. */ const re_node_set *cur_nodes = &state->nodes; bitset_empty (accepts); ndests = 0; /* For all the nodes belonging to `state', */ for (i = 0; i < cur_nodes->nelem; ++i) { re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; re_token_type_t type = node->type; unsigned int constraint = node->constraint; /* Enumerate all single byte character this node can accept. */ if (type == CHARACTER) bitset_set (accepts, node->opr.c); else if (type == SIMPLE_BRACKET) { bitset_merge (accepts, node->opr.sbcset); } else if (type == OP_PERIOD) { #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) bitset_merge (accepts, dfa->sb_char); else #endif bitset_set_all (accepts); if (!(dfa->syntax & RE_DOT_NEWLINE)) bitset_clear (accepts, '\n'); if (dfa->syntax & RE_DOT_NOT_NULL) bitset_clear (accepts, '\0'); } #ifdef RE_ENABLE_I18N else if (type == OP_UTF8_PERIOD) { memset (accepts, '\xff', sizeof (bitset_t) / 2); if (!(dfa->syntax & RE_DOT_NEWLINE)) bitset_clear (accepts, '\n'); if (dfa->syntax & RE_DOT_NOT_NULL) bitset_clear (accepts, '\0'); } #endif else continue; /* Check the `accepts' and sift the characters which are not match it the context. */ if (constraint) { if (constraint & NEXT_NEWLINE_CONSTRAINT) { bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR); bitset_empty (accepts); if (accepts_newline) bitset_set (accepts, NEWLINE_CHAR); else continue; } if (constraint & NEXT_ENDBUF_CONSTRAINT) { bitset_empty (accepts); continue; } if (constraint & NEXT_WORD_CONSTRAINT) { bitset_word_t any_set = 0; if (type == CHARACTER && !node->word_char) { bitset_empty (accepts); continue; } #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) for (j = 0; j < BITSET_WORDS; ++j) any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); else #endif for (j = 0; j < BITSET_WORDS; ++j) any_set |= (accepts[j] &= dfa->word_char[j]); if (!any_set) continue; } if (constraint & NEXT_NOTWORD_CONSTRAINT) { bitset_word_t any_set = 0; if (type == CHARACTER && node->word_char) { bitset_empty (accepts); continue; } #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) for (j = 0; j < BITSET_WORDS; ++j) any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); else #endif for (j = 0; j < BITSET_WORDS; ++j) any_set |= (accepts[j] &= ~dfa->word_char[j]); if (!any_set) continue; } } /* Then divide `accepts' into DFA states, or create a new state. Above, we make sure that accepts is not empty. */ for (j = 0; j < ndests; ++j) { bitset_t intersec; /* Intersection sets, see below. */ bitset_t remains; /* Flags, see below. */ bitset_word_t has_intersec, not_subset, not_consumed; /* Optimization, skip if this state doesn't accept the character. */ if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) continue; /* Enumerate the intersection set of this state and `accepts'. */ has_intersec = 0; for (k = 0; k < BITSET_WORDS; ++k) has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; /* And skip if the intersection set is empty. */ if (!has_intersec) continue; /* Then check if this state is a subset of `accepts'. */ not_subset = not_consumed = 0; for (k = 0; k < BITSET_WORDS; ++k) { not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k]; not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; } /* If this state isn't a subset of `accepts', create a new group state, which has the `remains'. */ if (not_subset) { bitset_copy (dests_ch[ndests], remains); bitset_copy (dests_ch[j], intersec); err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]); if (BE (err != REG_NOERROR, 0)) goto error_return; ++ndests; } /* Put the position in the current group. */ result = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); if (BE (result < 0, 0)) goto error_return; /* If all characters are consumed, go to next node. */ if (!not_consumed) break; } /* Some characters remain, create a new group. */ if (j == ndests) { bitset_copy (dests_ch[ndests], accepts); err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]); if (BE (err != REG_NOERROR, 0)) goto error_return; ++ndests; bitset_empty (accepts); } } return ndests; error_return: for (j = 0; j < ndests; ++j) re_node_set_free (dests_node + j); return -1; } #ifdef RE_ENABLE_I18N /* Check how many bytes the node `dfa->nodes[node_idx]' accepts. Return the number of the bytes the node accepts. STR_IDX is the current index of the input string. This function handles the nodes which can accept one character, or one collating element like '.', '[a-z]', opposite to the other nodes can only accept one byte. */ static int internal_function check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, const re_string_t *input, int str_idx) { const re_token_t *node = dfa->nodes + node_idx; int char_len, elem_len; int i; if (BE (node->type == OP_UTF8_PERIOD, 0)) { unsigned char c = re_string_byte_at (input, str_idx), d; if (BE (c < 0xc2, 1)) return 0; if (str_idx + 2 > input->len) return 0; d = re_string_byte_at (input, str_idx + 1); if (c < 0xe0) return (d < 0x80 || d > 0xbf) ? 0 : 2; else if (c < 0xf0) { char_len = 3; if (c == 0xe0 && d < 0xa0) return 0; } else if (c < 0xf8) { char_len = 4; if (c == 0xf0 && d < 0x90) return 0; } else if (c < 0xfc) { char_len = 5; if (c == 0xf8 && d < 0x88) return 0; } else if (c < 0xfe) { char_len = 6; if (c == 0xfc && d < 0x84) return 0; } else return 0; if (str_idx + char_len > input->len) return 0; for (i = 1; i < char_len; ++i) { d = re_string_byte_at (input, str_idx + i); if (d < 0x80 || d > 0xbf) return 0; } return char_len; } char_len = re_string_char_size_at (input, str_idx); if (node->type == OP_PERIOD) { if (char_len <= 1) return 0; /* FIXME: I don't think this if is needed, as both '\n' and '\0' are char_len == 1. */ /* '.' accepts any one character except the following two cases. */ if ((!(dfa->syntax & RE_DOT_NEWLINE) && re_string_byte_at (input, str_idx) == '\n') || ((dfa->syntax & RE_DOT_NOT_NULL) && re_string_byte_at (input, str_idx) == '\0')) return 0; return char_len; } elem_len = re_string_elem_size_at (input, str_idx); if ((elem_len <= 1 && char_len <= 1) || char_len == 0) return 0; if (node->type == COMPLEX_BRACKET) { const re_charset_t *cset = node->opr.mbcset; # ifdef _LIBC const unsigned char *pin = ((const unsigned char *) re_string_get_buffer (input) + str_idx); int j; uint32_t nrules; # endif /* _LIBC */ int match_len = 0; wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) ? re_string_wchar_at (input, str_idx) : 0); /* match with multibyte character? */ for (i = 0; i < cset->nmbchars; ++i) if (wc == cset->mbchars[i]) { match_len = char_len; goto check_node_accept_bytes_match; } /* match with character_class? */ for (i = 0; i < cset->nchar_classes; ++i) { wctype_t wt = cset->char_classes[i]; if (__iswctype (wc, wt)) { match_len = char_len; goto check_node_accept_bytes_match; } } # ifdef _LIBC nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules != 0) { unsigned int in_collseq = 0; const int32_t *table, *indirect; const unsigned char *weights, *extra; const char *collseqwc; int32_t idx; /* This #include defines a local function! */ # include /* match with collating_symbol? */ if (cset->ncoll_syms) extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); for (i = 0; i < cset->ncoll_syms; ++i) { const unsigned char *coll_sym = extra + cset->coll_syms[i]; /* Compare the length of input collating element and the length of current collating element. */ if (*coll_sym != elem_len) continue; /* Compare each bytes. */ for (j = 0; j < *coll_sym; j++) if (pin[j] != coll_sym[1 + j]) break; if (j == *coll_sym) { /* Match if every bytes is equal. */ match_len = j; goto check_node_accept_bytes_match; } } if (cset->nranges) { if (elem_len <= char_len) { collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); in_collseq = __collseq_table_lookup (collseqwc, wc); } else in_collseq = find_collation_sequence_value (pin, elem_len); } /* match with range expression? */ for (i = 0; i < cset->nranges; ++i) if (cset->range_starts[i] <= in_collseq && in_collseq <= cset->range_ends[i]) { match_len = elem_len; goto check_node_accept_bytes_match; } /* match with equivalence_class? */ if (cset->nequiv_classes) { const unsigned char *cp = pin; table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); idx = findidx (&cp); if (idx > 0) for (i = 0; i < cset->nequiv_classes; ++i) { int32_t equiv_class_idx = cset->equiv_classes[i]; size_t weight_len = weights[idx]; if (weight_len == weights[equiv_class_idx]) { int cnt = 0; while (cnt <= weight_len && (weights[equiv_class_idx + 1 + cnt] == weights[idx + 1 + cnt])) ++cnt; if (cnt > weight_len) { match_len = elem_len; goto check_node_accept_bytes_match; } } } } } else # endif /* _LIBC */ { /* match with range expression? */ #if __GNUC__ >= 2 wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'}; #else wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; cmp_buf[2] = wc; #endif for (i = 0; i < cset->nranges; ++i) { cmp_buf[0] = cset->range_starts[i]; cmp_buf[4] = cset->range_ends[i]; if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) { match_len = char_len; goto check_node_accept_bytes_match; } } } check_node_accept_bytes_match: if (!cset->non_match) return match_len; else { if (match_len > 0) return 0; else return (elem_len > char_len) ? elem_len : char_len; } } return 0; } # ifdef _LIBC static unsigned int internal_function find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) { uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules == 0) { if (mbs_len == 1) { /* No valid character. Match it as a single byte character. */ const unsigned char *collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); return collseq[mbs[0]]; } return UINT_MAX; } else { int32_t idx; const unsigned char *extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); int32_t extrasize = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra; for (idx = 0; idx < extrasize;) { int mbs_cnt, found = 0; int32_t elem_mbs_len; /* Skip the name of collating element name. */ idx = idx + extra[idx] + 1; elem_mbs_len = extra[idx++]; if (mbs_len == elem_mbs_len) { for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt) if (extra[idx + mbs_cnt] != mbs[mbs_cnt]) break; if (mbs_cnt == elem_mbs_len) /* Found the entry. */ found = 1; } /* Skip the byte sequence of the collating element. */ idx += elem_mbs_len; /* Adjust for the alignment. */ idx = (idx + 3) & ~3; /* Skip the collation sequence value. */ idx += sizeof (uint32_t); /* Skip the wide char sequence of the collating element. */ idx = idx + sizeof (uint32_t) * (extra[idx] + 1); /* If we found the entry, return the sequence value. */ if (found) return *(uint32_t *) (extra + idx); /* Skip the collation sequence value. */ idx += sizeof (uint32_t); } return UINT_MAX; } } # endif /* _LIBC */ #endif /* RE_ENABLE_I18N */ /* Check whether the node accepts the byte which is IDX-th byte of the INPUT. */ static int internal_function check_node_accept (const re_match_context_t *mctx, const re_token_t *node, int idx) { unsigned char ch; ch = re_string_byte_at (&mctx->input, idx); switch (node->type) { case CHARACTER: if (node->opr.c != ch) return 0; break; case SIMPLE_BRACKET: if (!bitset_contain (node->opr.sbcset, ch)) return 0; break; #ifdef RE_ENABLE_I18N case OP_UTF8_PERIOD: if (ch >= 0x80) return 0; /* FALLTHROUGH */ #endif case OP_PERIOD: if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE)) || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL))) return 0; break; default: return 0; } if (node->constraint) { /* The node has constraints. Check whether the current context satisfies the constraints. */ unsigned int context = re_string_context_at (&mctx->input, idx, mctx->eflags); if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) return 0; } return 1; } /* Extend the buffers, if the buffers have run out. */ static reg_errcode_t internal_function extend_buffers (re_match_context_t *mctx) { reg_errcode_t ret; re_string_t *pstr = &mctx->input; /* Double the lengthes of the buffers. */ ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); if (BE (ret != REG_NOERROR, 0)) return ret; if (mctx->state_log != NULL) { /* And double the length of state_log. */ /* XXX We have no indication of the size of this buffer. If this allocation fail we have no indication that the state_log array does not have the right size. */ re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *, pstr->bufs_len + 1); if (BE (new_array == NULL, 0)) return REG_ESPACE; mctx->state_log = new_array; } /* Then reconstruct the buffers. */ if (pstr->icase) { #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { ret = build_wcs_upper_buffer (pstr); if (BE (ret != REG_NOERROR, 0)) return ret; } else #endif /* RE_ENABLE_I18N */ build_upper_buffer (pstr); } else { #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) build_wcs_buffer (pstr); else #endif /* RE_ENABLE_I18N */ { if (pstr->trans != NULL) re_string_translate_buffer (pstr); } } return REG_NOERROR; } /* Functions for matching context. */ /* Initialize MCTX. */ static reg_errcode_t internal_function match_ctx_init (re_match_context_t *mctx, int eflags, int n) { mctx->eflags = eflags; mctx->match_last = -1; if (n > 0) { mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); mctx->sub_tops = re_malloc (re_sub_match_top_t *, n); if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0)) return REG_ESPACE; } /* Already zero-ed by the caller. else mctx->bkref_ents = NULL; mctx->nbkref_ents = 0; mctx->nsub_tops = 0; */ mctx->abkref_ents = n; mctx->max_mb_elem_len = 1; mctx->asub_tops = n; return REG_NOERROR; } /* Clean the entries which depend on the current input in MCTX. This function must be invoked when the matcher changes the start index of the input, or changes the input string. */ static void internal_function match_ctx_clean (re_match_context_t *mctx) { int st_idx; for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx) { int sl_idx; re_sub_match_top_t *top = mctx->sub_tops[st_idx]; for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx) { re_sub_match_last_t *last = top->lasts[sl_idx]; re_free (last->path.array); re_free (last); } re_free (top->lasts); if (top->path) { re_free (top->path->array); re_free (top->path); } free (top); } mctx->nsub_tops = 0; mctx->nbkref_ents = 0; } /* Free all the memory associated with MCTX. */ static void internal_function match_ctx_free (re_match_context_t *mctx) { /* First, free all the memory associated with MCTX->SUB_TOPS. */ match_ctx_clean (mctx); re_free (mctx->sub_tops); re_free (mctx->bkref_ents); } /* Add a new backreference entry to MCTX. Note that we assume that caller never call this function with duplicate entry, and call with STR_IDX which isn't smaller than any existing entry. */ static reg_errcode_t internal_function match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from, int to) { if (mctx->nbkref_ents >= mctx->abkref_ents) { struct re_backref_cache_entry* new_entry; new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry, mctx->abkref_ents * 2); if (BE (new_entry == NULL, 0)) { re_free (mctx->bkref_ents); return REG_ESPACE; } mctx->bkref_ents = new_entry; memset (mctx->bkref_ents + mctx->nbkref_ents, '\0', sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); mctx->abkref_ents *= 2; } if (mctx->nbkref_ents > 0 && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1; mctx->bkref_ents[mctx->nbkref_ents].node = node; mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; /* This is a cache that saves negative results of check_dst_limits_calc_pos. If bit N is clear, means that this entry won't epsilon-transition to an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If it is set, check_dst_limits_calc_pos_1 will recurse and try to find one such node. A backreference does not epsilon-transition unless it is empty, so set to all zeros if FROM != TO. */ mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map = (from == to ? ~0 : 0); mctx->bkref_ents[mctx->nbkref_ents++].more = 0; if (mctx->max_mb_elem_len < to - from) mctx->max_mb_elem_len = to - from; return REG_NOERROR; } /* Search for the first entry which has the same str_idx, or -1 if none is found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ static int internal_function search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx) { int left, right, mid, last; last = right = mctx->nbkref_ents; for (left = 0; left < right;) { mid = (left + right) / 2; if (mctx->bkref_ents[mid].str_idx < str_idx) left = mid + 1; else right = mid; } if (left < last && mctx->bkref_ents[left].str_idx == str_idx) return left; else return -1; } /* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches at STR_IDX. */ static reg_errcode_t internal_function match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx) { #ifdef DEBUG assert (mctx->sub_tops != NULL); assert (mctx->asub_tops > 0); #endif if (BE (mctx->nsub_tops == mctx->asub_tops, 0)) { int new_asub_tops = mctx->asub_tops * 2; re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops, re_sub_match_top_t *, new_asub_tops); if (BE (new_array == NULL, 0)) return REG_ESPACE; mctx->sub_tops = new_array; mctx->asub_tops = new_asub_tops; } mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t)); if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0)) return REG_ESPACE; mctx->sub_tops[mctx->nsub_tops]->node = node; mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx; return REG_NOERROR; } /* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */ static re_sub_match_last_t * internal_function match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx) { re_sub_match_last_t *new_entry; if (BE (subtop->nlasts == subtop->alasts, 0)) { int new_alasts = 2 * subtop->alasts + 1; re_sub_match_last_t **new_array = re_realloc (subtop->lasts, re_sub_match_last_t *, new_alasts); if (BE (new_array == NULL, 0)) return NULL; subtop->lasts = new_array; subtop->alasts = new_alasts; } new_entry = calloc (1, sizeof (re_sub_match_last_t)); if (BE (new_entry != NULL, 1)) { subtop->lasts[subtop->nlasts] = new_entry; new_entry->node = node; new_entry->str_idx = str_idx; ++subtop->nlasts; } return new_entry; } static void internal_function sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, re_dfastate_t **limited_sts, int last_node, int last_str_idx) { sctx->sifted_states = sifted_sts; sctx->limited_states = limited_sts; sctx->last_node = last_node; sctx->last_str_idx = last_str_idx; re_node_set_init_empty (&sctx->limits); } kbuild-3686/src/oldsed/lib/stdbool_.h0000664000175000017500000000277015053010105017475 0ustar locutuslocutus/* Copyright (C) 2001-2002 Free Software Foundation, Inc. Written by Bruno Haible , 2001. 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, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _STDBOOL_H #define _STDBOOL_H /* ISO C 99 for platforms that lack it. */ /* 7.16. Boolean type and values */ /* BeOS already #defines false 0, true 1. We use the same definitions below, but temporarily we have to #undef them. */ #ifdef __BEOS__ # undef false # undef true #endif /* For the sake of symbolic names in gdb, define _Bool as an enum type. */ #ifndef __cplusplus # if !@HAVE__BOOL@ typedef enum { false = 0, true = 1 } _Bool; # endif #else typedef bool _Bool; #endif #define bool _Bool /* The other macros must be usable in preprocessor directives. */ #define false 0 #define true 1 #define __bool_true_false_are_defined 1 #endif /* _STDBOOL_H */ kbuild-3686/src/oldsed/lib/getopt.h0000664000175000017500000001076315053010105017173 0ustar locutuslocutus/* Declarations for getopt. Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. 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, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _GETOPT_H #define _GETOPT_H 1 #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if defined (__STDC__) && __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #if defined (__STDC__) && __STDC__ #ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int argc, char *const *argv, const char *shortopts); #else /* not __GNU_LIBRARY__ */ extern int getopt (); #endif /* __GNU_LIBRARY__ */ extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #else /* not __STDC__ */ extern int getopt (); extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); #endif /* __STDC__ */ #ifdef __cplusplus } #endif #endif /* getopt.h */ kbuild-3686/src/oldsed/lib/mkstemp.c0000664000175000017500000000247215053010105017342 0ustar locutuslocutus#ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_STRINGS_H # include #else # include #endif /* HAVE_STRINGS_H */ #ifdef HAVE_STDLIB_H # include #endif /* HAVE_STDLIB_H */ #ifdef HAVE_SYS_FILE_H # include #endif /* HAVE_SYS_FILE_H */ #ifdef HAVE_IO_H # include #endif /* HAVE_IO_H */ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ #ifdef HAVE_FCNTL_H #include #endif /* HAVE_FCNTL_H */ #include #include /* Generate a unique temporary file name from template. The last six characters of template must be XXXXXX and these are replaced with a string that makes the filename unique. */ int mkstemp (template) char *template; { int i, j, n, fd; char *data = template + strlen(template) - 6; if (data < template) { errno = EINVAL; return -1; } for (n = 0; n <= 5; n++) if (data[n] != 'X') { errno = EINVAL; return -1; } for (i = 0; i < INT_MAX; i++) { j = i ^ 827714841; /* Base 36 DOSSUX :-) */ for (n = 5; n >= 0; n--) { data[n] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" [j % 36]; j /= 36; } fd = open (template, O_CREAT|O_EXCL|O_RDWR, 0600); if (fd != -1) return fd; } errno = EEXIST; return -1; } kbuild-3686/src/oldsed/lib/memcmp.c0000664000175000017500000002237715053010105017146 0ustar locutuslocutus/* Copyright (C) 1991, 1993, 1995, 1997, 1998 Free Software Foundation, Inc. Contributed by Torbjorn Granlund (tege@sics.se). NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. 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, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #undef __ptr_t #if defined __cplusplus || (defined __STDC__ && __STDC__) # define __ptr_t void * #else /* Not C++ or ANSI C. */ # undef const # define const # define __ptr_t char * #endif /* C++ or ANSI C. */ #ifndef __P # if defined __GNUC__ || (defined __STDC__ && __STDC__) # define __P(args) args # else # define __P(args) () # endif /* GCC. */ #endif /* Not __P. */ #if defined HAVE_STRING_H || defined _LIBC # include #endif #undef memcmp #ifdef _LIBC # include # include # if __BYTE_ORDER == __BIG_ENDIAN # define WORDS_BIGENDIAN # endif #else /* Not in the GNU C library. */ # include /* Type to use for aligned memory operations. This should normally be the biggest type supported by a single load and store. Must be an unsigned type. */ # define op_t unsigned long int # define OPSIZ (sizeof(op_t)) /* Threshold value for when to enter the unrolled loops. */ # define OP_T_THRES 16 /* Type to use for unaligned operations. */ typedef unsigned char byte; # ifndef WORDS_BIGENDIAN # define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2))) # else # define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2))) # endif #endif /* In the GNU C library. */ #ifdef WORDS_BIGENDIAN # define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1) #else # define CMP_LT_OR_GT(a, b) memcmp_bytes ((a), (b)) #endif /* BE VERY CAREFUL IF YOU CHANGE THIS CODE! */ /* The strategy of this memcmp is: 1. Compare bytes until one of the block pointers is aligned. 2. Compare using memcmp_common_alignment or memcmp_not_common_alignment, regarding the alignment of the other block after the initial byte operations. The maximum number of full words (of type op_t) are compared in this way. 3. Compare the few remaining bytes. */ #ifndef WORDS_BIGENDIAN /* memcmp_bytes -- Compare A and B bytewise in the byte order of the machine. A and B are known to be different. This is needed only on little-endian machines. */ static int memcmp_bytes __P((op_t, op_t)); # ifdef __GNUC__ __inline # endif static int memcmp_bytes (a, b) op_t a, b; { long int srcp1 = (long int) &a; long int srcp2 = (long int) &b; op_t a0, b0; do { a0 = ((byte *) srcp1)[0]; b0 = ((byte *) srcp2)[0]; srcp1 += 1; srcp2 += 1; } while (a0 == b0); return a0 - b0; } #endif static int memcmp_common_alignment __P((long, long, size_t)); /* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t' objects (not LEN bytes!). Both SRCP1 and SRCP2 should be aligned for memory operations on `op_t's. */ #ifdef __GNUC__ __inline #endif static int memcmp_common_alignment (srcp1, srcp2, len) long int srcp1; long int srcp2; size_t len; { op_t a0, a1; op_t b0, b1; switch (len % 4) { default: /* Avoid warning about uninitialized local variables. */ case 2: a0 = ((op_t *) srcp1)[0]; b0 = ((op_t *) srcp2)[0]; srcp1 -= 2 * OPSIZ; srcp2 -= 2 * OPSIZ; len += 2; goto do1; case 3: a1 = ((op_t *) srcp1)[0]; b1 = ((op_t *) srcp2)[0]; srcp1 -= OPSIZ; srcp2 -= OPSIZ; len += 1; goto do2; case 0: if (OP_T_THRES <= 3 * OPSIZ && len == 0) return 0; a0 = ((op_t *) srcp1)[0]; b0 = ((op_t *) srcp2)[0]; goto do3; case 1: a1 = ((op_t *) srcp1)[0]; b1 = ((op_t *) srcp2)[0]; srcp1 += OPSIZ; srcp2 += OPSIZ; len -= 1; if (OP_T_THRES <= 3 * OPSIZ && len == 0) goto do0; /* Fall through. */ } do { a0 = ((op_t *) srcp1)[0]; b0 = ((op_t *) srcp2)[0]; if (a1 != b1) return CMP_LT_OR_GT (a1, b1); do3: a1 = ((op_t *) srcp1)[1]; b1 = ((op_t *) srcp2)[1]; if (a0 != b0) return CMP_LT_OR_GT (a0, b0); do2: a0 = ((op_t *) srcp1)[2]; b0 = ((op_t *) srcp2)[2]; if (a1 != b1) return CMP_LT_OR_GT (a1, b1); do1: a1 = ((op_t *) srcp1)[3]; b1 = ((op_t *) srcp2)[3]; if (a0 != b0) return CMP_LT_OR_GT (a0, b0); srcp1 += 4 * OPSIZ; srcp2 += 4 * OPSIZ; len -= 4; } while (len != 0); /* This is the right position for do0. Please don't move it into the loop. */ do0: if (a1 != b1) return CMP_LT_OR_GT (a1, b1); return 0; } static int memcmp_not_common_alignment __P((long, long, size_t)); /* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t' objects (not LEN bytes!). SRCP2 should be aligned for memory operations on `op_t', but SRCP1 *should be unaligned*. */ #ifdef __GNUC__ __inline #endif static int memcmp_not_common_alignment (srcp1, srcp2, len) long int srcp1; long int srcp2; size_t len; { op_t a0, a1, a2, a3; op_t b0, b1, b2, b3; op_t x; int shl, shr; /* Calculate how to shift a word read at the memory operation aligned srcp1 to make it aligned for comparison. */ shl = 8 * (srcp1 % OPSIZ); shr = 8 * OPSIZ - shl; /* Make SRCP1 aligned by rounding it down to the beginning of the `op_t' it points in the middle of. */ srcp1 &= -OPSIZ; switch (len % 4) { default: /* Avoid warning about uninitialized local variables. */ case 2: a1 = ((op_t *) srcp1)[0]; a2 = ((op_t *) srcp1)[1]; b2 = ((op_t *) srcp2)[0]; srcp1 -= 1 * OPSIZ; srcp2 -= 2 * OPSIZ; len += 2; goto do1; case 3: a0 = ((op_t *) srcp1)[0]; a1 = ((op_t *) srcp1)[1]; b1 = ((op_t *) srcp2)[0]; srcp2 -= 1 * OPSIZ; len += 1; goto do2; case 0: if (OP_T_THRES <= 3 * OPSIZ && len == 0) return 0; a3 = ((op_t *) srcp1)[0]; a0 = ((op_t *) srcp1)[1]; b0 = ((op_t *) srcp2)[0]; srcp1 += 1 * OPSIZ; goto do3; case 1: a2 = ((op_t *) srcp1)[0]; a3 = ((op_t *) srcp1)[1]; b3 = ((op_t *) srcp2)[0]; srcp1 += 2 * OPSIZ; srcp2 += 1 * OPSIZ; len -= 1; if (OP_T_THRES <= 3 * OPSIZ && len == 0) goto do0; /* Fall through. */ } do { a0 = ((op_t *) srcp1)[0]; b0 = ((op_t *) srcp2)[0]; x = MERGE(a2, shl, a3, shr); if (x != b3) return CMP_LT_OR_GT (x, b3); do3: a1 = ((op_t *) srcp1)[1]; b1 = ((op_t *) srcp2)[1]; x = MERGE(a3, shl, a0, shr); if (x != b0) return CMP_LT_OR_GT (x, b0); do2: a2 = ((op_t *) srcp1)[2]; b2 = ((op_t *) srcp2)[2]; x = MERGE(a0, shl, a1, shr); if (x != b1) return CMP_LT_OR_GT (x, b1); do1: a3 = ((op_t *) srcp1)[3]; b3 = ((op_t *) srcp2)[3]; x = MERGE(a1, shl, a2, shr); if (x != b2) return CMP_LT_OR_GT (x, b2); srcp1 += 4 * OPSIZ; srcp2 += 4 * OPSIZ; len -= 4; } while (len != 0); /* This is the right position for do0. Please don't move it into the loop. */ do0: x = MERGE(a2, shl, a3, shr); if (x != b3) return CMP_LT_OR_GT (x, b3); return 0; } int memcmp (s1, s2, len) const __ptr_t s1; const __ptr_t s2; size_t len; { op_t a0; op_t b0; long int srcp1 = (long int) s1; long int srcp2 = (long int) s2; op_t res; if (len >= OP_T_THRES) { /* There are at least some bytes to compare. No need to test for LEN == 0 in this alignment loop. */ while (srcp2 % OPSIZ != 0) { a0 = ((byte *) srcp1)[0]; b0 = ((byte *) srcp2)[0]; srcp1 += 1; srcp2 += 1; res = a0 - b0; if (res != 0) return res; len -= 1; } /* SRCP2 is now aligned for memory operations on `op_t'. SRCP1 alignment determines if we can do a simple, aligned compare or need to shuffle bits. */ if (srcp1 % OPSIZ == 0) res = memcmp_common_alignment (srcp1, srcp2, len / OPSIZ); else res = memcmp_not_common_alignment (srcp1, srcp2, len / OPSIZ); if (res != 0) return res; /* Number of bytes remaining in the interval [0..OPSIZ-1]. */ srcp1 += len & -OPSIZ; srcp2 += len & -OPSIZ; len %= OPSIZ; } /* There are just a few bytes to compare. Use byte memory operations. */ while (len != 0) { a0 = ((byte *) srcp1)[0]; b0 = ((byte *) srcp2)[0]; srcp1 += 1; srcp2 += 1; res = a0 - b0; if (res != 0) return res; len -= 1; } return 0; } #ifdef weak_alias # undef bcmp weak_alias (memcmp, bcmp) #endif kbuild-3686/src/oldsed/lib/strverscmp.h0000664000175000017500000000063015053010104020070 0ustar locutuslocutus/* strverscmp.h -- compare strings holding indices/version numbers */ #ifndef STRVERSCMP_H_ # define STRVERSCMP_H_ # if HAVE_CONFIG_H # include # endif # ifndef PARAMS # if defined PROTOTYPES || (defined __STDC__ && __STDC__) # define PARAMS(Args) Args # else # define PARAMS(Args) () # endif # endif int strverscmp PARAMS ((const char*, const char*)); #endif /* not STRVERSCMP_H_ */ kbuild-3686/src/oldsed/lib/regex.c0000664000175000017500000000561315053010105016774 0ustar locutuslocutus/* Extended regular expression matching and search library. Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* Make sure noone compiles this code with a C++ compiler. */ #ifdef __cplusplus # error "This is C code, use a C compiler" #endif #ifdef _LIBC /* We have to keep the namespace clean. */ # define regfree(preg) __regfree (preg) # define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) # define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) # define regerror(errcode, preg, errbuf, errbuf_size) \ __regerror(errcode, preg, errbuf, errbuf_size) # define re_set_registers(bu, re, nu, st, en) \ __re_set_registers (bu, re, nu, st, en) # define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) # define re_match(bufp, string, size, pos, regs) \ __re_match (bufp, string, size, pos, regs) # define re_search(bufp, string, size, startpos, range, regs) \ __re_search (bufp, string, size, startpos, range, regs) # define re_compile_pattern(pattern, length, bufp) \ __re_compile_pattern (pattern, length, bufp) # define re_set_syntax(syntax) __re_set_syntax (syntax) # define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) # define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) # include "../locale/localeinfo.h" #endif /* On some systems, limits.h sets RE_DUP_MAX to a lower value than GNU regex allows. Include it before , which correctly #undefs RE_DUP_MAX and sets it to the right value. */ #include #include #include "regex_internal.h" #include "regex_internal.c" #include "regcomp.c" #include "regexec.c" /* Binary backward compatibility. */ #if _LIBC # include # if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") int re_max_failures = 2000; # endif #endif kbuild-3686/src/oldsed/lib/strverscmp.c0000664000175000017500000000773515053010104020100 0ustar locutuslocutus/* Compare strings while treating digits characters numerically. Copyright (C) 1997, 2000, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jean-François Bignolles , 1997. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #if HAVE_CONFIG_H # include #endif #include #include /* states: S_N: normal, S_I: comparing integral part, S_F: comparing fractional parts, S_Z: idem but with leading Zeroes only */ #define S_N 0x0 #define S_I 0x4 #define S_F 0x8 #define S_Z 0xC /* result_type: CMP: return diff; LEN: compare using len_diff/diff */ #define CMP 2 #define LEN 3 /* ISDIGIT differs from isdigit, as follows: - Its arg may be any int or unsigned int; it need not be an unsigned char. - It's guaranteed to evaluate its argument exactly once. - It's typically faster. POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to ISDIGIT_LOCALE unless it's important to use the locale's definition of `digit' even when the host does not conform to POSIX. */ #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) #undef __strverscmp #undef strverscmp #ifndef weak_alias # define __strverscmp strverscmp #endif /* Compare S1 and S2 as strings holding indices/version numbers, returning less than, equal to or greater than zero if S1 is less than, equal to or greater than S2 (for more info, see the texinfo doc). */ int __strverscmp (const char *s1, const char *s2) { const unsigned char *p1 = (const unsigned char *) s1; const unsigned char *p2 = (const unsigned char *) s2; unsigned char c1, c2; int state; int diff; /* Symbol(s) 0 [1-9] others (padding) Transition (10) 0 (01) d (00) x (11) - */ static const unsigned int next_state[] = { /* state x d 0 - */ /* S_N */ S_N, S_I, S_Z, S_N, /* S_I */ S_N, S_I, S_I, S_I, /* S_F */ S_N, S_F, S_F, S_F, /* S_Z */ S_N, S_F, S_Z, S_Z }; static const int result_type[] = { /* state x/x x/d x/0 x/- d/x d/d d/0 d/- 0/x 0/d 0/0 0/- -/x -/d -/0 -/- */ /* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, /* S_I */ CMP, -1, -1, CMP, 1, LEN, LEN, CMP, 1, LEN, LEN, CMP, CMP, CMP, CMP, CMP, /* S_F */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, /* S_Z */ CMP, 1, 1, CMP, -1, CMP, CMP, CMP, -1, CMP, CMP, CMP }; if (p1 == p2) return 0; c1 = *p1++; c2 = *p2++; /* Hint: '0' is a digit too. */ state = S_N | ((c1 == '0') + (ISDIGIT (c1) != 0)); while ((diff = c1 - c2) == 0 && c1 != '\0') { state = next_state[state]; c1 = *p1++; c2 = *p2++; state |= (c1 == '0') + (ISDIGIT (c1) != 0); } state = result_type[state << 2 | ((c2 == '0') + (ISDIGIT (c2) != 0))]; switch (state) { case CMP: return diff; case LEN: while (ISDIGIT (*p1++)) if (!ISDIGIT (*p2++)) return 1; return ISDIGIT (*p2) ? -1 : diff; default: return state; } } #ifdef weak_alias weak_alias (__strverscmp, strverscmp) #endif kbuild-3686/src/oldsed/lib/regex_internal.h0000664000175000017500000005275215053010105020703 0ustar locutuslocutus/* Extended regular expression matching and search library. Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _REGEX_INTERNAL_H #define _REGEX_INTERNAL_H 1 #include #include #include #include #include #if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC # include #endif #if defined HAVE_LOCALE_H || defined _LIBC # include #endif #if defined HAVE_WCHAR_H || defined _LIBC # include #endif /* HAVE_WCHAR_H || _LIBC */ #if defined HAVE_WCTYPE_H || defined _LIBC # include #endif /* HAVE_WCTYPE_H || _LIBC */ #if defined HAVE_STDBOOL_H || defined _LIBC || defined(__HAIKU__) /* haiku hack */ # include #endif /* HAVE_STDBOOL_H || _LIBC */ #if defined _LIBC # include #else # define __libc_lock_define(CLASS,NAME) # define __libc_lock_init(NAME) do { } while (0) # define __libc_lock_lock(NAME) do { } while (0) # define __libc_lock_unlock(NAME) do { } while (0) #endif /* In case that the system doesn't have isblank(). */ #if !defined _LIBC && !defined HAVE_ISBLANK && !defined isblank # define isblank(ch) ((ch) == ' ' || (ch) == '\t') #endif #ifdef _LIBC # ifndef _RE_DEFINE_LOCALE_FUNCTIONS # define _RE_DEFINE_LOCALE_FUNCTIONS 1 # include # include # include # endif #endif /* This is for other GNU distributions with internationalized messages. */ #if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC # include # ifdef _LIBC # undef gettext # define gettext(msgid) \ INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES) # endif #else # define gettext(msgid) (msgid) #endif #ifndef gettext_noop /* This define is so xgettext can find the internationalizable strings. */ # define gettext_noop(String) String #endif #if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC # if defined(__OS2__) /* setlocale() misbehaves in LIBC 0.6.1 and earlier, breaking /[a-z]/. */ # if defined(__KLIBC_VERSION__) # if __KLIBC_VERSION__ >= 0x00060002 # define RE_ENABLE_I18N # endif # endif # else # define RE_ENABLE_I18N # endif #endif #if __GNUC__ >= 3 # define BE(expr, val) __builtin_expect (expr, val) #else # define BE(expr, val) (expr) # ifndef inline /* bird: silly since the rest of sed depends on this working.. */ # define inline # endif #endif /* Number of single byte character. */ #define SBC_MAX 256 #define COLL_ELEM_LEN_MAX 8 /* The character which represents newline. */ #define NEWLINE_CHAR '\n' #define WIDE_NEWLINE_CHAR L'\n' /* Rename to standard API for using out of glibc. */ #ifndef _LIBC # define __wctype wctype # define __iswctype iswctype # define __btowc btowc # ifndef __mempcpy /* keep quiet if string.h defines it (bird) */ # define __mempcpy mempcpy # endif # define __wcrtomb wcrtomb # define __regfree regfree # define attribute_hidden #endif /* not _LIBC */ #ifdef __GNUC__ # define __attribute(arg) __attribute__ (arg) #else # define __attribute(arg) #endif #ifndef SIZE_MAX #define SIZE_MAX ((size_t)-1) #endif extern const char __re_error_msgid[] attribute_hidden; extern const size_t __re_error_msgid_idx[] attribute_hidden; /* An integer used to represent a set of bits. It must be unsigned, and must be at least as wide as unsigned int. */ typedef unsigned long int bitset_word_t; /* All bits set in a bitset_word_t. */ #define BITSET_WORD_MAX ULONG_MAX /* Number of bits in a bitset_word_t. */ #define BITSET_WORD_BITS (sizeof (bitset_word_t) * CHAR_BIT) /* Number of bitset_word_t in a bit_set. */ #define BITSET_WORDS (SBC_MAX / BITSET_WORD_BITS) typedef bitset_word_t bitset_t[BITSET_WORDS]; typedef bitset_word_t *re_bitset_ptr_t; typedef const bitset_word_t *re_const_bitset_ptr_t; #define bitset_set(set,i) \ (set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS) #define bitset_clear(set,i) \ (set[i / BITSET_WORD_BITS] &= ~((bitset_word_t) 1 << i % BITSET_WORD_BITS)) #define bitset_contain(set,i) \ (set[i / BITSET_WORD_BITS] & ((bitset_word_t) 1 << i % BITSET_WORD_BITS)) #define bitset_empty(set) memset (set, '\0', sizeof (bitset_t)) #define bitset_set_all(set) memset (set, '\xff', sizeof (bitset_t)) #define bitset_copy(dest,src) memcpy (dest, src, sizeof (bitset_t)) #define PREV_WORD_CONSTRAINT 0x0001 #define PREV_NOTWORD_CONSTRAINT 0x0002 #define NEXT_WORD_CONSTRAINT 0x0004 #define NEXT_NOTWORD_CONSTRAINT 0x0008 #define PREV_NEWLINE_CONSTRAINT 0x0010 #define NEXT_NEWLINE_CONSTRAINT 0x0020 #define PREV_BEGBUF_CONSTRAINT 0x0040 #define NEXT_ENDBUF_CONSTRAINT 0x0080 #define WORD_DELIM_CONSTRAINT 0x0100 #define NOT_WORD_DELIM_CONSTRAINT 0x0200 typedef enum { INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, LINE_FIRST = PREV_NEWLINE_CONSTRAINT, LINE_LAST = NEXT_NEWLINE_CONSTRAINT, BUF_FIRST = PREV_BEGBUF_CONSTRAINT, BUF_LAST = NEXT_ENDBUF_CONSTRAINT, WORD_DELIM = WORD_DELIM_CONSTRAINT, NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT } re_context_type; typedef struct { int alloc; int nelem; int *elems; } re_node_set; typedef enum { NON_TYPE = 0, /* Node type, These are used by token, node, tree. */ CHARACTER = 1, END_OF_RE = 2, SIMPLE_BRACKET = 3, OP_BACK_REF = 4, OP_PERIOD = 5, #ifdef RE_ENABLE_I18N COMPLEX_BRACKET = 6, OP_UTF8_PERIOD = 7, #endif /* RE_ENABLE_I18N */ /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used when the debugger shows values of this enum type. */ #define EPSILON_BIT 8 OP_OPEN_SUBEXP = EPSILON_BIT | 0, OP_CLOSE_SUBEXP = EPSILON_BIT | 1, OP_ALT = EPSILON_BIT | 2, OP_DUP_ASTERISK = EPSILON_BIT | 3, ANCHOR = EPSILON_BIT | 4, /* Tree type, these are used only by tree. */ CONCAT = 16, SUBEXP = 17, /* Token type, these are used only by token. */ OP_DUP_PLUS = 18, OP_DUP_QUESTION, OP_OPEN_BRACKET, OP_CLOSE_BRACKET, OP_CHARSET_RANGE, OP_OPEN_DUP_NUM, OP_CLOSE_DUP_NUM, OP_NON_MATCH_LIST, OP_OPEN_COLL_ELEM, OP_CLOSE_COLL_ELEM, OP_OPEN_EQUIV_CLASS, OP_CLOSE_EQUIV_CLASS, OP_OPEN_CHAR_CLASS, OP_CLOSE_CHAR_CLASS, OP_WORD, OP_NOTWORD, OP_SPACE, OP_NOTSPACE, BACK_SLASH } re_token_type_t; #ifdef RE_ENABLE_I18N typedef struct { /* Multibyte characters. */ wchar_t *mbchars; /* Collating symbols. */ # ifdef _LIBC int32_t *coll_syms; # endif /* Equivalence classes. */ # ifdef _LIBC int32_t *equiv_classes; # endif /* Range expressions. */ # ifdef _LIBC uint32_t *range_starts; uint32_t *range_ends; # else /* not _LIBC */ wchar_t *range_starts; wchar_t *range_ends; # endif /* not _LIBC */ /* Character classes. */ wctype_t *char_classes; /* If this character set is the non-matching list. */ unsigned int non_match : 1; /* # of multibyte characters. */ int nmbchars; /* # of collating symbols. */ int ncoll_syms; /* # of equivalence classes. */ int nequiv_classes; /* # of range expressions. */ int nranges; /* # of character classes. */ int nchar_classes; } re_charset_t; #endif /* RE_ENABLE_I18N */ typedef struct { union { unsigned char c; /* for CHARACTER */ re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ #ifdef RE_ENABLE_I18N re_charset_t *mbcset; /* for COMPLEX_BRACKET */ #endif /* RE_ENABLE_I18N */ int idx; /* for BACK_REF */ re_context_type ctx_type; /* for ANCHOR */ } opr; #if __GNUC__ >= 2 re_token_type_t type : 8; #else re_token_type_t type; #endif unsigned int constraint : 10; /* context constraint */ unsigned int duplicated : 1; unsigned int opt_subexp : 1; #ifdef RE_ENABLE_I18N unsigned int accept_mb : 1; /* These 2 bits can be moved into the union if needed (e.g. if running out of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ unsigned int mb_partial : 1; #endif unsigned int word_char : 1; } re_token_t; #define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT) struct re_string_t { /* Indicate the raw buffer which is the original string passed as an argument of regexec(), re_search(), etc.. */ const unsigned char *raw_mbs; /* Store the multibyte string. In case of "case insensitive mode" like REG_ICASE, upper cases of the string are stored, otherwise MBS points the same address that RAW_MBS points. */ unsigned char *mbs; #ifdef RE_ENABLE_I18N /* Store the wide character string which is corresponding to MBS. */ wint_t *wcs; int *offsets; mbstate_t cur_state; #endif /* Index in RAW_MBS. Each character mbs[i] corresponds to raw_mbs[raw_mbs_idx + i]. */ int raw_mbs_idx; /* The length of the valid characters in the buffers. */ int valid_len; /* The corresponding number of bytes in raw_mbs array. */ int valid_raw_len; /* The length of the buffers MBS and WCS. */ int bufs_len; /* The index in MBS, which is updated by re_string_fetch_byte. */ int cur_idx; /* length of RAW_MBS array. */ int raw_len; /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */ int len; /* End of the buffer may be shorter than its length in the cases such as re_match_2, re_search_2. Then, we use STOP for end of the buffer instead of LEN. */ int raw_stop; /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */ int stop; /* The context of mbs[0]. We store the context independently, since the context of mbs[0] may be different from raw_mbs[0], which is the beginning of the input string. */ unsigned int tip_context; /* The translation passed as a part of an argument of re_compile_pattern. */ RE_TRANSLATE_TYPE trans; /* Copy of re_dfa_t's word_char. */ re_const_bitset_ptr_t word_char; /* 1 if REG_ICASE. */ unsigned char icase; unsigned char is_utf8; unsigned char map_notascii; unsigned char mbs_allocated; unsigned char offsets_needed; unsigned char newline_anchor; unsigned char word_ops_used; int mb_cur_max; }; typedef struct re_string_t re_string_t; struct re_dfa_t; typedef struct re_dfa_t re_dfa_t; #ifndef _LIBC # ifdef __i386__ # ifdef __OS2__ # define internal_function __attribute ((regparm (3))) # else # define internal_function __attribute ((regparm (3), stdcall)) # endif # else # define internal_function # endif #endif static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, int new_buf_len) internal_function; #ifdef RE_ENABLE_I18N static void build_wcs_buffer (re_string_t *pstr) internal_function; static int build_wcs_upper_buffer (re_string_t *pstr) internal_function; #endif /* RE_ENABLE_I18N */ static void build_upper_buffer (re_string_t *pstr) internal_function; static void re_string_translate_buffer (re_string_t *pstr) internal_function; static unsigned int re_string_context_at (const re_string_t *input, int idx, int eflags) internal_function __attribute ((pure)); #define re_string_peek_byte(pstr, offset) \ ((pstr)->mbs[(pstr)->cur_idx + offset]) #define re_string_fetch_byte(pstr) \ ((pstr)->mbs[(pstr)->cur_idx++]) #define re_string_first_byte(pstr, idx) \ ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF) #define re_string_is_single_byte_char(pstr, idx) \ ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \ || (pstr)->wcs[(idx) + 1] != WEOF)) #define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx) #define re_string_cur_idx(pstr) ((pstr)->cur_idx) #define re_string_get_buffer(pstr) ((pstr)->mbs) #define re_string_length(pstr) ((pstr)->len) #define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx]) #define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) #define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) #if HAVE_ALLOCA_H # include #elif HAVE_MALLOC_H # include #endif #ifndef _LIBC # if HAVE_ALLOCA /* The OS usually guarantees only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely allocate anything larger than 4096 bytes. Also care for the possibility of a few compiler-allocated temporary stack slots. */ # define __libc_use_alloca(n) ((n) < 4032) # else /* alloca is implemented with malloc, so just use malloc. */ # define __libc_use_alloca(n) 0 # endif #endif #define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) #define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) #define re_free(p) free (p) struct bin_tree_t { struct bin_tree_t *parent; struct bin_tree_t *left; struct bin_tree_t *right; struct bin_tree_t *first; struct bin_tree_t *next; re_token_t token; /* `node_idx' is the index in dfa->nodes, if `type' == 0. Otherwise `type' indicate the type of this node. */ int node_idx; }; typedef struct bin_tree_t bin_tree_t; #define BIN_TREE_STORAGE_SIZE \ ((1024 - sizeof (void *)) / sizeof (bin_tree_t)) struct bin_tree_storage_t { struct bin_tree_storage_t *next; bin_tree_t data[BIN_TREE_STORAGE_SIZE]; }; typedef struct bin_tree_storage_t bin_tree_storage_t; #define CONTEXT_WORD 1 #define CONTEXT_NEWLINE (CONTEXT_WORD << 1) #define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1) #define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1) #define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD) #define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE) #define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF) #define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF) #define IS_ORDINARY_CONTEXT(c) ((c) == 0) #define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_') #define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR) #define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_') #define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR) #define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \ ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\ || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context))) #define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \ ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \ || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context))) struct re_dfastate_t { unsigned int hash; re_node_set nodes; re_node_set non_eps_nodes; re_node_set inveclosure; re_node_set *entrance_nodes; struct re_dfastate_t **trtable, **word_trtable; unsigned int context : 4; unsigned int halt : 1; /* If this state can accept `multi byte'. Note that we refer to multibyte characters, and multi character collating elements as `multi byte'. */ unsigned int accept_mb : 1; /* If this state has backreference node(s). */ unsigned int has_backref : 1; unsigned int has_constraint : 1; }; typedef struct re_dfastate_t re_dfastate_t; struct re_state_table_entry { int num; int alloc; re_dfastate_t **array; }; /* Array type used in re_sub_match_last_t and re_sub_match_top_t. */ typedef struct { int next_idx; int alloc; re_dfastate_t **array; } state_array_t; /* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */ typedef struct { int node; int str_idx; /* The position NODE match at. */ state_array_t path; } re_sub_match_last_t; /* Store information about the node NODE whose type is OP_OPEN_SUBEXP. And information about the node, whose type is OP_CLOSE_SUBEXP, corresponding to NODE is stored in LASTS. */ typedef struct { int str_idx; int node; state_array_t *path; int alasts; /* Allocation size of LASTS. */ int nlasts; /* The number of LASTS. */ re_sub_match_last_t **lasts; } re_sub_match_top_t; struct re_backref_cache_entry { int node; int str_idx; int subexp_from; int subexp_to; char more; char unused; unsigned short int eps_reachable_subexps_map; }; typedef struct { /* The string object corresponding to the input string. */ re_string_t input; #if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) const re_dfa_t *const dfa; #else const re_dfa_t *dfa; #endif /* EFLAGS of the argument of regexec. */ int eflags; /* Where the matching ends. */ int match_last; int last_node; /* The state log used by the matcher. */ re_dfastate_t **state_log; int state_log_top; /* Back reference cache. */ int nbkref_ents; int abkref_ents; struct re_backref_cache_entry *bkref_ents; int max_mb_elem_len; int nsub_tops; int asub_tops; re_sub_match_top_t **sub_tops; } re_match_context_t; typedef struct { re_dfastate_t **sifted_states; re_dfastate_t **limited_states; int last_node; int last_str_idx; re_node_set limits; } re_sift_context_t; struct re_fail_stack_ent_t { int idx; int node; regmatch_t *regs; re_node_set eps_via_nodes; }; struct re_fail_stack_t { int num; int alloc; struct re_fail_stack_ent_t *stack; }; struct re_dfa_t { re_token_t *nodes; size_t nodes_alloc; size_t nodes_len; int *nexts; int *org_indices; re_node_set *edests; re_node_set *eclosures; re_node_set *inveclosures; struct re_state_table_entry *state_table; re_dfastate_t *init_state; re_dfastate_t *init_state_word; re_dfastate_t *init_state_nl; re_dfastate_t *init_state_begbuf; bin_tree_t *str_tree; bin_tree_storage_t *str_tree_storage; re_bitset_ptr_t sb_char; int str_tree_storage_idx; /* number of subexpressions `re_nsub' is in regex_t. */ unsigned int state_hash_mask; int init_node; int nbackref; /* The number of backreference in this dfa. */ /* Bitmap expressing which backreference is used. */ bitset_word_t used_bkref_map; bitset_word_t completed_bkref_map; unsigned int has_plural_match : 1; /* If this dfa has "multibyte node", which is a backreference or a node which can accept multibyte character or multi character collating element. */ unsigned int has_mb_node : 1; unsigned int is_utf8 : 1; unsigned int map_notascii : 1; unsigned int word_ops_used : 1; int mb_cur_max; bitset_t word_char; reg_syntax_t syntax; int *subexp_map; #ifdef DEBUG char* re_str; #endif __libc_lock_define (, lock) }; #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) #define re_node_set_remove(set,id) \ (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) #define re_node_set_empty(p) ((p)->nelem = 0) #define re_node_set_free(set) re_free ((set)->elems) typedef enum { SB_CHAR, MB_CHAR, EQUIV_CLASS, COLL_SYM, CHAR_CLASS } bracket_elem_type; typedef struct { bracket_elem_type type; union { unsigned char ch; unsigned char *name; wchar_t wch; } opr; } bracket_elem_t; /* Inline functions for bitset operation. */ static inline void bitset_not (bitset_t set) { int bitset_i; for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) set[bitset_i] = ~set[bitset_i]; } static inline void bitset_merge (bitset_t dest, const bitset_t src) { int bitset_i; for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) dest[bitset_i] |= src[bitset_i]; } static inline void bitset_mask (bitset_t dest, const bitset_t src) { int bitset_i; for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) dest[bitset_i] &= src[bitset_i]; } #ifdef RE_ENABLE_I18N /* Inline functions for re_string. */ static inline int internal_function __attribute ((pure)) re_string_char_size_at (const re_string_t *pstr, int idx) { int byte_idx; if (pstr->mb_cur_max == 1) return 1; for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) if (pstr->wcs[idx + byte_idx] != WEOF) break; return byte_idx; } static inline wint_t internal_function __attribute ((pure)) re_string_wchar_at (const re_string_t *pstr, int idx) { if (pstr->mb_cur_max == 1) return (wint_t) pstr->mbs[idx]; return (wint_t) pstr->wcs[idx]; } static int internal_function __attribute ((pure)) re_string_elem_size_at (const re_string_t *pstr, int idx) { # ifdef _LIBC const unsigned char *p, *extra; const int32_t *table, *indirect; int32_t tmp; # include uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules != 0) { table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); p = pstr->mbs + idx; tmp = findidx (&p); return p - pstr->mbs - idx; } else # endif /* _LIBC */ return 1; } #endif /* RE_ENABLE_I18N */ #endif /* _REGEX_INTERNAL_H */ kbuild-3686/src/oldsed/lib/obstack.c0000664000175000017500000004153315053010105017311 0ustar locutuslocutus/* obstack.c - subroutines used implicitly by object stack macros -*- C -*- Copyright (C) 1988,89,90,91,92,93,94,96,97 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include "obstack.h" /* NOTE BEFORE MODIFYING THIS FILE: This version number must be incremented whenever callers compiled using an old obstack.h can no longer properly call the functions in this obstack.c. */ #define OBSTACK_INTERFACE_VERSION 1 /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself, and the installed library supports the same library interface we do. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #include /* Random thing to get __GNU_LIBRARY__. */ #if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 #include #if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE #if defined (__STDC__) && __STDC__ #define POINTER void * #else #define POINTER char * #endif /* Determine default alignment. */ struct fooalign {char x; double d;}; #define DEFAULT_ALIGNMENT \ ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0)) /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. But in fact it might be less smart and round addresses to as much as DEFAULT_ROUNDING. So we prepare for it to do that. */ union fooround {long x; double d;}; #define DEFAULT_ROUNDING (sizeof (union fooround)) #ifdef original_glibc_code /**//* When we copy a long block of data, this is the unit to do it with. */ /**//* On some machines, copying successive ints does not work; */ /**//* in such a case, redefine COPYING_UNIT to `long' (if that works) */ /**//* or `char' as a last resort. */ /**/#ifndef COPYING_UNIT /**/#define COPYING_UNIT int /**/#endif #endif /* The functions allocating more room by calling `obstack_chunk_alloc' jump to the handler pointed to by `obstack_alloc_failed_handler'. This variable by default points to the internal function `print_and_abort'. */ #if defined (__STDC__) && __STDC__ static void print_and_abort (void); void (*obstack_alloc_failed_handler) (void) = print_and_abort; #else static void print_and_abort (); void (*obstack_alloc_failed_handler) () = print_and_abort; #endif /* Exit value used when `print_and_abort' is used. */ #if defined __GNU_LIBRARY__ || defined HAVE_STDLIB_H #include #endif #ifndef EXIT_FAILURE #define EXIT_FAILURE 1 #endif int obstack_exit_failure = EXIT_FAILURE; /* The non-GNU-C macros copy the obstack into this global variable to avoid multiple evaluation. */ struct obstack *_obstack; /* Define a macro that either calls functions with the traditional malloc/free calling interface, or calls functions with the mmalloc/mfree interface (that adds an extra first argument), based on the state of use_extra_arg. For free, do not use ?:, since some compilers, like the MIPS compilers, do not allow (expr) ? void : void. */ #if defined (__STDC__) && __STDC__ #define CALL_CHUNKFUN(h, size) \ (((h) -> use_extra_arg) \ ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size))) #define CALL_FREEFUN(h, old_chunk) \ do { \ if ((h) -> use_extra_arg) \ (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ else \ (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \ } while (0) #else #define CALL_CHUNKFUN(h, size) \ (((h) -> use_extra_arg) \ ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ : (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size))) #define CALL_FREEFUN(h, old_chunk) \ do { \ if ((h) -> use_extra_arg) \ (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ else \ (*(void (*) ()) (h)->freefun) ((old_chunk)); \ } while (0) #endif /* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). Objects start on multiples of ALIGNMENT (0 means use default). CHUNKFUN is the function to use to allocate chunks, and FREEFUN the function to free them. Return nonzero if successful, zero if out of memory. To recover from an out of memory error, free up some memory, then call this again. */ int _obstack_begin (h, size, alignment, chunkfun, freefun) struct obstack *h; int size; int alignment; #if defined (__STDC__) && __STDC__ POINTER (*chunkfun) (long); void (*freefun) (void *); #else POINTER (*chunkfun) (); void (*freefun) (); #endif { register struct _obstack_chunk *chunk; /* points to new chunk */ if (alignment == 0) alignment = DEFAULT_ALIGNMENT; if (size == 0) /* Default size is what GNU malloc can fit in a 4096-byte block. */ { /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. Use the values for range checking, because if range checking is off, the extra bytes won't be missed terribly, but if range checking is on and we used a larger request, a whole extra 4096 bytes would be allocated. These number are irrelevant to the new GNU malloc. I suspect it is less sensitive to the size of the request. */ int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + 4 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)); size = 4096 - extra; } #if defined (__STDC__) && __STDC__ h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; #else h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; h->freefun = freefun; #endif h->chunk_size = size; h->alignment_mask = alignment - 1; h->use_extra_arg = 0; chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); if (!chunk) (*obstack_alloc_failed_handler) (); h->next_free = h->object_base = chunk->contents; h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size; chunk->prev = 0; /* The initial chunk now contains no empty object. */ h->maybe_empty_object = 0; h->alloc_failed = 0; return 1; } int _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg) struct obstack *h; int size; int alignment; #if defined (__STDC__) && __STDC__ POINTER (*chunkfun) (POINTER, long); void (*freefun) (POINTER, POINTER); #else POINTER (*chunkfun) (); void (*freefun) (); #endif POINTER arg; { register struct _obstack_chunk *chunk; /* points to new chunk */ if (alignment == 0) alignment = DEFAULT_ALIGNMENT; if (size == 0) /* Default size is what GNU malloc can fit in a 4096-byte block. */ { /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. Use the values for range checking, because if range checking is off, the extra bytes won't be missed terribly, but if range checking is on and we used a larger request, a whole extra 4096 bytes would be allocated. These number are irrelevant to the new GNU malloc. I suspect it is less sensitive to the size of the request. */ int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + 4 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)); size = 4096 - extra; } #if defined(__STDC__) && __STDC__ h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; #else h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; h->freefun = freefun; #endif h->chunk_size = size; h->alignment_mask = alignment - 1; h->extra_arg = arg; h->use_extra_arg = 1; chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); if (!chunk) (*obstack_alloc_failed_handler) (); h->next_free = h->object_base = chunk->contents; h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size; chunk->prev = 0; /* The initial chunk now contains no empty object. */ h->maybe_empty_object = 0; h->alloc_failed = 0; return 1; } /* Allocate a new current chunk for the obstack *H on the assumption that LENGTH bytes need to be added to the current object, or a new object of length LENGTH allocated. Copies any partial object from the end of the old chunk to the beginning of the new one. */ void _obstack_newchunk (h, length) struct obstack *h; int length; { register struct _obstack_chunk *old_chunk = h->chunk; register struct _obstack_chunk *new_chunk; register long new_size; register int obj_size = h->next_free - h->object_base; /* Compute size for new chunk. */ new_size = (obj_size + length) + (obj_size >> 3) + 100; if (new_size < h->chunk_size) new_size = h->chunk_size; /* Allocate and initialize the new chunk. */ new_chunk = CALL_CHUNKFUN (h, new_size); if (!new_chunk) (*obstack_alloc_failed_handler) (); h->chunk = new_chunk; new_chunk->prev = old_chunk; new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; _obstack_memcpy(new_chunk->contents, h->object_base, obj_size); /* If the object just copied was the only data in OLD_CHUNK, */ /* free that chunk and remove it from the chain. */ /* But not if that chunk might contain an empty object. */ if (h->object_base == old_chunk->contents && ! h->maybe_empty_object) { new_chunk->prev = old_chunk->prev; CALL_FREEFUN (h, old_chunk); } h->object_base = new_chunk->contents; h->next_free = h->object_base + obj_size; /* The new chunk certainly contains no empty object yet. */ h->maybe_empty_object = 0; } /* Return nonzero if object OBJ has been allocated from obstack H. This is here for debugging. If you use it in a program, you are probably losing. */ #if defined (__STDC__) && __STDC__ /* Suppress -Wmissing-prototypes warning. We don't want to declare this in obstack.h because it is just for debugging. */ int _obstack_allocated_p (struct obstack *h, POINTER obj); #endif int _obstack_allocated_p (h, obj) struct obstack *h; POINTER obj; { register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ register struct _obstack_chunk *plp; /* point to previous chunk if any */ lp = (h)->chunk; /* We use >= rather than > since the object cannot be exactly at the beginning of the chunk but might be an empty object exactly at the end of an adjacent chunk. */ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) { plp = lp->prev; lp = plp; } return lp != 0; } /* Free objects in obstack H, including OBJ and everything allocate more recently than OBJ. If OBJ is zero, free everything in H. */ #undef obstack_free /* This function has two names with identical definitions. This is the first one, called from non-ANSI code. */ void _obstack_free (h, obj) struct obstack *h; POINTER obj; { register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ register struct _obstack_chunk *plp; /* point to previous chunk if any */ lp = h->chunk; /* We use >= because there cannot be an object at the beginning of a chunk. But there can be an empty object at that address at the end of another chunk. */ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) { plp = lp->prev; CALL_FREEFUN (h, lp); lp = plp; /* If we switch chunks, we can't tell whether the new current chunk contains an empty object, so assume that it may. */ h->maybe_empty_object = 1; } if (lp) { h->object_base = h->next_free = (char *) (obj); h->chunk_limit = lp->limit; h->chunk = lp; } else if (obj != 0) /* obj is not in any of the chunks! */ abort (); } /* This function is used from ANSI code. */ void obstack_free (h, obj) struct obstack *h; POINTER obj; { register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ register struct _obstack_chunk *plp; /* point to previous chunk if any */ lp = h->chunk; /* We use >= because there cannot be an object at the beginning of a chunk. But there can be an empty object at that address at the end of another chunk. */ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) { plp = lp->prev; CALL_FREEFUN (h, lp); lp = plp; /* If we switch chunks, we can't tell whether the new current chunk contains an empty object, so assume that it may. */ h->maybe_empty_object = 1; } if (lp) { h->object_base = h->next_free = (char *) (obj); h->chunk_limit = lp->limit; h->chunk = lp; } else if (obj != 0) /* obj is not in any of the chunks! */ abort (); } int _obstack_memory_used (h) struct obstack *h; { register struct _obstack_chunk* lp; register int nbytes = 0; for (lp = h->chunk; lp != 0; lp = lp->prev) { nbytes += lp->limit - (char *) lp; } return nbytes; } /* Define the error handler. */ #ifndef _ # ifdef HAVE_LIBINTL_H # include # ifndef _ # define _(Str) gettext (Str) # endif # else # define _(Str) (Str) # endif #endif static void print_and_abort () { fputs (_("memory exhausted\n"), stderr); exit (obstack_exit_failure); } #if 0 /* These are now turned off because the applications do not use it and it uses bcopy via obstack_grow, which causes trouble on sysV. */ /* Now define the functional versions of the obstack macros. Define them to simply use the corresponding macros to do the job. */ #if defined (__STDC__) && __STDC__ /* These function definitions do not work with non-ANSI preprocessors; they won't pass through the macro names in parentheses. */ /* The function names appear in parentheses in order to prevent the macro-definitions of the names from being expanded there. */ POINTER (obstack_base) (obstack) struct obstack *obstack; { return obstack_base (obstack); } POINTER (obstack_next_free) (obstack) struct obstack *obstack; { return obstack_next_free (obstack); } int (obstack_object_size) (obstack) struct obstack *obstack; { return obstack_object_size (obstack); } int (obstack_room) (obstack) struct obstack *obstack; { return obstack_room (obstack); } int (obstack_make_room) (obstack, length) struct obstack *obstack; int length; { return obstack_make_room (obstack, length); } void (obstack_grow) (obstack, pointer, length) struct obstack *obstack; POINTER pointer; int length; { obstack_grow (obstack, pointer, length); } void (obstack_grow0) (obstack, pointer, length) struct obstack *obstack; POINTER pointer; int length; { obstack_grow0 (obstack, pointer, length); } void (obstack_1grow) (obstack, character) struct obstack *obstack; int character; { obstack_1grow (obstack, character); } void (obstack_blank) (obstack, length) struct obstack *obstack; int length; { obstack_blank (obstack, length); } void (obstack_1grow_fast) (obstack, character) struct obstack *obstack; int character; { obstack_1grow_fast (obstack, character); } void (obstack_blank_fast) (obstack, length) struct obstack *obstack; int length; { obstack_blank_fast (obstack, length); } POINTER (obstack_finish) (obstack) struct obstack *obstack; { return obstack_finish (obstack); } POINTER (obstack_alloc) (obstack, length) struct obstack *obstack; int length; { return obstack_alloc (obstack, length); } POINTER (obstack_copy) (obstack, pointer, length) struct obstack *obstack; POINTER pointer; int length; { return obstack_copy (obstack, pointer, length); } POINTER (obstack_copy0) (obstack, pointer, length) struct obstack *obstack; POINTER pointer; int length; { return obstack_copy0 (obstack, pointer, length); } #endif /* __STDC__ */ #endif /* 0 */ #endif /* !ELIDE_CODE */ kbuild-3686/src/oldsed/lib/memchr.c0000664000175000017500000001405515053010105017135 0ustar locutuslocutus/* Copyright (C) 1991, 1993, 1996, 1997 Free Software Foundation, Inc. Based on strlen implementation by Torbjorn Granlund (tege@sics.se), with help from Dan Sahlin (dan@sics.se) and commentary by Jim Blandy (jimb@ai.mit.edu); adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), and implemented by Roland McGrath (roland@ai.mit.edu). NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. 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, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif #undef __ptr_t #if defined (__cplusplus) || (defined (__STDC__) && __STDC__) # define __ptr_t void * #else /* Not C++ or ANSI C. */ # define __ptr_t char * #endif /* C++ or ANSI C. */ #if defined (_LIBC) # include #endif #if defined (HAVE_LIMITS_H) || defined (_LIBC) # include #endif #define LONG_MAX_32_BITS 2147483647 #ifndef LONG_MAX #define LONG_MAX LONG_MAX_32_BITS #endif #include #undef memchr /* Search no more than N bytes of S for C. */ __ptr_t memchr (s, c, n) const __ptr_t s; int c; size_t n; { const unsigned char *char_ptr; const unsigned long int *longword_ptr; unsigned long int longword, magic_bits, charmask; c = (unsigned char) c; /* Handle the first few characters by reading one character at a time. Do this until CHAR_PTR is aligned on a longword boundary. */ for (char_ptr = (const unsigned char *) s; n > 0 && ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0; --n, ++char_ptr) if (*char_ptr == c) return (__ptr_t) char_ptr; /* All these elucidatory comments refer to 4-byte longwords, but the theory applies equally well to 8-byte longwords. */ longword_ptr = (unsigned long int *) char_ptr; /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits the "holes." Note that there is a hole just to the left of each byte, with an extra at the end: bits: 01111110 11111110 11111110 11111111 bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD The 1-bits make sure that carries propagate to the next 0-bit. The 0-bits provide holes for carries to fall into. */ if (sizeof (longword) != 4 && sizeof (longword) != 8) abort (); #if LONG_MAX <= LONG_MAX_32_BITS magic_bits = 0x7efefeff; #else magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff; #endif /* Set up a longword, each of whose bytes is C. */ charmask = c | (c << 8); charmask |= charmask << 16; #if LONG_MAX > LONG_MAX_32_BITS charmask |= charmask << 32; #endif /* Instead of the traditional loop which tests each character, we will test a longword at a time. The tricky part is testing if *any of the four* bytes in the longword in question are zero. */ while (n >= sizeof (longword)) { /* We tentatively exit the loop if adding MAGIC_BITS to LONGWORD fails to change any of the hole bits of LONGWORD. 1) Is this safe? Will it catch all the zero bytes? Suppose there is a byte with all zeros. Any carry bits propagating from its left will fall into the hole at its least significant bit and stop. Since there will be no carry from its most significant bit, the LSB of the byte to the left will be unchanged, and the zero will be detected. 2) Is this worthwhile? Will it ignore everything except zero bytes? Suppose every byte of LONGWORD has a bit set somewhere. There will be a carry into bit 8. If bit 8 is set, this will carry into bit 16. If bit 8 is clear, one of bits 9-15 must be set, so there will be a carry into bit 16. Similarly, there will be a carry into bit 24. If one of bits 24-30 is set, there will be a carry into bit 31, so all of the hole bits will be changed. The one misfire occurs when bits 24-30 are clear and bit 31 is set; in this case, the hole at bit 31 is not changed. If we had access to the processor carry flag, we could close this loophole by putting the fourth hole at bit 32! So it ignores everything except 128's, when they're aligned properly. 3) But wait! Aren't we looking for C, not zero? Good point. So what we do is XOR LONGWORD with a longword, each of whose bytes is C. This turns each byte that is C into a zero. */ longword = *longword_ptr++ ^ charmask; /* Add MAGIC_BITS to LONGWORD. */ if ((((longword + magic_bits) /* Set those bits that were unchanged by the addition. */ ^ ~longword) /* Look at only the hole bits. If any of the hole bits are unchanged, most likely one of the bytes was a zero. */ & ~magic_bits) != 0) { /* Which of the bytes was C? If none of them were, it was a misfire; continue the search. */ const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); if (cp[0] == c) return (__ptr_t) cp; if (cp[1] == c) return (__ptr_t) &cp[1]; if (cp[2] == c) return (__ptr_t) &cp[2]; if (cp[3] == c) return (__ptr_t) &cp[3]; #if LONG_MAX > 2147483647 if (cp[4] == c) return (__ptr_t) &cp[4]; if (cp[5] == c) return (__ptr_t) &cp[5]; if (cp[6] == c) return (__ptr_t) &cp[6]; if (cp[7] == c) return (__ptr_t) &cp[7]; #endif } n -= sizeof (longword); } char_ptr = (const unsigned char *) longword_ptr; while (n-- > 0) { if (*char_ptr == c) return (__ptr_t) char_ptr; else ++char_ptr; } return 0; } kbuild-3686/src/oldsed/lib/obstack.h0000664000175000017500000005522415053010104017317 0ustar locutuslocutus/* obstack.h - object stack macros Copyright (C) 1988,89,90,91,92,93,94,96,97,98,99 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Summary: All the apparent functions defined here are macros. The idea is that you would use these pre-tested macros to solve a very specific set of problems, and they would run fast. Caution: no side-effects in arguments please!! They may be evaluated MANY times!! These macros operate a stack of objects. Each object starts life small, and may grow to maturity. (Consider building a word syllable by syllable.) An object can move while it is growing. Once it has been "finished" it never changes address again. So the "top of the stack" is typically an immature growing object, while the rest of the stack is of mature, fixed size and fixed address objects. These routines grab large chunks of memory, using a function you supply, called `obstack_chunk_alloc'. On occasion, they free chunks, by calling `obstack_chunk_free'. You must define them and declare them before using any obstack macros. Each independent stack is represented by a `struct obstack'. Each of the obstack macros expects a pointer to such a structure as the first argument. One motivation for this package is the problem of growing char strings in symbol tables. Unless you are "fascist pig with a read-only mind" --Gosper's immortal quote from HAKMEM item 154, out of context--you would not like to put any arbitrary upper limit on the length of your symbols. In practice this often means you will build many short symbols and a few long symbols. At the time you are reading a symbol you don't know how long it is. One traditional method is to read a symbol into a buffer, realloc()ating the buffer every time you try to read a symbol that is longer than the buffer. This is beaut, but you still will want to copy the symbol from the buffer to a more permanent symbol-table entry say about half the time. With obstacks, you can work differently. Use one obstack for all symbol names. As you read a symbol, grow the name in the obstack gradually. When the name is complete, finalize it. Then, if the symbol exists already, free the newly read name. The way we do this is to take a large chunk, allocating memory from low addresses. When you want to build a symbol in the chunk you just add chars above the current "high water mark" in the chunk. When you have finished adding chars, because you got to the end of the symbol, you know how long the chars are, and you can create a new object. Mostly the chars will not burst over the highest address of the chunk, because you would typically expect a chunk to be (say) 100 times as long as an average object. In case that isn't clear, when we have enough chars to make up the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed) so we just point to it where it lies. No moving of chars is needed and this is the second win: potentially long strings need never be explicitly shuffled. Once an object is formed, it does not change its address during its lifetime. When the chars burst over a chunk boundary, we allocate a larger chunk, and then copy the partly formed object from the end of the old chunk to the beginning of the new larger chunk. We then carry on accreting characters to the end of the object as we normally would. A special macro is provided to add a single char at a time to a growing object. This allows the use of register variables, which break the ordinary 'growth' macro. Summary: We allocate large chunks. We carve out one object at a time from the current chunk. Once carved, an object never moves. We are free to append data of any size to the currently growing object. Exactly one object is growing in an obstack at any one time. You can run one obstack per control block. You may have as many control blocks as you dare. Because of the way we do it, you can `unwind' an obstack back to a previous state. (You may remove objects much as you would with a stack.) */ /* Don't do the contents of this file more than once. */ #ifndef _OBSTACK_H #define _OBSTACK_H 1 #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef __cplusplus extern "C" { #endif /* We use subtraction of (char *) 0 instead of casting to int because on word-addressable machines a simple cast to int may ignore the byte-within-word field of the pointer. */ #ifndef __PTR_TO_INT # define __PTR_TO_INT(P) ((P) - (char *) 0) #endif #ifndef __INT_TO_PTR # define __INT_TO_PTR(P) ((P) + (char *) 0) #endif /* We need the type of the resulting object. If __PTRDIFF_TYPE__ is defined, as with GNU C, use that; that way we don't pollute the namespace with 's symbols. Otherwise, if is available, include it and use ptrdiff_t. In traditional C, long is the best that we can do. */ #ifdef __PTRDIFF_TYPE__ # define PTR_INT_TYPE __PTRDIFF_TYPE__ #else # ifdef HAVE_STDDEF_H # include # define PTR_INT_TYPE ptrdiff_t # else # define PTR_INT_TYPE long # endif #endif #if defined _LIBC || defined HAVE_STRING_H # include # define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N)) #else # ifdef memcpy # define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N)) # else # define _obstack_memcpy(To, From, N) bcopy ((From), (To), (N)) # endif #endif struct _obstack_chunk /* Lives at front of each chunk. */ { char *limit; /* 1 past end of this chunk */ struct _obstack_chunk *prev; /* address of prior chunk or NULL */ char contents[4]; /* objects begin here */ }; struct obstack /* control current object in current chunk */ { long chunk_size; /* preferred size to allocate chunks in */ struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */ char *object_base; /* address of object we are building */ char *next_free; /* where to add next char to current object */ char *chunk_limit; /* address of char after current chunk */ PTR_INT_TYPE temp; /* Temporary for some macros. */ int alignment_mask; /* Mask of alignment for each object. */ #if defined __STDC__ && __STDC__ /* These prototypes vary based on `use_extra_arg', and we use casts to the prototypeless function type in all assignments, but having prototypes here quiets -Wstrict-prototypes. */ struct _obstack_chunk *(*chunkfun) (void *, long); void (*freefun) (void *, struct _obstack_chunk *); void *extra_arg; /* first arg for chunk alloc/dealloc funcs */ #else struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */ void (*freefun) (); /* User's function to free a chunk. */ char *extra_arg; /* first arg for chunk alloc/dealloc funcs */ #endif unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */ unsigned maybe_empty_object:1;/* There is a possibility that the current chunk contains a zero-length object. This prevents freeing the chunk if we allocate a bigger chunk to replace it. */ unsigned alloc_failed:1; /* No longer used, as we now call the failed handler on error, but retained for binary compatibility. */ }; /* Declare the external functions we use; they are in obstack.c. */ #if defined __STDC__ && __STDC__ extern void _obstack_newchunk (struct obstack *, int); extern void _obstack_free (struct obstack *, void *); extern int _obstack_begin (struct obstack *, int, int, void *(*) (long), void (*) (void *)); extern int _obstack_begin_1 (struct obstack *, int, int, void *(*) (void *, long), void (*) (void *, void *), void *); extern int _obstack_memory_used (struct obstack *); #else extern void _obstack_newchunk (); extern void _obstack_free (); extern int _obstack_begin (); extern int _obstack_begin_1 (); extern int _obstack_memory_used (); #endif #if defined __STDC__ && __STDC__ /* Do the function-declarations after the structs but before defining the macros. */ void obstack_init (struct obstack *obstack); void * obstack_alloc (struct obstack *obstack, int size); void * obstack_copy (struct obstack *obstack, const void *address, int size); void * obstack_copy0 (struct obstack *obstack, const void *address, int size); void obstack_free (struct obstack *obstack, void *block); void obstack_blank (struct obstack *obstack, int size); void obstack_grow (struct obstack *obstack, const void *data, int size); void obstack_grow0 (struct obstack *obstack, const void *data, int size); void obstack_1grow (struct obstack *obstack, int data_char); void obstack_ptr_grow (struct obstack *obstack, const void *data); void obstack_int_grow (struct obstack *obstack, int data); void * obstack_finish (struct obstack *obstack); int obstack_object_size (struct obstack *obstack); int obstack_room (struct obstack *obstack); void obstack_make_room (struct obstack *obstack, int size); void obstack_1grow_fast (struct obstack *obstack, int data_char); void obstack_ptr_grow_fast (struct obstack *obstack, const void *data); void obstack_int_grow_fast (struct obstack *obstack, int data); void obstack_blank_fast (struct obstack *obstack, int size); void * obstack_base (struct obstack *obstack); void * obstack_next_free (struct obstack *obstack); int obstack_alignment_mask (struct obstack *obstack); int obstack_chunk_size (struct obstack *obstack); int obstack_memory_used (struct obstack *obstack); #endif /* __STDC__ */ /* Non-ANSI C cannot really support alternative functions for these macros, so we do not declare them. */ /* Error handler called when `obstack_chunk_alloc' failed to allocate more memory. This can be set to a user defined function which should either abort gracefully or use longjump - but shouldn't return. The default action is to print a message and abort. */ #if defined __STDC__ && __STDC__ extern void (*obstack_alloc_failed_handler) (void); #else extern void (*obstack_alloc_failed_handler) (); #endif /* Exit value used when `print_and_abort' is used. */ extern int obstack_exit_failure; /* Pointer to beginning of object being allocated or to be allocated next. Note that this might not be the final address of the object because a new chunk might be needed to hold the final size. */ #define obstack_base(h) ((h)->object_base) /* Size for allocating ordinary chunks. */ #define obstack_chunk_size(h) ((h)->chunk_size) /* Pointer to next byte not yet allocated in current chunk. */ #define obstack_next_free(h) ((h)->next_free) /* Mask specifying low bits that should be clear in address of an object. */ #define obstack_alignment_mask(h) ((h)->alignment_mask) /* To prevent prototype warnings provide complete argument list in standard C version. */ #if defined __STDC__ && __STDC__ # define obstack_init(h) \ _obstack_begin ((h), 0, 0, \ (void *(*) (long)) obstack_chunk_alloc, \ (void (*) (void *)) obstack_chunk_free) # define obstack_begin(h, size) \ _obstack_begin ((h), (size), 0, \ (void *(*) (long)) obstack_chunk_alloc, \ (void (*) (void *)) obstack_chunk_free) # define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ _obstack_begin ((h), (size), (alignment), \ (void *(*) (long)) (chunkfun), \ (void (*) (void *)) (freefun)) # define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ _obstack_begin_1 ((h), (size), (alignment), \ (void *(*) (void *, long)) (chunkfun), \ (void (*) (void *, void *)) (freefun), (arg)) # define obstack_chunkfun(h, newchunkfun) \ ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun)) # define obstack_freefun(h, newfreefun) \ ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun)) #else # define obstack_init(h) \ _obstack_begin ((h), 0, 0, \ (void *(*) ()) obstack_chunk_alloc, \ (void (*) ()) obstack_chunk_free) # define obstack_begin(h, size) \ _obstack_begin ((h), (size), 0, \ (void *(*) ()) obstack_chunk_alloc, \ (void (*) ()) obstack_chunk_free) # define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ _obstack_begin ((h), (size), (alignment), \ (void *(*) ()) (chunkfun), \ (void (*) ()) (freefun)) # define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ _obstack_begin_1 ((h), (size), (alignment), \ (void *(*) ()) (chunkfun), \ (void (*) ()) (freefun), (arg)) # define obstack_chunkfun(h, newchunkfun) \ ((h) -> chunkfun = (struct _obstack_chunk *(*)()) (newchunkfun)) # define obstack_freefun(h, newfreefun) \ ((h) -> freefun = (void (*)()) (newfreefun)) #endif #define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar) #define obstack_blank_fast(h,n) ((h)->next_free += (n)) #define obstack_memory_used(h) _obstack_memory_used (h) #if defined __GNUC__ && defined __STDC__ && __STDC__ /* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and does not implement __extension__. But that compiler doesn't define __GNUC_MINOR__. */ # if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__) # define __extension__ # endif /* For GNU C, if not -traditional, we can define these macros to compute all args only once without using a global variable. Also, we can avoid using the `temp' slot, to make faster code. */ # define obstack_object_size(OBSTACK) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ (unsigned) (__o->next_free - __o->object_base); }) # define obstack_room(OBSTACK) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ (unsigned) (__o->chunk_limit - __o->next_free); }) # define obstack_make_room(OBSTACK,length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ if (__o->chunk_limit - __o->next_free < __len) \ _obstack_newchunk (__o, __len); \ (void) 0; }) # define obstack_empty_p(OBSTACK) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ (__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); }) # define obstack_grow(OBSTACK,where,length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ if (__o->next_free + __len > __o->chunk_limit) \ _obstack_newchunk (__o, __len); \ _obstack_memcpy (__o->next_free, (where), __len); \ __o->next_free += __len; \ (void) 0; }) # define obstack_grow0(OBSTACK,where,length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ if (__o->next_free + __len + 1 > __o->chunk_limit) \ _obstack_newchunk (__o, __len + 1); \ _obstack_memcpy (__o->next_free, (where), __len); \ __o->next_free += __len; \ *(__o->next_free)++ = 0; \ (void) 0; }) # define obstack_1grow(OBSTACK,datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ if (__o->next_free + 1 > __o->chunk_limit) \ _obstack_newchunk (__o, 1); \ *(__o->next_free)++ = (datum); \ (void) 0; }) /* These assume that the obstack alignment is good enough for pointers or ints, and that the data added so far to the current object shares that much alignment. */ # define obstack_ptr_grow(OBSTACK,datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ if (__o->next_free + sizeof (void *) > __o->chunk_limit) \ _obstack_newchunk (__o, sizeof (void *)); \ ((*((void **)__o->next_free) = (datum)), (__o->next_free += sizeof (void *))); \ (void) 0; }) # define obstack_int_grow(OBSTACK,datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ if (__o->next_free + sizeof (int) > __o->chunk_limit) \ _obstack_newchunk (__o, sizeof (int)); \ ((*((int *)__o->next_free) = (datum)), (__o->next_free += sizeof (int ))); \ (void) 0; }) # define obstack_ptr_grow_fast(h,aptr) \ (((*((void **) (h)->next_free) = (aptr)), ( (h)->next_free += sizeof (void *)))) # define obstack_int_grow_fast(h,aint) \ (((*((int *) (h)->next_free) = (aint)), ( (h)->next_free += sizeof (int )))) # define obstack_blank(OBSTACK,length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ if (__o->chunk_limit - __o->next_free < __len) \ _obstack_newchunk (__o, __len); \ __o->next_free += __len; \ (void) 0; }) # define obstack_alloc(OBSTACK,length) \ __extension__ \ ({ struct obstack *__h = (OBSTACK); \ obstack_blank (__h, (length)); \ obstack_finish (__h); }) # define obstack_copy(OBSTACK,where,length) \ __extension__ \ ({ struct obstack *__h = (OBSTACK); \ obstack_grow (__h, (where), (length)); \ obstack_finish (__h); }) # define obstack_copy0(OBSTACK,where,length) \ __extension__ \ ({ struct obstack *__h = (OBSTACK); \ obstack_grow0 (__h, (where), (length)); \ obstack_finish (__h); }) /* The local variable is named __o1 to avoid a name conflict when obstack_blank is called. */ # define obstack_finish(OBSTACK) \ __extension__ \ ({ struct obstack *__o1 = (OBSTACK); \ void *value; \ value = (void *) __o1->object_base; \ if (__o1->next_free == value) \ __o1->maybe_empty_object = 1; \ __o1->next_free \ = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\ & ~ (__o1->alignment_mask)); \ if (__o1->next_free - (char *)__o1->chunk \ > __o1->chunk_limit - (char *)__o1->chunk) \ __o1->next_free = __o1->chunk_limit; \ __o1->object_base = __o1->next_free; \ value; }) # define obstack_free(OBSTACK, OBJ) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ void *__obj = (OBJ); \ if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \ __o->next_free = __o->object_base = (char *)__obj; \ else (obstack_free) (__o, __obj); }) #else /* not __GNUC__ or not __STDC__ */ # define obstack_object_size(h) \ (unsigned) ((h)->next_free - (h)->object_base) # define obstack_room(h) \ (unsigned) ((h)->chunk_limit - (h)->next_free) # define obstack_empty_p(h) \ ((h)->chunk->prev == 0 && (h)->next_free - (h)->chunk->contents == 0) /* Note that the call to _obstack_newchunk is enclosed in (..., 0) so that we can avoid having void expressions in the arms of the conditional expression. Casting the third operand to void was tried before, but some compilers won't accept it. */ # define obstack_make_room(h,length) \ ( (h)->temp = (length), \ (((h)->next_free + (h)->temp > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0)) # define obstack_grow(h,where,length) \ ( (h)->temp = (length), \ (((h)->next_free + (h)->temp > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ _obstack_memcpy ((h)->next_free, (where), (h)->temp), \ (h)->next_free += (h)->temp) # define obstack_grow0(h,where,length) \ ( (h)->temp = (length), \ (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \ _obstack_memcpy ((h)->next_free, (where), (h)->temp), \ (h)->next_free += (h)->temp, \ *((h)->next_free)++ = 0) # define obstack_1grow(h,datum) \ ( (((h)->next_free + 1 > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), 1), 0) : 0), \ (*((h)->next_free)++ = (datum))) # define obstack_ptr_grow(h,datum) \ ( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ (*((const char **) (((h)->next_free+=sizeof(char *))-sizeof(char *))) = (datum))) # define obstack_int_grow(h,datum) \ ( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ (*((int *) (((h)->next_free+=sizeof(int))-sizeof(int))) = (datum))) # define obstack_ptr_grow_fast(h,aptr) \ (((*((const char **) (h)->next_free) = (aptr)), ( (h)->next_free += sizeof (const char *)))) # define obstack_int_grow_fast(h,aint) \ (((*((int *) (h)->next_free) = (aint)), ( (h)->next_free += sizeof (int )))) # define obstack_blank(h,length) \ ( (h)->temp = (length), \ (((h)->chunk_limit - (h)->next_free < (h)->temp) \ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ ((h)->next_free += (h)->temp)) # define obstack_alloc(h,length) \ (obstack_blank ((h), (length)), obstack_finish ((h))) # define obstack_copy(h,where,length) \ (obstack_grow ((h), (where), (length)), obstack_finish ((h))) # define obstack_copy0(h,where,length) \ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) # define obstack_finish(h) \ ( ((h)->next_free == (h)->object_base \ ? (((h)->maybe_empty_object = 1), 0) \ : 0), \ (h)->temp = __PTR_TO_INT ((h)->object_base), \ (h)->next_free \ = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \ & ~ ((h)->alignment_mask)), \ (((h)->next_free - (char *) (h)->chunk \ > (h)->chunk_limit - (char *) (h)->chunk) \ ? ((h)->next_free = (h)->chunk_limit) : 0), \ (h)->object_base = (h)->next_free, \ __INT_TO_PTR ((h)->temp)) # if defined __STDC__ && __STDC__ # define obstack_free(h,obj) \ ( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \ (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ ? (int) ((h)->next_free = (h)->object_base \ = (h)->temp + (char *) (h)->chunk) \ : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0))) # else # define obstack_free(h,obj) \ ( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \ (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ ? (int) ((h)->next_free = (h)->object_base \ = (h)->temp + (char *) (h)->chunk) \ : (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0))) # endif #endif /* not __GNUC__ or not __STDC__ */ #ifdef __cplusplus } /* C++ */ #endif #endif /* obstack.h */ kbuild-3686/src/oldsed/lib/regex_.h0000664000175000017500000005202015053010105017132 0ustar locutuslocutus/* Definitions for data structures and routines for the regular expression library. Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _REGEX_H #define _REGEX_H 1 #include /* Allow the use in C++ code. */ #ifdef __cplusplus extern "C" { #endif /* POSIX says that must be included (by the caller) before . */ #if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS /* VMS doesn't have `size_t' in , even though POSIX says it should be there. */ # include #endif /* The following two types have to be signed and unsigned integer type wide enough to hold a value of a pointer. For most ANSI compilers ptrdiff_t and size_t should be likely OK. Still size of these two types is 2 for Microsoft C. Ugh... */ typedef long int s_reg_t; typedef unsigned long int active_reg_t; /* The following bits are used to determine the regexp syntax we recognize. The set/not-set meanings are chosen so that Emacs syntax remains the value 0. The bits are given in alphabetical order, and the definitions shifted by one from the previous bit; thus, when we add or remove a bit, only one other definition need change. */ typedef unsigned long int reg_syntax_t; /* If this bit is not set, then \ inside a bracket expression is literal. If set, then such a \ quotes the following character. */ #define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) /* If this bit is not set, then + and ? are operators, and \+ and \? are literals. If set, then \+ and \? are operators and + and ? are literals. */ #define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) /* If this bit is set, then character classes are supported. They are: [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. If not set, then character classes are not supported. */ #define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) /* If this bit is set, then ^ and $ are always anchors (outside bracket expressions, of course). If this bit is not set, then it depends: ^ is an anchor if it is at the beginning of a regular expression or after an open-group or an alternation operator; $ is an anchor if it is at the end of a regular expression, or before a close-group or an alternation operator. This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because POSIX draft 11.2 says that * etc. in leading positions is undefined. We already implemented a previous draft which made those constructs invalid, though, so we haven't changed the code back. */ #define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) /* If this bit is set, then special characters are always special regardless of where they are in the pattern. If this bit is not set, then special characters are special only in some contexts; otherwise they are ordinary. Specifically, * + ? and intervals are only special when not after the beginning, open-group, or alternation operator. */ #define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) /* If this bit is set, then *, +, ?, and { cannot be first in an re or immediately after an alternation or begin-group operator. */ #define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) /* If this bit is set, then . matches newline. If not set, then it doesn't. */ #define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) /* If this bit is set, then . doesn't match NUL. If not set, then it does. */ #define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) /* If this bit is set, nonmatching lists [^...] do not match newline. If not set, they do. */ #define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) /* If this bit is set, either \{...\} or {...} defines an interval, depending on RE_NO_BK_BRACES. If not set, \{, \}, {, and } are literals. */ #define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) /* If this bit is set, +, ? and | aren't recognized as operators. If not set, they are. */ #define RE_LIMITED_OPS (RE_INTERVALS << 1) /* If this bit is set, newline is an alternation operator. If not set, newline is literal. */ #define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) /* If this bit is set, then `{...}' defines an interval, and \{ and \} are literals. If not set, then `\{...\}' defines an interval. */ #define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) /* If this bit is set, (...) defines a group, and \( and \) are literals. If not set, \(...\) defines a group, and ( and ) are literals. */ #define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) /* If this bit is set, then \ matches . If not set, then \ is a back-reference. */ #define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) /* If this bit is set, then | is an alternation operator, and \| is literal. If not set, then \| is an alternation operator, and | is literal. */ #define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) /* If this bit is set, then an ending range point collating higher than the starting range point, as in [z-a], is invalid. If not set, then when ending range point collates higher than the starting range point, the range is ignored. */ #define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) /* If this bit is set, then an unmatched ) is ordinary. If not set, then an unmatched ) is invalid. */ #define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) /* If this bit is set, succeed as soon as we match the whole pattern, without further backtracking. */ #define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) /* If this bit is set, do not process the GNU regex operators. If not set, then the GNU regex operators are recognized. */ #define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) /* If this bit is set, turn on internal regex debugging. If not set, and debugging was on, turn it off. This only works if regex.c is compiled -DDEBUG. We define this bit always, so that all that's needed to turn on debugging is to recompile regex.c; the calling code can always have this bit set, and it won't affect anything in the normal case. */ #define RE_DEBUG (RE_NO_GNU_OPS << 1) /* If this bit is set, a syntactically invalid interval is treated as a string of ordinary characters. For example, the ERE 'a{1' is treated as 'a\{1'. */ #define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) /* If this bit is set, then ignore case when matching. If not set, then case is significant. */ #define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) /* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only for ^, because it is difficult to scan the regex backwards to find whether ^ should be special. */ #define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) /* If this bit is set, then \{ cannot be first in an bre or immediately after an alternation or begin-group operator. */ #define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) /* If this bit is set, then no_sub will be set to 1 during re_compile_pattern. */ #define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) /* This global variable defines the particular regexp syntax to use (for some interfaces). When a regexp is compiled, the syntax used is stored in the pattern buffer, so changing this does not affect already-compiled regexps. */ extern reg_syntax_t re_syntax_options; /* Define combinations of the above bits for the standard possibilities. (The [[[ comments delimit what gets put into the Texinfo file, so don't delete them!) */ /* [[[begin syntaxes]]] */ #define RE_SYNTAX_EMACS 0 #define RE_SYNTAX_AWK \ (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) #define RE_SYNTAX_GNU_AWK \ ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \ | RE_CONTEXT_INVALID_OPS )) #define RE_SYNTAX_POSIX_AWK \ (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ | RE_INTERVALS | RE_NO_GNU_OPS) #define RE_SYNTAX_GREP \ (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ | RE_NEWLINE_ALT) #define RE_SYNTAX_EGREP \ (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ | RE_NO_BK_VBAR) #define RE_SYNTAX_POSIX_EGREP \ (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \ | RE_INVALID_INTERVAL_ORD) /* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ #define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC #define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC /* Syntax bits common to both basic and extended POSIX regex syntax. */ #define _RE_SYNTAX_POSIX_COMMON \ (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ | RE_INTERVALS | RE_NO_EMPTY_RANGES) #define RE_SYNTAX_POSIX_BASIC \ (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) /* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this isn't minimal, since other operators, such as \`, aren't disabled. */ #define RE_SYNTAX_POSIX_MINIMAL_BASIC \ (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) #define RE_SYNTAX_POSIX_EXTENDED \ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) /* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is removed and RE_NO_BK_REFS is added. */ #define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) /* [[[end syntaxes]]] */ /* Maximum number of duplicates an interval can allow. Some systems (erroneously) define this in other header files, but we want our value, so remove any previous define. */ #ifdef RE_DUP_MAX # undef RE_DUP_MAX #endif /* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */ #define RE_DUP_MAX (0x7fff) /* POSIX `cflags' bits (i.e., information for `regcomp'). */ /* If this bit is set, then use extended regular expression syntax. If not set, then use basic regular expression syntax. */ #define REG_EXTENDED 1 /* If this bit is set, then ignore case when matching. If not set, then case is significant. */ #define REG_ICASE (REG_EXTENDED << 1) /* If this bit is set, then anchors do not match at newline characters in the string. If not set, then anchors do match at newlines. */ #define REG_NEWLINE (REG_ICASE << 1) /* If this bit is set, then report only success or fail in regexec. If not set, then returns differ between not matching and errors. */ #define REG_NOSUB (REG_NEWLINE << 1) /* POSIX `eflags' bits (i.e., information for regexec). */ /* If this bit is set, then the beginning-of-line operator doesn't match the beginning of the string (presumably because it's not the beginning of a line). If not set, then the beginning-of-line operator does match the beginning of the string. */ #define REG_NOTBOL 1 /* Like REG_NOTBOL, except for the end-of-line. */ #define REG_NOTEOL (1 << 1) /* Use PMATCH[0] to delimit the start and end of the search in the buffer. */ #define REG_STARTEND (1 << 2) /* If any error codes are removed, changed, or added, update the `re_error_msg' table in regex.c. */ typedef enum { #ifdef _XOPEN_SOURCE REG_ENOSYS = -1, /* This will never happen for this implementation. */ #endif REG_NOERROR = 0, /* Success. */ REG_NOMATCH, /* Didn't find a match (for regexec). */ /* POSIX regcomp return error codes. (In the order listed in the standard.) */ REG_BADPAT, /* Invalid pattern. */ REG_ECOLLATE, /* Inalid collating element. */ REG_ECTYPE, /* Invalid character class name. */ REG_EESCAPE, /* Trailing backslash. */ REG_ESUBREG, /* Invalid back reference. */ REG_EBRACK, /* Unmatched left bracket. */ REG_EPAREN, /* Parenthesis imbalance. */ REG_EBRACE, /* Unmatched \{. */ REG_BADBR, /* Invalid contents of \{\}. */ REG_ERANGE, /* Invalid range end. */ REG_ESPACE, /* Ran out of memory. */ REG_BADRPT, /* No preceding re for repetition op. */ /* Error codes we've added. */ REG_EEND, /* Premature end. */ REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ } reg_errcode_t; /* This data structure represents a compiled pattern. Before calling the pattern compiler, the fields `buffer', `allocated', `fastmap', `translate', and `no_sub' can be set. After the pattern has been compiled, the `re_nsub' field is available. All other fields are private to the regex routines. */ #ifndef RE_TRANSLATE_TYPE # define RE_TRANSLATE_TYPE unsigned char * #endif struct re_pattern_buffer { /* Space that holds the compiled pattern. It is declared as `unsigned char *' because its elements are sometimes used as array indexes. */ unsigned char *buffer; /* Number of bytes to which `buffer' points. */ unsigned long int allocated; /* Number of bytes actually used in `buffer'. */ unsigned long int used; /* Syntax setting with which the pattern was compiled. */ reg_syntax_t syntax; /* Pointer to a fastmap, if any, otherwise zero. re_search uses the fastmap, if there is one, to skip over impossible starting points for matches. */ char *fastmap; /* Either a translate table to apply to all characters before comparing them, or zero for no translation. The translation is applied to a pattern when it is compiled and to a string when it is matched. */ RE_TRANSLATE_TYPE translate; /* Number of subexpressions found by the compiler. */ size_t re_nsub; /* Zero if this pattern cannot match the empty string, one else. Well, in truth it's used only in `re_search_2', to see whether or not we should use the fastmap, so we don't set this absolutely perfectly; see `re_compile_fastmap' (the `duplicate' case). */ unsigned can_be_null : 1; /* If REGS_UNALLOCATED, allocate space in the `regs' structure for `max (RE_NREGS, re_nsub + 1)' groups. If REGS_REALLOCATE, reallocate space if necessary. If REGS_FIXED, use what's there. */ #define REGS_UNALLOCATED 0 #define REGS_REALLOCATE 1 #define REGS_FIXED 2 unsigned regs_allocated : 2; /* Set to zero when `regex_compile' compiles a pattern; set to one by `re_compile_fastmap' if it updates the fastmap. */ unsigned fastmap_accurate : 1; /* If set, `re_match_2' does not return information about subexpressions. */ unsigned no_sub : 1; /* If set, a beginning-of-line anchor doesn't match at the beginning of the string. */ unsigned not_bol : 1; /* Similarly for an end-of-line anchor. */ unsigned not_eol : 1; /* If true, an anchor at a newline matches. */ unsigned newline_anchor : 1; }; typedef struct re_pattern_buffer regex_t; /* Type for byte offsets within the string. POSIX mandates this. */ typedef int regoff_t; /* This is the structure we store register match data in. See regex.texinfo for a full description of what registers match. */ struct re_registers { unsigned num_regs; regoff_t *start; regoff_t *end; }; /* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, `re_match_2' returns information about at least this many registers the first time a `regs' structure is passed. */ #ifndef RE_NREGS # define RE_NREGS 30 #endif /* POSIX specification for registers. Aside from the different names than `re_registers', POSIX uses an array of structures, instead of a structure of arrays. */ typedef struct { regoff_t rm_so; /* Byte offset from string's start to substring's start. */ regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ } regmatch_t; /* Declarations for routines. */ /* Sets the current default syntax to SYNTAX, and return the old syntax. You can also simply assign to the `re_syntax_options' variable. */ extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); /* Compile the regular expression PATTERN, with length LENGTH and syntax given by the global `re_syntax_options', into the buffer BUFFER. Return NULL if successful, and an error string if not. */ extern const char *re_compile_pattern (const char *__pattern, size_t __length, struct re_pattern_buffer *__buffer); /* Compile a fastmap for the compiled pattern in BUFFER; used to accelerate searches. Return 0 if successful and -2 if was an internal error. */ extern int re_compile_fastmap (struct re_pattern_buffer *__buffer); /* Search in the string STRING (with length LENGTH) for the pattern compiled into BUFFER. Start searching at position START, for RANGE characters. Return the starting position of the match, -1 for no match, or -2 for an internal error. Also return register information in REGS (if REGS and BUFFER->no_sub are nonzero). */ extern int re_search (struct re_pattern_buffer *__buffer, const char *__string, int __length, int __start, int __range, struct re_registers *__regs); /* Like `re_search', but search in the concatenation of STRING1 and STRING2. Also, stop searching at index START + STOP. */ extern int re_search_2 (struct re_pattern_buffer *__buffer, const char *__string1, int __length1, const char *__string2, int __length2, int __start, int __range, struct re_registers *__regs, int __stop); /* Like `re_search', but return how many characters in STRING the regexp in BUFFER matched, starting at position START. */ extern int re_match (struct re_pattern_buffer *__buffer, const char *__string, int __length, int __start, struct re_registers *__regs); /* Relates to `re_match' as `re_search_2' relates to `re_search'. */ extern int re_match_2 (struct re_pattern_buffer *__buffer, const char *__string1, int __length1, const char *__string2, int __length2, int __start, struct re_registers *__regs, int __stop); /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be allocated with malloc, and must each be at least `NUM_REGS * sizeof (regoff_t)' bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using PATTERN_BUFFER will allocate its own register data, without freeing the old data. */ extern void re_set_registers (struct re_pattern_buffer *__buffer, struct re_registers *__regs, unsigned int __num_regs, regoff_t *__starts, regoff_t *__ends); #if defined _REGEX_RE_COMP || defined _LIBC # ifndef _CRAY /* 4.2 bsd compatibility. */ extern char *re_comp (const char *); extern int re_exec (const char *); # endif #endif /* GCC 2.95 and later have "__restrict"; C99 compilers have "restrict", and "configure" may have defined "restrict". */ #ifndef __restrict # if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) # if defined restrict || 199901L <= __STDC_VERSION__ # define __restrict restrict # else # define __restrict # endif # endif #endif /* gcc 3.1 and up support the [restrict] syntax. */ #ifndef __restrict_arr # if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) # define __restrict_arr __restrict # else # define __restrict_arr # endif #endif /* POSIX compatibility. */ extern int regcomp (regex_t *__restrict __preg, const char *__restrict __pattern, int __cflags); extern int regexec (const regex_t *__restrict __preg, const char *__restrict __string, size_t __nmatch, regmatch_t __pmatch[__restrict_arr], int __eflags); extern size_t regerror (int __errcode, const regex_t *__restrict __preg, char *__restrict __errbuf, size_t __errbuf_size); extern void regfree (regex_t *__preg); #ifdef __cplusplus } #endif /* C++ */ #endif /* regex.h */ kbuild-3686/src/oldsed/lib/memmove.c0000664000175000017500000000365615053010105017334 0ustar locutuslocutus/* Copyright (C) 1998 Free Software Foundation, Inc. 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, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Last ditch effort to support memmove: if user doesn't have memmove or bcopy, we offer this sluggish implementation. */ #include "config.h" #ifndef HAVE_MEMMOVE #include #ifdef HAVE_MEMORY_H # include #endif #ifndef VOID # define VOID void #endif VOID * memmove(dest, src, len) VOID *dest; const VOID *src; size_t len; { #ifdef HAVE_BCOPY bcopy(src, dest, len); #else /*!HAVE_BCOPY*/ char *dp = dest; const char *sp = src; # ifdef HAVE_MEMCPY /* A special-case for non-overlapping regions, on the assumption that there is some hope that the sytem's memcpy() implementaion is better than our dumb fall-back one. */ if ((dp < sp && dp+len < sp) || (sp < dp && sp+len < dp)) return memcpy(dest, src, len); # endif /* I tried real hard to avoid getting to this point. You *really* ought to upgrade your system's libraries; the performance of this implementation sucks. */ if (dp < sp) { while (len-- > 0) *dp++ = *sp++; } else { if (dp == sp) return dest; dp += len; sp += len; while (len-- > 0) *--dp = *--sp; } #endif /*!HAVE_BCOPY*/ return dest; } #endif /*!HAVE_MEMMOVE*/ kbuild-3686/src/oldsed/lib/getopt1.c0000664000175000017500000001071615053010105017245 0ustar locutuslocutus/* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. 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, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include "getopt.h" #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #endif #ifndef NULL #define NULL 0 #endif int getopt_long (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } #endif /* Not ELIDE_CODE. */ #ifdef TEST #include int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "abc:d:0123456789", long_options, &option_index); if (c == -1) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case 'd': printf ("option d with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ kbuild-3686/src/oldsed/lib/getline.c0000664000175000017500000000443215053010104017306 0ustar locutuslocutus#ifdef HAVE_CONFIG_H #include "config.h" #endif #undef _GNU_SOURCE #include #define getline stdio_getline /* bird */ #include #undef getline /* bird */ #ifdef HAVE_STRINGS_H # include #else # include #endif /* HAVE_STRINGS_H */ #ifdef HAVE_STDLIB_H # include #endif /* HAVE_STDLIB_H */ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ #include #include /* Read up to (and including) a '\n' from STREAM into *LINEPTR (and null-terminate it). *LINEPTR is a pointer returned from malloc (or NULL), pointing to *N characters of space. It is realloc'd as necessary. Returns the number of characters read (not including the null terminator), or -1 on error or EOF. */ size_t getline (lineptr, n, stream) char **lineptr; size_t *n; FILE *stream; { char *line, *p; long size, copy; if (lineptr == NULL || n == NULL) { errno = EINVAL; return (size_t) -1; } if (ferror (stream)) return (size_t) -1; /* Make sure we have a line buffer to start with. */ if (*lineptr == NULL || *n < 2) /* !seen and no buf yet need 2 chars. */ { #ifndef MAX_CANON #define MAX_CANON 256 #endif if (!*lineptr) line = (char *) malloc (MAX_CANON); else line = (char *) realloc (*lineptr, MAX_CANON); if (line == NULL) return (size_t) -1; *lineptr = line; *n = MAX_CANON; } line = *lineptr; size = *n; copy = size; p = line; while (1) { long len; while (--copy > 0) { register int c = getc (stream); if (c == EOF) goto lose; else if ((*p++ = c) == '\n') goto win; } /* Need to enlarge the line buffer. */ len = p - line; size *= 2; line = (char *) realloc (line, size); if (line == NULL) goto lose; *lineptr = line; *n = size; p = line + len; copy = size - len; } lose: if (p == *lineptr) return (size_t) -1; /* Return a partial line since we got an error in the middle. */ win: #if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(MSDOS) || defined(__EMX__) if (p - 2 >= *lineptr && p[-2] == '\r') p[-2] = p[-1], --p; #endif *p = '\0'; return p - *lineptr; } kbuild-3686/src/oldsed/Makefile.am0000664000175000017500000000273615053010105017007 0ustar locutuslocutus## Process this file with automake to produce Makefile.in # Automake requirements AUTOMAKE_OPTIONS = gnits 1.8 ACLOCAL_AMFLAGS = -I config PACKAGE = sed SUBDIRS = intl lib po sed doc testsuite noinst_DATA = bootstrap.sh noinst_HEADERS = basicdefs.h EXTRA_DIST = BUGS THANKS COPYING.DOC README.boot bootstrap.sh \ config/texi2dvi config/help2man html: cd doc && make html DISTCHECK_CONFIGURE_FLAGS = XGETTEXT='$(SHELL) -c : dummy' $(EXTRA_DC_FLAGS) EXTRA_DC_FLAGS = full-distcheck: make distcheck EXTRA_DC_FLAGS='--enable-html' make distcheck EXTRA_DC_FLAGS='--disable-i18n' make distcheck EXTRA_DC_FLAGS='--disable-nls' make distcheck EXTRA_DC_FLAGS='--without-included-regex' make distcheck EXTRA_DC_FLAGS='--without-included-gettext' update-regex: HOST=sources.redhat.com && \ BASEURL="http://$$HOST/cgi-bin/cvsweb.cgi/~checkout~/libc/posix" && \ QUERY='cvsroot=glibc&content-type=text/plain' && \ wget -O lib/regcomp.c "$$BASEURL/regcomp.c?$$QUERY" && \ wget -O lib/regexec.c "$$BASEURL/regexec.c?$$QUERY" && \ wget -O lib/regex.c "$$BASEURL/regex.c?$$QUERY" && \ wget -O lib/regex_.h "$$BASEURL/regex.h?$$QUERY" && \ wget -O lib/regex_internal.c "$$BASEURL/regex_internal.c?$$QUERY" && \ wget -O lib/regex_internal.h "$$BASEURL/regex_internal.h?$$QUERY" && \ wget -O testsuite/BOOST.tests "$$BASEURL/BOOST.tests?$$QUERY" && \ wget -O testsuite/PCRE.tests "$$BASEURL/PCRE.tests?$$QUERY" && \ wget -O testsuite/SPENCER.tests "$$BASEURL/rxspencer/tests?$$QUERY" kbuild-3686/src/oldsed/sed/0000775000175000017500000000000015053010105015516 5ustar locutuslocutuskbuild-3686/src/oldsed/sed/execute.c0000664000175000017500000013157715053010105017342 0ustar locutuslocutus/* GNU SED, a batch stream editor. Copyright (C) 1989,90,91,92,93,94,95,98,99,2002,2003,2004,2005,2006 Free Software Foundation, Inc. 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, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #undef EXPERIMENTAL_DASH_N_OPTIMIZATION /*don't use -- is very buggy*/ #define INITIAL_BUFFER_SIZE 50 #define FREAD_BUFFER_SIZE 8192 #include "sed.h" #include #include #include #ifndef errno extern int errno; #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef __GNUC__ # if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__-0 >= 7) /* silence warning about unused parameter even for "gcc -W -Wunused" */ # define UNUSED __attribute__((unused)) # endif #endif #ifndef UNUSED # define UNUSED #endif #ifdef HAVE_STRINGS_H # include #else # include #endif /*HAVE_STRINGS_H*/ #ifdef HAVE_MEMORY_H # include #endif #ifndef HAVE_STRCHR # define strchr index # define strrchr rindex #endif #ifdef HAVE_STDLIB_H # include #endif #ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 #endif #ifdef HAVE_SYS_TYPES_H # include #endif #include /* Sed operates a line at a time. */ struct line { char *text; /* Pointer to line allocated by malloc. */ char *active; /* Pointer to non-consumed part of text. */ size_t length; /* Length of text (or active, if used). */ size_t alloc; /* Allocated space for active. */ bool chomped; /* Was a trailing newline dropped? */ #ifdef HAVE_MBRTOWC mbstate_t mbstate; #endif }; /* A queue of text to write out at the end of a cycle (filled by the "a", "r" and "R" commands.) */ struct append_queue { const char *fname; char *text; size_t textlen; struct append_queue *next; bool free; }; /* State information for the input stream. */ struct input { /* The list of yet-to-be-opened files. It is invalid for file_list to be NULL. When *file_list is NULL we are currently processing the last file. */ char **file_list; /* Count of files we failed to open. */ countT bad_count; /* Current input line number (over all files). */ countT line_number; /* True if we'll reset line numbers and addresses before starting to process the next (possibly the first) file. */ bool reset_at_next_file; /* Function to read one line. If FP is NULL, read_fn better not be one which uses fp; in particular, read_always_fail() is recommended. */ bool (*read_fn) P_((struct input *)); /* read one line */ char *out_file_name; const char *in_file_name; /* if NULL, none of the following are valid */ FILE *fp; bool no_buffering; }; /* Have we done any replacements lately? This is used by the `t' command. */ static bool replaced = false; /* The current output file (stdout if -i is not being used. */ static struct output output_file; /* The `current' input line. */ static struct line line; /* An input line used to accumulate the result of the s and e commands. */ static struct line s_accum; /* An input line that's been stored by later use by the program */ static struct line hold; /* The buffered input look-ahead. The only field that should be used outside of read_mem_line() or line_init() is buffer.length. */ static struct line buffer; static struct append_queue *append_head = NULL; static struct append_queue *append_tail = NULL; #ifdef BOOTSTRAP /* We can't be sure that the system we're boostrapping on has memchr(), and ../lib/memchr.c requires configuration knowledge about how many bits are in a `long'. This implementation is far from ideal, but it should get us up-and-limping well enough to run the configure script, which is all that matters. */ # ifdef memchr # undef memchr # endif # define memchr bootstrap_memchr static VOID *bootstrap_memchr P_((const VOID *s, int c, size_t n)); static VOID * bootstrap_memchr(s, c, n) const VOID *s; int c; size_t n; { char *p; for (p=(char *)s; n-- > 0; ++p) if (*p == c) return p; return CAST(VOID *)0; } #endif /*BOOTSTRAP*/ /* increase a struct line's length, making some attempt at keeping realloc() calls under control by padding for future growth. */ static void resize_line P_((struct line *, size_t)); static void resize_line(lb, len) struct line *lb; size_t len; { int inactive; inactive = lb->active - lb->text; /* If the inactive part has got to more than two thirds of the buffer, * remove it. */ if (inactive > lb->alloc * 2) { MEMMOVE(lb->text, lb->active, lb->length); lb->alloc += lb->active - lb->text; lb->active = lb->text; inactive = 0; if (lb->alloc > len) return; } lb->alloc *= 2; if (lb->alloc < len) lb->alloc = len; if (lb->alloc < INITIAL_BUFFER_SIZE) lb->alloc = INITIAL_BUFFER_SIZE; lb->text = REALLOC(lb->text, inactive + lb->alloc, char); lb->active = lb->text + inactive; } /* Append `length' bytes from `string' to the line `to'. */ static void str_append P_((struct line *, const char *, size_t)); static void str_append(to, string, length) struct line *to; const char *string; size_t length; { size_t new_length = to->length + length; if (to->alloc < new_length) resize_line(to, new_length); MEMCPY(to->active + to->length, string, length); to->length = new_length; #ifdef HAVE_MBRTOWC if (mb_cur_max == 1) return; while (length) { int n = MBRLEN (string, length, &to->mbstate); /* An invalid sequence is treated like a singlebyte character. */ if (n == -1) { memset (&to->mbstate, 0, sizeof (to->mbstate)); n = 1; } if (n > 0) length -= n; else break; } #endif } static void str_append_modified P_((struct line *, const char *, size_t, enum replacement_types)); static void str_append_modified(to, string, length, type) struct line *to; const char *string; size_t length; enum replacement_types type; { size_t old_length = to->length; char *start, *end; if (length == 0) return; #ifdef HAVE_MBRTOWC { mbstate_t from_stat; if (type == REPL_ASIS) { str_append(to, string, length); return; } if (to->alloc - to->length < length * mb_cur_max) resize_line(to, to->length + length * mb_cur_max); MEMCPY (&from_stat, &to->mbstate, sizeof(mbstate_t)); while (length) { wchar_t wc; int n = MBRTOWC (&wc, string, length, &from_stat); /* An invalid sequence is treated like a singlebyte character. */ if (n == -1) { memset (&to->mbstate, 0, sizeof (from_stat)); n = 1; } if (n > 0) string += n, length -= n; else { /* Incomplete sequence, copy it manually. */ str_append(to, string, length); return; } /* Convert the first character specially... */ if (type & (REPL_UPPERCASE_FIRST | REPL_LOWERCASE_FIRST)) { if (type & REPL_UPPERCASE_FIRST) wc = towupper(wc); else wc = towlower(wc); type &= ~(REPL_LOWERCASE_FIRST | REPL_UPPERCASE_FIRST); if (type == REPL_ASIS) { n = WCRTOMB (to->active + to->length, wc, &to->mbstate); to->length += n; str_append(to, string, length); return; } } else if (type & REPL_UPPERCASE) wc = towupper(wc); else wc = towlower(wc); /* Copy the new wide character to the end of the string. */ n = WCRTOMB (to->active + to->length, wc, &to->mbstate); to->length += n; if (n == -1) { fprintf (stderr, "Case conversion produced an invalid character!"); abort (); } } } #else str_append(to, string, length); start = to->active + old_length; end = start + length; /* Now do the required modifications. First \[lu]... */ if (type & REPL_UPPERCASE_FIRST) { *start = toupper(*start); start++; type &= ~REPL_UPPERCASE_FIRST; } else if (type & REPL_LOWERCASE_FIRST) { *start = tolower(*start); start++; type &= ~REPL_LOWERCASE_FIRST; } if (type == REPL_ASIS) return; /* ...and then \[LU] */ if (type == REPL_UPPERCASE) for (; start != end; start++) *start = toupper(*start); else for (; start != end; start++) *start = tolower(*start); #endif } /* initialize a "struct line" buffer */ static void line_init P_((struct line *, size_t initial_size)); static void line_init(buf, initial_size) struct line *buf; size_t initial_size; { buf->text = MALLOC(initial_size, char); buf->active = buf->text; buf->alloc = initial_size; buf->length = 0; buf->chomped = true; #ifdef HAVE_MBRTOWC memset (&buf->mbstate, 0, sizeof (buf->mbstate)); #endif } /* Copy the contents of the line `from' into the line `to'. This destroys the old contents of `to'. */ static void line_copy P_((struct line *from, struct line *to)); static void line_copy(from, to) struct line *from; struct line *to; { /* Remove the inactive portion in the destination buffer. */ to->alloc += to->active - to->text; if (to->alloc < from->length) { to->alloc *= 2; if (to->alloc < from->length) to->alloc = from->length; if (to->alloc < INITIAL_BUFFER_SIZE) to->alloc = INITIAL_BUFFER_SIZE; /* Use FREE()+MALLOC() instead of REALLOC() to avoid unnecessary copying of old text. */ FREE(to->text); to->text = MALLOC(to->alloc, char); } to->active = to->text; to->length = from->length; to->chomped = from->chomped; MEMCPY(to->active, from->active, from->length); #ifdef HAVE_MBRTOWC MEMCPY(&to->mbstate, &from->mbstate, sizeof (from->mbstate)); #endif } /* Append the contents of the line `from' to the line `to'. */ static void line_append P_((struct line *from, struct line *to)); static void line_append(from, to) struct line *from; struct line *to; { str_append(to, "\n", 1); str_append(to, from->active, from->length); to->chomped = from->chomped; #ifdef HAVE_MBRTOWC MEMCPY (&to->mbstate, &from->mbstate, sizeof (from->mbstate)); #endif } /* Exchange the contents of two "struct line" buffers. */ static void line_exchange P_((struct line *, struct line *)); static void line_exchange(a, b) struct line *a; struct line *b; { struct line t; MEMCPY(&t, a, sizeof(struct line)); MEMCPY( a, b, sizeof(struct line)); MEMCPY( b, &t, sizeof(struct line)); } /* dummy function to simplify read_pattern_space() */ static bool read_always_fail P_((struct input *)); static bool read_always_fail(input) struct input *input UNUSED; { return false; } static bool read_file_line P_((struct input *)); static bool read_file_line(input) struct input *input; { static char *b; static size_t blen; long result = ck_getline (&b, &blen, input->fp); if (result <= 0) return false; /* Remove the trailing new-line that is left by getline. */ if (b[result - 1] == '\n') --result; else line.chomped = false; str_append(&line, b, result); return true; } static inline void output_missing_newline P_((struct output *)); static inline void output_missing_newline(outf) struct output *outf; { if (outf->missing_newline) { ck_fwrite("\n", 1, 1, outf->fp); outf->missing_newline = false; } } static inline void flush_output P_((FILE *)); static inline void flush_output(fp) FILE *fp; { #ifndef CONFIG_WITHOUT_O_OPT if (fp != sed_stdout || unbuffered_output) #else if (fp != stdout || unbuffered_output) #endif ck_fflush(fp); } static void output_line P_((const char *, size_t, bool, struct output *)); static void output_line(text, length, nl, outf) const char *text; size_t length; bool nl; struct output *outf; { output_missing_newline(outf); if (length) ck_fwrite(text, 1, length, outf->fp); if (nl) ck_fwrite("\n", 1, 1, outf->fp); else outf->missing_newline = true; flush_output(outf->fp); } static struct append_queue *next_append_slot P_((void)); static struct append_queue * next_append_slot() { struct append_queue *n = MALLOC(1, struct append_queue); n->fname = NULL; n->text = NULL; n->textlen = 0; n->next = NULL; n->free = false; if (append_tail) append_tail->next = n; else append_head = n; return append_tail = n; } static void release_append_queue P_((void)); static void release_append_queue() { struct append_queue *p, *q; for (p=append_head; p; p=q) { if (p->free) FREE(p->text); q = p->next; FREE(p); } append_head = append_tail = NULL; } static void dump_append_queue P_((void)); static void dump_append_queue() { struct append_queue *p; output_missing_newline(&output_file); for (p=append_head; p; p=p->next) { if (p->text) ck_fwrite(p->text, 1, p->textlen, output_file.fp); if (p->fname) { char buf[FREAD_BUFFER_SIZE]; size_t cnt; FILE *fp; /* "If _fname_ does not exist or cannot be read, it shall be treated as if it were an empty file, causing no error condition." IEEE Std 1003.2-1992 So, don't fail. */ fp = ck_fopen(p->fname, "r", false); if (fp) { while ((cnt = ck_fread(buf, 1, sizeof buf, fp)) > 0) ck_fwrite(buf, 1, cnt, output_file.fp); ck_fclose(fp); } } } flush_output(output_file.fp); release_append_queue(); } /* Compute the name of the backup file for in-place editing */ static char *get_backup_file_name P_((const char *)); static char * get_backup_file_name(name) const char *name; { char *old_asterisk, *asterisk, *backup, *p; int name_length = strlen(name), backup_length = strlen(in_place_extension); /* Compute the length of the backup file */ for (asterisk = in_place_extension - 1, old_asterisk = asterisk + 1; asterisk = strchr(old_asterisk, '*'); old_asterisk = asterisk + 1) backup_length += name_length - 1; p = backup = xmalloc(backup_length + 1); /* Each iteration gobbles up to an asterisk */ for (asterisk = in_place_extension - 1, old_asterisk = asterisk + 1; asterisk = strchr(old_asterisk, '*'); old_asterisk = asterisk + 1) { MEMCPY (p, old_asterisk, asterisk - old_asterisk); p += asterisk - old_asterisk; strcpy (p, name); p += name_length; } /* Tack on what's after the last asterisk */ strcpy (p, old_asterisk); return backup; } /* Initialize a struct input for the named file. */ static void open_next_file P_((const char *name, struct input *)); static void open_next_file(name, input) const char *name; struct input *input; { buffer.length = 0; if (name[0] == '-' && name[1] == '\0' && !in_place_extension) { clearerr(stdin); /* clear any stale EOF indication */ input->fp = stdin; } else if ( ! (input->fp = ck_fopen(name, "r", false)) ) { const char *ptr = strerror(errno); fprintf(stderr, _("%s: can't read %s: %s\n"), myname, name, ptr); input->read_fn = read_always_fail; /* a redundancy */ ++input->bad_count; return; } input->read_fn = read_file_line; if (in_place_extension) { int output_fd; char *tmpdir = ck_strdup(name), *p; struct stat st; /* get the base name */ if (p = strrchr(tmpdir, '/')) *(p + 1) = 0; else strcpy(tmpdir, "."); input->in_file_name = name; if (isatty (fileno (input->fp))) panic(_("couldn't edit %s: is a terminal"), input->in_file_name); fstat (fileno (input->fp), &st); if (!S_ISREG (st.st_mode)) panic(_("couldn't edit %s: not a regular file"), input->in_file_name); output_file.fp = ck_mkstemp (&input->out_file_name, tmpdir, "sed"); output_file.missing_newline = false; free (tmpdir); if (!output_file.fp) panic(_("couldn't open temporary file %s: %s"), input->out_file_name, strerror(errno)); output_fd = fileno (output_file.fp); #ifdef HAVE_FCHMOD fchmod (output_fd, st.st_mode); #endif #ifdef HAVE_FCHOWN if (fchown (output_fd, st.st_uid, st.st_gid) == -1) fchown (output_fd, -1, st.st_gid); #endif } else #ifndef CONFIG_WITHOUT_O_OPT output_file.fp = sed_stdout; #else output_file.fp = stdout; #endif } /* Clean up an input stream that we are done with. */ static void closedown P_((struct input *)); static void closedown(input) struct input *input; { input->read_fn = read_always_fail; if (!input->fp) return; if (input->fp != stdin) /* stdin can be reused on tty and tape devices */ ck_fclose(input->fp); if (in_place_extension && output_file.fp != NULL) { ck_fclose (output_file.fp); if (strcmp(in_place_extension, "*") != 0) { char *backup_file_name = get_backup_file_name(input->in_file_name); ck_rename (input->in_file_name, backup_file_name, input->out_file_name); free (backup_file_name); } ck_rename (input->out_file_name, input->in_file_name, input->out_file_name); free (input->out_file_name); } input->fp = NULL; } /* Reset range commands so that they are marked as non-matching */ static void reset_addresses P_((struct vector *)); static void reset_addresses(vec) struct vector *vec; { struct sed_cmd *cur_cmd; int n; for (cur_cmd = vec->v, n = vec->v_length; n--; cur_cmd++) if (cur_cmd->a1 && cur_cmd->a1->addr_type == ADDR_IS_NUM && cur_cmd->a1->addr_number == 0) cur_cmd->range_state = RANGE_ACTIVE; else cur_cmd->range_state = RANGE_INACTIVE; } /* Read in the next line of input, and store it in the pattern space. Return zero if there is nothing left to input. */ static bool read_pattern_space P_((struct input *, struct vector *, bool)); static bool read_pattern_space(input, the_program, append) struct input *input; struct vector *the_program; bool append; { if (append_head) /* redundant test to optimize for common case */ dump_append_queue(); replaced = false; if (!append) line.length = 0; line.chomped = true; /* default, until proved otherwise */ while ( ! (*input->read_fn)(input) ) { closedown(input); if (!*input->file_list) return false; if (input->reset_at_next_file) { input->line_number = 0; reset_addresses (the_program); rewind_read_files (); /* If doing in-place editing, we will never append the new-line to this file; but if the output goes to stdout, we might still have to output the missing new-line. */ if (in_place_extension) output_file.missing_newline = false; input->reset_at_next_file = separate_files; } open_next_file (*input->file_list++, input); } ++input->line_number; return true; } static bool last_file_with_data_p P_((struct input *)); static bool last_file_with_data_p(input) struct input *input; { for (;;) { int ch; closedown(input); if (!*input->file_list) return true; open_next_file(*input->file_list++, input); if (input->fp) { if ((ch = getc(input->fp)) != EOF) { ungetc(ch, input->fp); return false; } } } } /* Determine if we match the `$' address. */ static bool test_eof P_((struct input *)); static bool test_eof(input) struct input *input; { int ch; if (buffer.length) return false; if (!input->fp) return separate_files || last_file_with_data_p(input); if (feof(input->fp)) return separate_files || last_file_with_data_p(input); if ((ch = getc(input->fp)) == EOF) return separate_files || last_file_with_data_p(input); ungetc(ch, input->fp); return false; } /* Return non-zero if the current line matches the address pointed to by `addr'. */ static bool match_an_address_p P_((struct addr *, struct input *)); static bool match_an_address_p(addr, input) struct addr *addr; struct input *input; { switch (addr->addr_type) { case ADDR_IS_NULL: return true; case ADDR_IS_REGEX: return match_regex(addr->addr_regex, line.active, line.length, 0, NULL, 0); case ADDR_IS_NUM_MOD: return (input->line_number >= addr->addr_number && ((input->line_number - addr->addr_number) % addr->addr_step) == 0); case ADDR_IS_STEP: case ADDR_IS_STEP_MOD: /* reminder: these are only meaningful for a2 addresses */ /* a2->addr_number needs to be recomputed each time a1 address matches for the step and step_mod types */ return (addr->addr_number <= input->line_number); case ADDR_IS_LAST: return test_eof(input); /* ADDR_IS_NUM is handled in match_address_p. */ case ADDR_IS_NUM: default: panic("INTERNAL ERROR: bad address type"); } /*NOTREACHED*/ return false; } /* return non-zero if current address is valid for cmd */ static bool match_address_p P_((struct sed_cmd *, struct input *)); static bool match_address_p(cmd, input) struct sed_cmd *cmd; struct input *input; { if (!cmd->a1) return true; if (cmd->range_state != RANGE_ACTIVE) { /* Find if we are going to activate a range. Handle ADDR_IS_NUM specially: it represent an "absolute" state, it should not be computed like regexes. */ if (cmd->a1->addr_type == ADDR_IS_NUM) { if (!cmd->a2) return (input->line_number == cmd->a1->addr_number); if (cmd->range_state == RANGE_CLOSED || input->line_number < cmd->a1->addr_number) return false; } else { if (!cmd->a2) return match_an_address_p(cmd->a1, input); if (!match_an_address_p(cmd->a1, input)) return false; } /* Ok, start a new range. */ cmd->range_state = RANGE_ACTIVE; switch (cmd->a2->addr_type) { case ADDR_IS_REGEX: /* Always include at least two lines. */ return true; case ADDR_IS_NUM: /* Same handling as below, but always include at least one line. */ if (input->line_number >= cmd->a2->addr_number) cmd->range_state = RANGE_CLOSED; return true; case ADDR_IS_STEP: cmd->a2->addr_number = input->line_number + cmd->a2->addr_step; return true; case ADDR_IS_STEP_MOD: cmd->a2->addr_number = input->line_number + cmd->a2->addr_step - (input->line_number%cmd->a2->addr_step); return true; default: break; } } /* cmd->range_state == RANGE_ACTIVE. Check if the range is ending; also handle ADDR_IS_NUM specially in this case. */ if (cmd->a2->addr_type == ADDR_IS_NUM) { /* If the second address is a line number, and if we got past that line, fail to match (it can happen when you jump over such addresses with `b' and `t'. Use RANGE_CLOSED so that the range is not re-enabled anymore. */ if (input->line_number >= cmd->a2->addr_number) cmd->range_state = RANGE_CLOSED; return (input->line_number <= cmd->a2->addr_number); } /* Other addresses are treated as usual. */ if (match_an_address_p(cmd->a2, input)) cmd->range_state = RANGE_CLOSED; return true; } static void do_list P_((int line_len)); static void do_list(line_len) int line_len; { unsigned char *p = CAST(unsigned char *)line.active; countT len = line.length; countT width = 0; char obuf[180]; /* just in case we encounter a 512-bit char (;-) */ char *o; size_t olen; FILE *fp = output_file.fp; output_missing_newline(&output_file); for (; len--; ++p) { o = obuf; /* Some locales define 8-bit characters as printable. This makes the testsuite fail at 8to7.sed because the `l' command in fact will not convert the 8-bit characters. */ #if defined isascii || defined HAVE_ISASCII if (isascii(*p) && ISPRINT(*p)) { #else if (ISPRINT(*p)) { #endif *o++ = *p; if (*p == '\\') *o++ = '\\'; } else { *o++ = '\\'; switch (*p) { #if defined __STDC__ && __STDC__-0 case '\a': *o++ = 'a'; break; #else /* Not STDC; we'll just assume ASCII */ case 007: *o++ = 'a'; break; #endif case '\b': *o++ = 'b'; break; case '\f': *o++ = 'f'; break; case '\n': *o++ = 'n'; break; case '\r': *o++ = 'r'; break; case '\t': *o++ = 't'; break; case '\v': *o++ = 'v'; break; default: sprintf(o, "%03o", *p); o += strlen(o); break; } } olen = o - obuf; if (width+olen >= line_len && line_len > 0) { ck_fwrite("\\\n", 1, 2, fp); width = 0; } ck_fwrite(obuf, 1, olen, fp); width += olen; } ck_fwrite("$\n", 1, 2, fp); flush_output (fp); } static enum replacement_types append_replacement P_((struct line *, struct replacement *, struct re_registers *, enum replacement_types)); static enum replacement_types append_replacement (buf, p, regs, repl_mod) struct line *buf; struct replacement *p; struct re_registers *regs; enum replacement_types repl_mod; { for (; p; p=p->next) { int i = p->subst_id; enum replacement_types curr_type; /* Apply a \[lu] modifier that was given earlier, but which we have not had yet the occasion to apply. But don't do it if this replacement has a modifier of its own. */ curr_type = (p->repl_type & REPL_MODIFIERS) ? p->repl_type : p->repl_type | repl_mod; repl_mod = 0; if (p->prefix_length) { str_append_modified(buf, p->prefix, p->prefix_length, curr_type); curr_type &= ~REPL_MODIFIERS; } if (0 <= i) if (regs->end[i] == regs->start[i] && p->repl_type & REPL_MODIFIERS) /* Save this modifier, we shall apply it later. e.g. in s/()([a-z])/\u\1\2/ the \u modifier is applied to \2, not \1 */ repl_mod = curr_type & REPL_MODIFIERS; else str_append_modified(buf, line.active + regs->start[i], CAST(size_t)(regs->end[i] - regs->start[i]), curr_type); } return repl_mod; } static void do_subst P_((struct subst *)); static void do_subst(sub) struct subst *sub; { size_t start = 0; /* where to start scan for (next) match in LINE */ size_t last_end = 0; /* where did the last successful match end in LINE */ countT count = 0; /* number of matches found */ bool again = true; static struct re_registers regs; if (s_accum.alloc == 0) line_init(&s_accum, INITIAL_BUFFER_SIZE); s_accum.length = 0; /* The first part of the loop optimizes s/xxx// when xxx is at the start, and s/xxx$// */ if (!match_regex(sub->regx, line.active, line.length, start, ®s, sub->max_id + 1)) return; if (!sub->replacement && sub->numb <= 1) if (regs.start[0] == 0 && !sub->global) { /* We found a match, set the `replaced' flag. */ replaced = true; line.active += regs.end[0]; line.length -= regs.end[0]; line.alloc -= regs.end[0]; goto post_subst; } else if (regs.end[0] == line.length) { /* We found a match, set the `replaced' flag. */ replaced = true; line.length = regs.start[0]; goto post_subst; } do { enum replacement_types repl_mod = 0; size_t offset = regs.start[0]; size_t matched = regs.end[0] - regs.start[0]; /* Copy stuff to the left of this match into the output string. */ if (start < offset) str_append(&s_accum, line.active + start, offset - start); /* If we're counting up to the Nth match, are we there yet? And even if we are there, there is another case we have to skip: are we matching an empty string immediately following another match? This latter case avoids that baaaac, when passed through s,a*,x,g, gives `xbxxcx' instead of xbxcx. This behavior is unacceptable because it is not consistently applied (for example, `baaaa' gives `xbx', not `xbxx'). */ if ((matched > 0 || count == 0 || offset > last_end) && ++count >= sub->numb) { /* We found a match, set the `replaced' flag. */ replaced = true; /* Now expand the replacement string into the output string. */ repl_mod = append_replacement (&s_accum, sub->replacement, ®s, repl_mod); again = sub->global; } else { /* The match was not replaced. Copy the text until its end; if it was vacuous, skip over one character and add that character to the output. */ if (matched == 0) { if (start < line.length) matched = 1; else break; } str_append(&s_accum, line.active + offset, matched); } /* Start after the match. last_end is the real end of the matched substring, excluding characters that were skipped in case the RE matched the empty string. */ start = offset + matched; last_end = regs.end[0]; } while (again && start <= line.length && match_regex(sub->regx, line.active, line.length, start, ®s, sub->max_id + 1)); /* Copy stuff to the right of the last match into the output string. */ if (start < line.length) str_append(&s_accum, line.active + start, line.length-start); s_accum.chomped = line.chomped; /* Exchange line and s_accum. This can be much cheaper than copying s_accum.active into line.text (for huge lines). */ line_exchange(&line, &s_accum); /* Finish up. */ if (count < sub->numb) return; post_subst: if (sub->print & 1) output_line(line.active, line.length, line.chomped, &output_file); if (sub->eval) { #ifdef HAVE_POPEN FILE *pipe; s_accum.length = 0; str_append (&line, "", 1); pipe = popen(line.active, "r"); if (pipe != NULL) { while (!feof (pipe)) { char buf[4096]; int n = fread (buf, sizeof(char), 4096, pipe); if (n > 0) str_append(&s_accum, buf, n); } pclose (pipe); line_exchange(&line, &s_accum); if (line.length && line.active[line.length - 1] == '\n') line.length--; } else panic(_("error in subprocess")); #else panic(_("option `e' not supported")); #endif } if (sub->print & 2) output_line(line.active, line.length, line.chomped, &output_file); if (sub->outf) output_line(line.active, line.length, line.chomped, sub->outf); } #ifdef EXPERIMENTAL_DASH_N_OPTIMIZATION /* Used to attempt a simple-minded optimization. */ static countT branches; static countT count_branches P_((struct vector *)); static countT count_branches(program) struct vector *program; { struct sed_cmd *cur_cmd = program->v; countT isn_cnt = program->v_length; countT cnt = 0; while (isn_cnt-- > 0) { switch (cur_cmd->cmd) { case 'b': case 't': case 'T': case '{': ++cnt; } } return cnt; } static struct sed_cmd *shrink_program P_((struct vector *, struct sed_cmd *)); static struct sed_cmd * shrink_program(vec, cur_cmd) struct vector *vec; struct sed_cmd *cur_cmd; { struct sed_cmd *v = vec->v; struct sed_cmd *last_cmd = v + vec->v_length; struct sed_cmd *p; countT cmd_cnt; for (p=v; p < cur_cmd; ++p) if (p->cmd != '#') MEMCPY(v++, p, sizeof *v); cmd_cnt = v - vec->v; for (; p < last_cmd; ++p) if (p->cmd != '#') MEMCPY(v++, p, sizeof *v); vec->v_length = v - vec->v; return (0 < vec->v_length) ? (vec->v + cmd_cnt) : CAST(struct sed_cmd *)0; } #endif /*EXPERIMENTAL_DASH_N_OPTIMIZATION*/ /* Execute the program `vec' on the current input line. Return exit status if caller should quit, -1 otherwise. */ static int execute_program P_((struct vector *, struct input *)); static int execute_program(vec, input) struct vector *vec; struct input *input; { struct sed_cmd *cur_cmd; struct sed_cmd *end_cmd; cur_cmd = vec->v; end_cmd = vec->v + vec->v_length; while (cur_cmd < end_cmd) { if (match_address_p(cur_cmd, input) != cur_cmd->addr_bang) { switch (cur_cmd->cmd) { case 'a': { struct append_queue *aq = next_append_slot(); aq->text = cur_cmd->x.cmd_txt.text; aq->textlen = cur_cmd->x.cmd_txt.text_length; } break; case '{': case 'b': cur_cmd = vec->v + cur_cmd->x.jump_index; continue; case '}': case '#': case ':': /* Executing labels and block-ends are easy. */ break; case 'c': if (cur_cmd->range_state != RANGE_ACTIVE) output_line(cur_cmd->x.cmd_txt.text, cur_cmd->x.cmd_txt.text_length - 1, true, &output_file); /* POSIX.2 is silent about c starting a new cycle, but it seems to be expected (and make sense). */ /* Fall Through */ case 'd': return -1; case 'D': { char *p = memchr(line.active, '\n', line.length); if (!p) return -1; ++p; line.alloc -= p - line.active; line.length -= p - line.active; line.active += p - line.active; /* reset to start next cycle without reading a new line: */ cur_cmd = vec->v; continue; } case 'e': { #ifdef HAVE_POPEN FILE *pipe; int cmd_length = cur_cmd->x.cmd_txt.text_length; if (s_accum.alloc == 0) line_init(&s_accum, INITIAL_BUFFER_SIZE); s_accum.length = 0; if (!cmd_length) { str_append (&line, "", 1); pipe = popen(line.active, "r"); } else { cur_cmd->x.cmd_txt.text[cmd_length - 1] = 0; pipe = popen(cur_cmd->x.cmd_txt.text, "r"); output_missing_newline(&output_file); } if (pipe != NULL) { while (!feof (pipe)) { char buf[4096]; int n = fread (buf, sizeof(char), 4096, pipe); if (n > 0) if (!cmd_length) str_append(&s_accum, buf, n); else ck_fwrite(buf, 1, n, output_file.fp); } pclose (pipe); if (!cmd_length) { /* Store into pattern space for plain `e' commands */ if (s_accum.length && s_accum.active[s_accum.length - 1] == '\n') s_accum.length--; /* Exchange line and s_accum. This can be much cheaper than copying s_accum.active into line.text (for huge lines). */ line_exchange(&line, &s_accum); } else flush_output(output_file.fp); } else panic(_("error in subprocess")); #else panic(_("`e' command not supported")); #endif break; } case 'g': line_copy(&hold, &line); break; case 'G': line_append(&hold, &line); break; case 'h': line_copy(&line, &hold); break; case 'H': line_append(&line, &hold); break; case 'i': output_line(cur_cmd->x.cmd_txt.text, cur_cmd->x.cmd_txt.text_length - 1, true, &output_file); break; case 'l': do_list(cur_cmd->x.int_arg == -1 ? lcmd_out_line_len : cur_cmd->x.int_arg); break; case 'L': output_missing_newline(&output_file); fmt(line.active, line.active + line.length, cur_cmd->x.int_arg == -1 ? lcmd_out_line_len : cur_cmd->x.int_arg, output_file.fp); flush_output(output_file.fp); break; case 'n': if (!no_default_output) output_line(line.active, line.length, line.chomped, &output_file); if (test_eof(input) || !read_pattern_space(input, vec, false)) return -1; break; case 'N': str_append(&line, "\n", 1); if (test_eof(input) || !read_pattern_space(input, vec, true)) { line.length--; if (posixicity == POSIXLY_EXTENDED && !no_default_output) output_line(line.active, line.length, line.chomped, &output_file); return -1; } break; case 'p': output_line(line.active, line.length, line.chomped, &output_file); break; case 'P': { char *p = memchr(line.active, '\n', line.length); output_line(line.active, p ? p - line.active : line.length, p ? true : line.chomped, &output_file); } break; case 'q': if (!no_default_output) output_line(line.active, line.length, line.chomped, &output_file); dump_append_queue(); case 'Q': return cur_cmd->x.int_arg == -1 ? 0 : cur_cmd->x.int_arg; case 'r': if (cur_cmd->x.fname) { struct append_queue *aq = next_append_slot(); aq->fname = cur_cmd->x.fname; } break; case 'R': if (cur_cmd->x.fp && !feof (cur_cmd->x.fp)) { struct append_queue *aq; size_t buflen; char *text = NULL; int result; result = ck_getline (&text, &buflen, cur_cmd->x.fp); if (result != EOF) { aq = next_append_slot(); aq->free = true; aq->text = text; aq->textlen = result; } } break; case 's': do_subst(cur_cmd->x.cmd_subst); break; case 't': if (replaced) { replaced = false; cur_cmd = vec->v + cur_cmd->x.jump_index; continue; } break; case 'T': if (!replaced) { cur_cmd = vec->v + cur_cmd->x.jump_index; continue; } else replaced = false; break; case 'w': if (cur_cmd->x.fp) output_line(line.active, line.length, line.chomped, cur_cmd->x.outf); break; case 'W': if (cur_cmd->x.fp) { char *p = memchr(line.active, '\n', line.length); output_line(line.active, p ? p - line.active : line.length, p ? true : line.chomped, cur_cmd->x.outf); } break; case 'x': line_exchange(&line, &hold); break; case 'y': { #ifdef HAVE_MBRTOWC if (mb_cur_max > 1) { int idx, prev_idx; /* index in the input line. */ char **trans; mbstate_t mbstate; memset(&mbstate, 0, sizeof(mbstate_t)); for (idx = 0; idx < line.length;) { int mbclen, i; mbclen = MBRLEN (line.active + idx, line.length - idx, &mbstate); /* An invalid sequence, or a truncated multibyte character. We treat it as a singlebyte character. */ if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0) mbclen = 1; trans = cur_cmd->x.translatemb; /* `i' indicate i-th translate pair. */ for (i = 0; trans[2*i] != NULL; i++) { if (strncmp(line.active + idx, trans[2*i], mbclen) == 0) { bool move_remain_buffer = false; int trans_len = strlen(trans[2*i+1]); if (mbclen < trans_len) { int new_len; new_len = line.length + 1 + trans_len - mbclen; /* We must extend the line buffer. */ if (line.alloc < new_len) { /* And we must resize the buffer. */ resize_line(&line, new_len); } move_remain_buffer = true; } else if (mbclen > trans_len) { /* We must truncate the line buffer. */ move_remain_buffer = true; } prev_idx = idx; if (move_remain_buffer) { int move_len, move_offset; char *move_from, *move_to; /* Move the remaining with \0. */ move_from = line.active + idx + mbclen; move_to = line.active + idx + trans_len; move_len = line.length + 1 - idx - mbclen; move_offset = trans_len - mbclen; memmove(move_to, move_from, move_len); line.length += move_offset; idx += move_offset; } strncpy(line.active + prev_idx, trans[2*i+1], trans_len); break; } } idx += mbclen; } } else #endif /* HAVE_MBRTOWC */ { unsigned char *p, *e; p = CAST(unsigned char *)line.active; for (e=p+line.length; px.translate[*p]; } } break; case '=': output_missing_newline(&output_file); fprintf(output_file.fp, "%lu\n", CAST(unsigned long)input->line_number); flush_output(output_file.fp); break; default: panic("INTERNAL ERROR: Bad cmd %c", cur_cmd->cmd); } } #ifdef EXPERIMENTAL_DASH_N_OPTIMIZATION /* If our top-level program consists solely of commands with ADDR_IS_NUM addresses then once we past the last mentioned line we should be able to quit if no_default_output is true, or otherwise quickly copy input to output. Now whether this optimization is a win or not depends on how cheaply we can implement this for the cases where it doesn't help, as compared against how much time is saved. One semantic difference (which I think is an improvement) is that *this* version will terminate after printing line two in the script "yes | sed -n 2p". Don't use this when in-place editing is active, because line numbers restart each time then. */ else if (!separate_files) { if (cur_cmd->a1->addr_type == ADDR_IS_NUM && (cur_cmd->a2 ? cur_cmd->range_state == RANGE_CLOSED : cur_cmd->a1->addr_number < input->line_number)) { /* Skip this address next time */ cur_cmd->addr_bang = !cur_cmd->addr_bang; cur_cmd->a1->addr_type = ADDR_IS_NULL; if (cur_cmd->a2) cur_cmd->a2->addr_type = ADDR_IS_NULL; /* can we make an optimization? */ if (cur_cmd->addr_bang) { if (cur_cmd->cmd == 'b' || cur_cmd->cmd == 't' || cur_cmd->cmd == 'T' || cur_cmd->cmd == '}') branches--; cur_cmd->cmd = '#'; /* replace with no-op */ if (branches == 0) cur_cmd = shrink_program(vec, cur_cmd); if (!cur_cmd && no_default_output) return 0; end_cmd = vec->v + vec->v_length; if (!cur_cmd) cur_cmd = end_cmd; continue; } } } #endif /*EXPERIMENTAL_DASH_N_OPTIMIZATION*/ /* this is buried down here so that a "continue" statement can skip it */ ++cur_cmd; } if (!no_default_output) output_line(line.active, line.length, line.chomped, &output_file); return -1; } /* Apply the compiled script to all the named files. */ int process_files(the_program, argv) struct vector *the_program; char **argv; { static char dash[] = "-"; static char *stdin_argv[2] = { dash, NULL }; struct input input; int status; line_init(&line, INITIAL_BUFFER_SIZE); line_init(&hold, 0); line_init(&buffer, 0); #ifdef EXPERIMENTAL_DASH_N_OPTIMIZATION branches = count_branches(the_program); #endif /*EXPERIMENTAL_DASH_N_OPTIMIZATION*/ input.reset_at_next_file = true; if (argv && *argv) input.file_list = argv; else if (in_place_extension) panic(_("no input files")); else input.file_list = stdin_argv; input.bad_count = 0; input.line_number = 0; input.read_fn = read_always_fail; input.fp = NULL; status = EXIT_SUCCESS; while (read_pattern_space(&input, the_program, false)) { status = execute_program(the_program, &input); if (status == -1) status = EXIT_SUCCESS; else break; } closedown(&input); #ifdef DEBUG_LEAKS /* We're about to exit, so these free()s are redundant. But if we're running under a memory-leak detecting implementation of malloc(), we want to explicitly deallocate in order to avoid extraneous noise from the allocator. */ release_append_queue(); FREE(buffer.text); FREE(hold.text); FREE(line.text); FREE(s_accum.text); #endif /*DEBUG_LEAKS*/ if (input.bad_count) status = 2; return status; } kbuild-3686/src/oldsed/sed/regexp.c0000664000175000017500000001453715053010105017166 0ustar locutuslocutus/* GNU SED, a batch stream editor. Copyright (C) 1999, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 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, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "sed.h" #include #include #ifdef HAVE_STDLIB_H # include #endif #ifdef gettext_noop # define N_(String) gettext_noop(String) #else # define N_(String) (String) #endif extern bool use_extended_syntax_p; static const char errors[] = "no previous regular expression\0" "cannot specify modifiers on empty regexp"; #define NO_REGEX (errors) #define BAD_MODIF (NO_REGEX + sizeof(N_("no previous regular expression"))) #define END_ERRORS (BAD_MODIF + sizeof(N_("cannot specify modifiers on empty regexp"))) static void compile_regex_1 (new_regex, needed_sub) struct regex *new_regex; int needed_sub; { #ifdef REG_PERL int errcode; errcode = regncomp(&new_regex->pattern, new_regex->re, new_regex->sz, (needed_sub ? 0 : REG_NOSUB) | new_regex->flags | extended_regexp_flags); if (errcode) { char errorbuf[200]; regerror(errcode, NULL, errorbuf, 200); bad_prog(gettext(errorbuf)); } #else const char *error; int syntax = ((extended_regexp_flags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC) & ~RE_UNMATCHED_RIGHT_PAREN_ORD; syntax |= RE_NO_POSIX_BACKTRACKING; #ifdef RE_ICASE syntax |= (new_regex->flags & REG_ICASE) ? RE_ICASE : 0; #endif #ifdef RE_NO_SUB syntax |= needed_sub ? 0 : RE_NO_SUB; #endif new_regex->pattern.fastmap = malloc (1 << (sizeof (char) * 8)); /* If REG_NEWLINE is set, newlines are treated differently. */ if (new_regex->flags & REG_NEWLINE) { /* REG_NEWLINE implies neither . nor [^...] match newline. */ syntax &= ~RE_DOT_NEWLINE; syntax |= RE_HAT_LISTS_NOT_NEWLINE; } re_set_syntax (syntax); error = re_compile_pattern (new_regex->re, new_regex->sz, &new_regex->pattern); new_regex->pattern.newline_anchor = (new_regex->flags & REG_NEWLINE) != 0; new_regex->pattern.translate = NULL; #ifndef RE_ICASE if (new_regex->flags & REG_ICASE) { static char translate[1 << (sizeof(char) * 8)]; int i; for (i = 0; i < sizeof(translate) / sizeof(char); i++) translate[i] = tolower (i); new_regex->pattern.translate = translate; } #endif if (error) bad_prog(error); #endif /* Just to be sure, I mark this as not POSIXLY_CORRECT behavior */ if (needed_sub && new_regex->pattern.re_nsub < needed_sub - 1 && posixicity == POSIXLY_EXTENDED) { char buf[200]; sprintf(buf, _("invalid reference \\%d on `s' command's RHS"), needed_sub - 1); bad_prog(buf); } } struct regex * compile_regex(b, flags, needed_sub) struct buffer *b; int flags; int needed_sub; { struct regex *new_regex; size_t re_len; /* // matches the last RE */ if (size_buffer(b) == 0) { if (flags > 0) bad_prog(_(BAD_MODIF)); return NULL; } re_len = size_buffer(b); new_regex = ck_malloc(sizeof (struct regex) + re_len - 1); new_regex->flags = flags; memcpy (new_regex->re, get_buffer(b), re_len); #ifdef REG_PERL new_regex->sz = re_len; #else /* GNU regex does not process \t & co. */ new_regex->sz = normalize_text(new_regex->re, re_len, TEXT_REGEX); #endif compile_regex_1 (new_regex, needed_sub); return new_regex; } #ifdef REG_PERL static void copy_regs (regs, pmatch, nregs) struct re_registers *regs; regmatch_t *pmatch; int nregs; { int i; int need_regs = nregs + 1; /* We need one extra element beyond `num_regs' for the `-1' marker GNU code uses. */ /* Have the register data arrays been allocated? */ if (!regs->start) { /* No. So allocate them with malloc. */ regs->start = MALLOC (need_regs, regoff_t); regs->end = MALLOC (need_regs, regoff_t); regs->num_regs = need_regs; } else if (need_regs > regs->num_regs) { /* Yes. We also need more elements than were already allocated, so reallocate them. */ regs->start = REALLOC (regs->start, need_regs, regoff_t); regs->end = REALLOC (regs->end, need_regs, regoff_t); regs->num_regs = need_regs; } /* Copy the regs. */ for (i = 0; i < nregs; ++i) { regs->start[i] = pmatch[i].rm_so; regs->end[i] = pmatch[i].rm_eo; } for ( ; i < regs->num_regs; ++i) regs->start[i] = regs->end[i] = -1; } #endif int match_regex(regex, buf, buflen, buf_start_offset, regarray, regsize) struct regex *regex; char *buf; size_t buflen; size_t buf_start_offset; struct re_registers *regarray; int regsize; { int ret; static struct regex *regex_last; #ifdef REG_PERL regmatch_t rm[10], *regmatch = rm; if (regsize > 10) regmatch = (regmatch_t *) alloca (sizeof (regmatch_t) * regsize); #endif /* printf ("Matching from %d/%d\n", buf_start_offset, buflen); */ /* Keep track of the last regexp matched. */ if (!regex) { regex = regex_last; if (!regex_last) bad_prog(_(NO_REGEX)); } else regex_last = regex; #ifdef REG_PERL regmatch[0].rm_so = CAST(int)buf_start_offset; regmatch[0].rm_eo = CAST(int)buflen; ret = regexec (®ex->pattern, buf, regsize, regmatch, REG_STARTEND); if (regsize) copy_regs (regarray, regmatch, regsize); return (ret == 0); #else if (regex->pattern.no_sub && regsize) compile_regex_1 (regex, regsize); regex->pattern.regs_allocated = REGS_REALLOCATE; ret = re_search (®ex->pattern, buf, buflen, buf_start_offset, buflen - buf_start_offset, regsize ? regarray : NULL); return (ret > -1); #endif } #ifdef DEBUG_LEAKS void release_regex(regex) struct regex *regex; { regfree(®ex->pattern); FREE(regex); } #endif /*DEBUG_LEAKS*/ kbuild-3686/src/oldsed/sed/Makefile.am0000664000175000017500000000067615053010105017563 0ustar locutuslocutus## Process this file with automake to produce Makefile.in bin_PROGRAMS = sed localedir = $(datadir)/locale sed_SOURCES = sed.c compile.c execute.c regexp.c fmt.c mbcs.c noinst_HEADERS = sed.h AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/intl \ -I$(top_srcdir) -I$(top_builddir)/lib \ -I$(top_builddir)/intl -DLOCALEDIR=\"$(localedir)\" sed_LDADD = ../lib/libsed.a @INTLLIBS@ sed_DEPENDENCIES = ../lib/libsed.a $(PROGRAMS): $(LDADD) kbuild-3686/src/oldsed/sed/mbcs.c0000664000175000017500000000300115053010104016577 0ustar locutuslocutus/* GNU SED, a batch stream editor. Copyright (C) 2003 Free Software Foundation, Inc. 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, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "sed.h" #include int mb_cur_max; #ifdef HAVE_MBRTOWC /* Add a byte to the multibyte character represented by the state CUR_STAT, and answer its length if a character is completed, or -2 if it is yet to be completed. */ int brlen (ch, cur_stat) int ch; mbstate_t *cur_stat; { char c = ch; /* If we use the generic brlen, then MBRLEN == mbrlen. */ int result = mbrtowc(NULL, &c, 1, cur_stat); /* An invalid sequence is treated like a singlebyte character. */ if (result == -1) { memset (cur_stat, 0, sizeof (mbstate_t)); return 1; } return result; } #endif void initialize_mbcs () { #ifdef HAVE_MBRTOWC mb_cur_max = MB_CUR_MAX; #else mb_cur_max = 1; #endif } kbuild-3686/src/oldsed/sed/Makefile.in0000664000175000017500000003605615053010105017575 0ustar locutuslocutus# Makefile.in generated by automake 1.9.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SOURCES = $(sed_SOURCES) srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = sed$(EXEEXT) subdir = sed DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/codeset.m4 \ $(top_srcdir)/config/getline.m4 \ $(top_srcdir)/config/gettext-ver.m4 \ $(top_srcdir)/config/gettext.m4 \ $(top_srcdir)/config/glibc21.m4 $(top_srcdir)/config/iconv.m4 \ $(top_srcdir)/config/lcmessage.m4 \ $(top_srcdir)/config/lib-ld.m4 \ $(top_srcdir)/config/lib-link.m4 \ $(top_srcdir)/config/lib-prefix.m4 \ $(top_srcdir)/config/progtest.m4 \ $(top_srcdir)/config/stdbool.m4 \ $(top_srcdir)/config/strverscmp.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) am_sed_OBJECTS = sed.$(OBJEXT) compile.$(OBJEXT) execute.$(OBJEXT) \ regexp.$(OBJEXT) fmt.$(OBJEXT) mbcs.$(OBJEXT) sed_OBJECTS = $(am_sed_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(sed_SOURCES) DIST_SOURCES = $(sed_SOURCES) HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_HTML_FALSE = @BUILD_HTML_FALSE@ BUILD_HTML_TRUE = @BUILD_HTML_TRUE@ BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GENCAT = @GENCAT@ GLIBC21 = @GLIBC21@ GMSGFMT = @GMSGFMT@ HAVE__BOOL = @HAVE__BOOL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLBISON = @INTLBISON@ INTLLIBS = @INTLLIBS@ INTLOBJS = @INTLOBJS@ INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MAKEINFO_HTML_FALSE = @MAKEINFO_HTML_FALSE@ MAKEINFO_HTML_TRUE = @MAKEINFO_HTML_TRUE@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ RANLIB = @RANLIB@ SED_FEATURE_VERSION = @SED_FEATURE_VERSION@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TEST_REGEX_FALSE = @TEST_REGEX_FALSE@ TEST_REGEX_TRUE = @TEST_REGEX_TRUE@ TEXI2HTML = @TEXI2HTML@ TEXI2HTML_HTML_FALSE = @TEXI2HTML_HTML_FALSE@ TEXI2HTML_HTML_TRUE = @TEXI2HTML_HTML_TRUE@ USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ localedir = $(datadir)/locale sed_SOURCES = sed.c compile.c execute.c regexp.c fmt.c mbcs.c noinst_HEADERS = sed.h AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/intl \ -I$(top_srcdir) -I$(top_builddir)/lib \ -I$(top_builddir)/intl -DLOCALEDIR=\"$(localedir)\" sed_LDADD = ../lib/libsed.a @INTLLIBS@ sed_DEPENDENCIES = ../lib/libsed.a all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits sed/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnits sed/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ rm -f "$(DESTDIR)$(bindir)/$$f"; \ done clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) installcheck-binPROGRAMS: $(bin_PROGRAMS) bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \ case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \ *" $$p "* | *" $(srcdir)/$$p "*) continue;; \ esac; \ f=`echo "$$p" | \ sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ for opt in --help --version; do \ if "$(DESTDIR)$(bindir)/$$f" $$opt >c$${pid}_.out \ 2>c$${pid}_.err &2; bad=1; fi; \ done; \ done; rm -f c$${pid}_.???; exit $$bad sed$(EXEEXT): $(sed_OBJECTS) $(sed_DEPENDENCIES) @rm -f sed$(EXEEXT) $(LINK) $(sed_LDFLAGS) $(sed_OBJECTS) $(sed_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execute.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbcs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regexp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sed.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` uninstall-info-am: ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-binPROGRAMS install-info: install-info-am install-man: installcheck-am: installcheck-binPROGRAMS maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-exec install-exec-am \ install-info install-info-am install-man install-strip \ installcheck installcheck-am installcheck-binPROGRAMS \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ ps ps-am tags uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-info-am $(PROGRAMS): $(LDADD) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: kbuild-3686/src/oldsed/sed/compile.c0000664000175000017500000012250015053010105017312 0ustar locutuslocutus/* GNU SED, a batch stream editor. Copyright (C) 1989,90,91,92,93,94,95,98,99,2002,2003,2004,2005,2006 Free Software Foundation, Inc. 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, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* compile.c: translate sed source into internal form */ #include "sed.h" #include "strverscmp.h" #include #include #ifdef HAVE_STRINGS_H # include # ifdef HAVE_MEMORY_H # include # endif #else # include #endif /* HAVE_STRINGS_H */ #ifdef HAVE_STDLIB_H # include #endif #ifndef EXIT_FAILURE # define EXIT_FAILURE 1 #endif #ifdef HAVE_SYS_TYPES_H # include #endif #include #define YMAP_LENGTH 256 /*XXX shouldn't this be (UCHAR_MAX+1)?*/ #define VECTOR_ALLOC_INCREMENT 40 /* let's not confuse text editors that have only dumb bracket-matching... */ #define OPEN_BRACKET '[' #define CLOSE_BRACKET ']' #define OPEN_BRACE '{' #define CLOSE_BRACE '}' struct prog_info { /* When we're reading a script command from a string, `prog.base' points to the first character in the string, 'prog.cur' points to the current character in the string, and 'prog.end' points to the end of the string. This allows us to compile script strings that contain nulls. */ const unsigned char *base; const unsigned char *cur; const unsigned char *end; /* This is the current script file. If it is NULL, we are reading from a string stored at `prog.cur' instead. If both `prog.file' and `prog.cur' are NULL, we're in trouble! */ FILE *file; }; /* Information used to give out useful and informative error messages. */ struct error_info { /* This is the name of the current script file. */ const char *name; /* This is the number of the current script line that we're compiling. */ countT line; /* This is the index of the "-e" expressions on the command line. */ countT string_expr_count; }; /* Label structure used to resolve GOTO's, labels, and block beginnings. */ struct sed_label { countT v_index; /* index of vector element being referenced */ char *name; /* NUL-terminated name of the label */ struct error_info err_info; /* track where `{}' blocks start */ struct sed_label *next; /* linked list (stack) */ }; struct special_files { struct output outf; FILE **pfp; }; FILE *my_stdin, *my_stdout, *my_stderr; struct special_files special_files[] = { { { "/dev/stdin", false, NULL, NULL }, &my_stdin }, { { "/dev/stdout", false, NULL, NULL }, &my_stdout }, { { "/dev/stderr", false, NULL, NULL }, &my_stderr }, { { NULL, false, NULL, NULL }, NULL } }; /* Where we are in the processing of the input. */ static struct prog_info prog; static struct error_info cur_input; /* Information about labels and jumps-to-labels. This is used to do the required backpatching after we have compiled all the scripts. */ static struct sed_label *jumps = NULL; static struct sed_label *labels = NULL; /* We wish to detect #n magic only in the first input argument; this flag tracks when we have consumed the first file of input. */ static bool first_script = true; /* Allow for scripts like "sed -e 'i\' -e foo": */ static struct buffer *pending_text = NULL; static struct text_buf *old_text_buf = NULL; /* Information about block start positions. This is used to backpatch block end positions. */ static struct sed_label *blocks = NULL; /* Use an obstack for compilation. */ static struct obstack obs; /* Various error messages we may want to print */ static const char errors[] = "multiple `!'s\0" "unexpected `,'\0" "invalid usage of +N or ~N as first address\0" "unmatched `{'\0" "unexpected `}'\0" "extra characters after command\0" "expected \\ after `a', `c' or `i'\0" "`}' doesn't want any addresses\0" ": doesn't want any addresses\0" "comments don't accept any addresses\0" "missing command\0" "command only uses one address\0" "unterminated address regex\0" "unterminated `s' command\0" "unterminated `y' command\0" "unknown option to `s'\0" "multiple `p' options to `s' command\0" "multiple `g' options to `s' command\0" "multiple number options to `s' command\0" "number option to `s' command may not be zero\0" "strings for `y' command are different lengths\0" "delimiter character is not a single-byte character\0" "expected newer version of sed\0" "invalid usage of line address 0\0" "unknown command: `%c'"; #define BAD_BANG (errors) #define BAD_COMMA (BAD_BANG + sizeof(N_("multiple `!'s"))) #define BAD_STEP (BAD_COMMA + sizeof(N_("unexpected `,'"))) #define EXCESS_OPEN_BRACE (BAD_STEP + sizeof(N_("invalid usage of +N or ~N as first address"))) #define EXCESS_CLOSE_BRACE (EXCESS_OPEN_BRACE + sizeof(N_("unmatched `{'"))) #define EXCESS_JUNK (EXCESS_CLOSE_BRACE + sizeof(N_("unexpected `}'"))) #define EXPECTED_SLASH (EXCESS_JUNK + sizeof(N_("extra characters after command"))) #define NO_CLOSE_BRACE_ADDR (EXPECTED_SLASH + sizeof(N_("expected \\ after `a', `c' or `i'"))) #define NO_COLON_ADDR (NO_CLOSE_BRACE_ADDR + sizeof(N_("`}' doesn't want any addresses"))) #define NO_SHARP_ADDR (NO_COLON_ADDR + sizeof(N_(": doesn't want any addresses"))) #define NO_COMMAND (NO_SHARP_ADDR + sizeof(N_("comments don't accept any addresses"))) #define ONE_ADDR (NO_COMMAND + sizeof(N_("missing command"))) #define UNTERM_ADDR_RE (ONE_ADDR + sizeof(N_("command only uses one address"))) #define UNTERM_S_CMD (UNTERM_ADDR_RE + sizeof(N_("unterminated address regex"))) #define UNTERM_Y_CMD (UNTERM_S_CMD + sizeof(N_("unterminated `s' command"))) #define UNKNOWN_S_OPT (UNTERM_Y_CMD + sizeof(N_("unterminated `y' command"))) #define EXCESS_P_OPT (UNKNOWN_S_OPT + sizeof(N_("unknown option to `s'"))) #define EXCESS_G_OPT (EXCESS_P_OPT + sizeof(N_("multiple `p' options to `s' command"))) #define EXCESS_N_OPT (EXCESS_G_OPT + sizeof(N_("multiple `g' options to `s' command"))) #define ZERO_N_OPT (EXCESS_N_OPT + sizeof(N_("multiple number options to `s' command"))) #define Y_CMD_LEN (ZERO_N_OPT + sizeof(N_("number option to `s' command may not be zero"))) #define BAD_DELIM (Y_CMD_LEN + sizeof(N_("strings for `y' command are different lengths"))) #define ANCIENT_VERSION (BAD_DELIM + sizeof(N_("delimiter character is not a single-byte character"))) #define INVALID_LINE_0 (ANCIENT_VERSION + sizeof(N_("expected newer version of sed"))) #define UNKNOWN_CMD (INVALID_LINE_0 + sizeof(N_("invalid usage of line address 0"))) #define END_ERRORS (UNKNOWN_CMD + sizeof(N_("unknown command: `%c'"))) static struct output *file_read = NULL; static struct output *file_write = NULL; /* Complain about an unknown command and exit. */ void bad_command(ch) char ch; { const char *msg = _(UNKNOWN_CMD); char *unknown_cmd = xmalloc(strlen(msg)); sprintf(unknown_cmd, msg, ch); bad_prog(unknown_cmd); } /* Complain about a programming error and exit. */ void bad_prog(why) const char *why; { if (cur_input.name) fprintf(stderr, _("%s: file %s line %lu: %s\n"), myname, cur_input.name, CAST(unsigned long)cur_input.line, why); else fprintf(stderr, _("%s: -e expression #%lu, char %lu: %s\n"), myname, CAST(unsigned long)cur_input.string_expr_count, CAST(unsigned long)(prog.cur-prog.base), why); exit(EXIT_FAILURE); } /* Read the next character from the program. Return EOF if there isn't anything to read. Keep cur_input.line up to date, so error messages can be meaningful. */ static int inchar P_((void)); static int inchar() { int ch = EOF; if (prog.cur) { if (prog.cur < prog.end) ch = *prog.cur++; } else if (prog.file) { if (!feof(prog.file)) ch = getc(prog.file); } if (ch == '\n') ++cur_input.line; return ch; } /* unget `ch' so the next call to inchar will return it. */ static void savchar P_((int ch)); static void savchar(ch) int ch; { if (ch == EOF) return; if (ch == '\n' && cur_input.line > 0) --cur_input.line; if (prog.cur) { if (prog.cur <= prog.base || *--prog.cur != ch) panic("Called savchar() with unexpected pushback (%x)", CAST(unsigned char)ch); } else ungetc(ch, prog.file); } /* Read the next non-blank character from the program. */ static int in_nonblank P_((void)); static int in_nonblank() { int ch; do ch = inchar(); while (ISBLANK(ch)); return ch; } /* Read an integer value from the program. */ static countT in_integer P_((int ch)); static countT in_integer(ch) int ch; { countT num = 0; while (ISDIGIT(ch)) { num = num * 10 + ch - '0'; ch = inchar(); } savchar(ch); return num; } static int add_then_next P_((struct buffer *b, int ch)); static int add_then_next(b, ch) struct buffer *b; int ch; { add1_buffer(b, ch); return inchar(); } static char * convert_number P_((char *, char *, const char *, int, int, int)); static char * convert_number(result, buf, bufend, base, maxdigits, default_char) char *result; char *buf; const char *bufend; int base; int maxdigits; int default_char; { int n = 0; char *p; for (p=buf; p < bufend && maxdigits-- > 0; ++p) { int d = -1; switch (*p) { case '0': d = 0x0; break; case '1': d = 0x1; break; case '2': d = 0x2; break; case '3': d = 0x3; break; case '4': d = 0x4; break; case '5': d = 0x5; break; case '6': d = 0x6; break; case '7': d = 0x7; break; case '8': d = 0x8; break; case '9': d = 0x9; break; case 'A': case 'a': d = 0xa; break; case 'B': case 'b': d = 0xb; break; case 'C': case 'c': d = 0xc; break; case 'D': case 'd': d = 0xd; break; case 'E': case 'e': d = 0xe; break; case 'F': case 'f': d = 0xf; break; } if (d < 0 || base <= d) break; n = n * base + d; } if (p == buf) *result = default_char; else *result = n; return p; } /* Read in a filename for a `r', `w', or `s///w' command. */ static struct buffer *read_filename P_((void)); static struct buffer * read_filename() { struct buffer *b; int ch; b = init_buffer(); ch = in_nonblank(); while (ch != EOF && ch != '\n') { #if 0 /*XXX ZZZ 1998-09-12 kpp: added, then had second thoughts*/ if (posixicity == POSIXLY_EXTENDED) if (ch == ';' || ch == '#') { savchar(ch); break; } #endif ch = add_then_next(b, ch); } add1_buffer(b, '\0'); return b; } static struct output *get_openfile P_((struct output **file_ptrs, char *mode, bool fail)); static struct output * get_openfile(file_ptrs, mode, fail) struct output **file_ptrs; char *mode; bool fail; { struct buffer *b; char *file_name; struct output *p; int is_stderr; b = read_filename(); file_name = get_buffer(b); for (p=*file_ptrs; p; p=p->link) if (strcmp(p->name, file_name) == 0) break; if (posixicity == POSIXLY_EXTENDED) { /* Check whether it is a special file (stdin, stdout or stderr) */ struct special_files *special = special_files; /* std* sometimes are not constants, so they cannot be used in the initializer for special_files */ #ifndef CONFIG_WITHOUT_O_OPT my_stdin = stdin; my_stdout = sed_stdout; my_stderr = stderr; #else my_stdin = stdin; my_stdout = stdout; my_stderr = stderr; #endif for (special = special_files; special->outf.name; special++) if (strcmp(special->outf.name, file_name) == 0) { special->outf.fp = *special->pfp; free_buffer (b); return &special->outf; } } if (!p) { p = OB_MALLOC(&obs, 1, struct output); p->name = ck_strdup(file_name); p->fp = ck_fopen(p->name, mode, fail); p->missing_newline = false; p->link = *file_ptrs; *file_ptrs = p; } free_buffer(b); return p; } static struct sed_cmd *next_cmd_entry P_((struct vector **vectorp)); static struct sed_cmd * next_cmd_entry(vectorp) struct vector **vectorp; { struct sed_cmd *cmd; struct vector *v; v = *vectorp; if (v->v_length == v->v_allocated) { v->v_allocated += VECTOR_ALLOC_INCREMENT; v->v = REALLOC(v->v, v->v_allocated, struct sed_cmd); } cmd = v->v + v->v_length; cmd->a1 = NULL; cmd->a2 = NULL; cmd->range_state = RANGE_INACTIVE; cmd->addr_bang = false; cmd->cmd = '\0'; /* something invalid, to catch bugs early */ *vectorp = v; return cmd; } static int snarf_char_class P_((struct buffer *b, mbstate_t *cur_stat)); static int snarf_char_class(b, cur_stat) struct buffer *b; mbstate_t *cur_stat; { int ch; int state = 0; int delim; bool pending_mb = 0; ch = inchar(); if (ch == '^') ch = add_then_next(b, ch); if (ch == CLOSE_BRACKET) ch = add_then_next(b, ch); /* States are: 0 outside a collation element, character class or collation class 1 after the bracket 2 after the opening ./:/= 3 after the closing ./:/= */ for (;; ch = add_then_next (b, ch)) { pending_mb = BRLEN (ch, cur_stat) != 1; switch (ch) { case EOF: case '\n': return ch; case '.': case ':': case '=': if (pending_mb) continue; if (state == 1) { delim = ch; state++; } else if (ch == delim && state == 2) state++; else break; continue; case OPEN_BRACKET: if (pending_mb) continue; state++; continue; case CLOSE_BRACKET: if (pending_mb) continue; if (state == 0 || state == 1) return ch; else if (state == 3) state = 0; break; default: break; } /* Getting a character different from .=: whilst in state 1 goes back to state 0, getting a character different from ] whilst in state 3 goes back to state 2. */ state &= ~1; } } static struct buffer *match_slash P_((int slash, bool regex)); static struct buffer * match_slash(slash, regex) int slash; bool regex; { struct buffer *b; int ch; bool pending_mb = false; mbstate_t cur_stat; memset (&cur_stat, 0, sizeof (mbstate_t)); if (BRLEN (slash, &cur_stat) == -2) if (BRLEN (slash, &cur_stat) == -2) bad_prog (BAD_DELIM); memset (&cur_stat, 0, sizeof (mbstate_t)); b = init_buffer(); while ((ch = inchar()) != EOF && ch != '\n') { pending_mb = BRLEN (ch, &cur_stat) != 1; pending_mb = BRLEN (ch, &cur_stat) != 1; if (!pending_mb) { if (ch == slash) return b; else if (ch == '\\') { ch = inchar(); if (ch == EOF) break; #ifndef REG_PERL else if (ch == 'n' && regex) ch = '\n'; #endif else if (ch != '\n' && ch != slash) add1_buffer(b, '\\'); } else if (ch == OPEN_BRACKET && regex) { add1_buffer(b, ch); ch = snarf_char_class(b, &cur_stat); if (ch != CLOSE_BRACKET) break; } } add1_buffer(b, ch); } if (ch == '\n') savchar(ch); /* for proper line number in error report */ free_buffer(b); return NULL; } static int mark_subst_opts P_((struct subst *cmd)); static int mark_subst_opts(cmd) struct subst *cmd; { int flags = 0; int ch; cmd->global = false; cmd->print = false; cmd->eval = false; cmd->numb = 0; cmd->outf = NULL; for (;;) switch ( (ch = in_nonblank()) ) { case 'i': /* GNU extension */ case 'I': /* GNU extension */ flags |= REG_ICASE; break; #ifdef REG_PERL case 's': /* GNU extension */ case 'S': /* GNU extension */ if (extended_regexp_flags & REG_PERL) flags |= REG_DOTALL; break; case 'x': /* GNU extension */ case 'X': /* GNU extension */ if (extended_regexp_flags & REG_PERL) flags |= REG_EXTENDED; break; #endif case 'm': /* GNU extension */ case 'M': /* GNU extension */ flags |= REG_NEWLINE; break; case 'e': cmd->eval = true; break; case 'p': if (cmd->print) bad_prog(_(EXCESS_P_OPT)); cmd->print |= (1 << cmd->eval); /* 1=before eval, 2=after */ break; case 'g': if (cmd->global) bad_prog(_(EXCESS_G_OPT)); cmd->global = true; break; case 'w': cmd->outf = get_openfile(&file_write, "w", true); return flags; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (cmd->numb) bad_prog(_(EXCESS_N_OPT)); cmd->numb = in_integer(ch); if (!cmd->numb) bad_prog(_(ZERO_N_OPT)); break; case CLOSE_BRACE: case '#': savchar(ch); /* Fall Through */ case EOF: case '\n': case ';': return flags; case '\r': if (inchar() == '\n') return flags; /* FALLTHROUGH */ default: bad_prog(_(UNKNOWN_S_OPT)); /*NOTREACHED*/ } } /* read in a label for a `:', `b', or `t' command */ static char *read_label P_((void)); static char * read_label() { struct buffer *b; int ch; char *ret; b = init_buffer(); ch = in_nonblank(); while (ch != EOF && ch != '\n' && !ISBLANK(ch) && ch != ';' && ch != CLOSE_BRACE && ch != '#') ch = add_then_next (b, ch); savchar(ch); add1_buffer(b, '\0'); ret = ck_strdup(get_buffer(b)); free_buffer(b); return ret; } /* Store a label (or label reference) created by a `:', `b', or `t' command so that the jump to/from the label can be backpatched after compilation is complete, or a reference created by a `{' to be backpatched when the corresponding `}' is found. */ static struct sed_label *setup_label P_((struct sed_label *, countT, char *, const struct error_info *)); static struct sed_label * setup_label(list, idx, name, err_info) struct sed_label *list; countT idx; char *name; const struct error_info *err_info; { struct sed_label *ret = OB_MALLOC(&obs, 1, struct sed_label); ret->v_index = idx; ret->name = name; if (err_info) MEMCPY(&ret->err_info, err_info, sizeof (ret->err_info)); ret->next = list; return ret; } static struct sed_label *release_label P_((struct sed_label *list_head)); static struct sed_label * release_label(list_head) struct sed_label *list_head; { struct sed_label *ret; if (!list_head) return NULL; ret = list_head->next; FREE(list_head->name); #if 0 /* We use obstacks */ FREE(list_head); #endif return ret; } static struct replacement *new_replacement P_((char *, size_t, enum replacement_types)); static struct replacement * new_replacement(text, length, type) char *text; size_t length; enum replacement_types type; { struct replacement *r = OB_MALLOC(&obs, 1, struct replacement); r->prefix = text; r->prefix_length = length; r->subst_id = -1; r->repl_type = type; /* r-> next = NULL; */ return r; } static void setup_replacement P_((struct subst *, const char *, size_t)); static void setup_replacement(sub, text, length) struct subst *sub; const char *text; size_t length; { char *base; char *p; char *text_end; enum replacement_types repl_type = REPL_ASIS, save_type = REPL_ASIS; struct replacement root; struct replacement *tail; sub->max_id = 0; base = MEMDUP(text, length, char); length = normalize_text(base, length, TEXT_REPLACEMENT); text_end = base + length; tail = &root; for (p=base; pnext = new_replacement(base, CAST(size_t)(p - base), repl_type); repl_type = save_type; /* Skip the backslash and look for a numeric back-reference, or a case-munging escape if not in POSIX mode: */ ++p; if (p < text_end && (posixicity != POSIXLY_BASIC || ISDIGIT (*p))) switch (*p) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': tail->subst_id = *p - '0'; if (sub->max_id < tail->subst_id) sub->max_id = tail->subst_id; break; case 'L': repl_type = REPL_LOWERCASE; save_type = REPL_LOWERCASE; break; case 'U': repl_type = REPL_UPPERCASE; save_type = REPL_UPPERCASE; break; case 'E': repl_type = REPL_ASIS; save_type = REPL_ASIS; break; case 'l': save_type = repl_type; repl_type |= REPL_LOWERCASE_FIRST; break; case 'u': save_type = repl_type; repl_type |= REPL_UPPERCASE_FIRST; break; default: p[-1] = *p; ++tail->prefix_length; } base = p + 1; } else if (*p == '&') { /* Preceding the ampersand may be some literal text: */ tail = tail->next = new_replacement(base, CAST(size_t)(p - base), repl_type); repl_type = save_type; tail->subst_id = 0; base = p + 1; } } /* There may be some trailing literal text: */ if (base < text_end) tail = tail->next = new_replacement(base, CAST(size_t)(text_end - base), repl_type); tail->next = NULL; sub->replacement = root.next; } static void read_text P_((struct text_buf *buf, int leadin_ch)); static void read_text(buf, leadin_ch) struct text_buf *buf; int leadin_ch; { int ch; /* Should we start afresh (as opposed to continue a partial text)? */ if (buf) { if (pending_text) free_buffer(pending_text); pending_text = init_buffer(); buf->text = NULL; buf->text_length = 0; old_text_buf = buf; } /* assert(old_text_buf != NULL); */ if (leadin_ch == EOF) return; if (leadin_ch != '\n') add1_buffer(pending_text, leadin_ch); ch = inchar(); while (ch != EOF && ch != '\n') { if (ch == '\\') { ch = inchar(); if (ch != EOF) add1_buffer (pending_text, '\\'); } if (ch == EOF) { add1_buffer (pending_text, '\n'); return; } ch = add_then_next (pending_text, ch); } add1_buffer(pending_text, '\n'); if (!buf) buf = old_text_buf; buf->text_length = normalize_text (get_buffer (pending_text), size_buffer (pending_text), TEXT_BUFFER); buf->text = MEMDUP(get_buffer(pending_text), buf->text_length, char); free_buffer(pending_text); pending_text = NULL; } /* Try to read an address for a sed command. If it succeeds, return non-zero and store the resulting address in `*addr'. If the input doesn't look like an address read nothing and return zero. */ static bool compile_address P_((struct addr *addr, int ch)); static bool compile_address(addr, ch) struct addr *addr; int ch; { addr->addr_type = ADDR_IS_NULL; addr->addr_step = 0; addr->addr_number = ~(countT)0; /* extremely unlikely to ever match */ addr->addr_regex = NULL; if (ch == '/' || ch == '\\') { int flags = 0; struct buffer *b; addr->addr_type = ADDR_IS_REGEX; if (ch == '\\') ch = inchar(); if ( !(b = match_slash(ch, true)) ) bad_prog(_(UNTERM_ADDR_RE)); for(;;) { ch = in_nonblank(); switch(ch) { case 'I': /* GNU extension */ flags |= REG_ICASE; break; #ifdef REG_PERL case 'S': /* GNU extension */ if (extended_regexp_flags & REG_PERL) flags |= REG_DOTALL; break; case 'X': /* GNU extension */ if (extended_regexp_flags & REG_PERL) flags |= REG_EXTENDED; break; #endif case 'M': /* GNU extension */ flags |= REG_NEWLINE; break; default: savchar (ch); addr->addr_regex = compile_regex (b, flags, 0); free_buffer(b); return true; } } } else if (ISDIGIT(ch)) { addr->addr_number = in_integer(ch); addr->addr_type = ADDR_IS_NUM; ch = in_nonblank(); if (ch != '~') { savchar(ch); } else { countT step = in_integer(in_nonblank()); if (step > 0) { addr->addr_step = step; addr->addr_type = ADDR_IS_NUM_MOD; } } } else if (ch == '+' || ch == '~') { addr->addr_step = in_integer(in_nonblank()); if (addr->addr_step==0) ; /* default to ADDR_IS_NULL; forces matching to stop on next line */ else if (ch == '+') addr->addr_type = ADDR_IS_STEP; else addr->addr_type = ADDR_IS_STEP_MOD; } else if (ch == '$') { addr->addr_type = ADDR_IS_LAST; } else return false; return true; } /* Read a program (or a subprogram within `{' `}' pairs) in and store the compiled form in `*vector'. Return a pointer to the new vector. */ static struct vector *compile_program P_((struct vector *)); static struct vector * compile_program(vector) struct vector *vector; { struct sed_cmd *cur_cmd; struct buffer *b; int ch; if (!vector) { vector = MALLOC(1, struct vector); vector->v = NULL; vector->v_allocated = 0; vector->v_length = 0; obstack_init (&obs); } if (pending_text) read_text(NULL, '\n'); for (;;) { struct addr a; while ((ch=inchar()) == ';' || ISSPACE(ch)) ; if (ch == EOF) break; cur_cmd = next_cmd_entry(&vector); if (compile_address(&a, ch)) { if (a.addr_type == ADDR_IS_STEP || a.addr_type == ADDR_IS_STEP_MOD) bad_prog(_(BAD_STEP)); cur_cmd->a1 = MEMDUP(&a, 1, struct addr); ch = in_nonblank(); if (ch == ',') { if (!compile_address(&a, in_nonblank())) bad_prog(_(BAD_COMMA)); cur_cmd->a2 = MEMDUP(&a, 1, struct addr); ch = in_nonblank(); } if (cur_cmd->a1->addr_type == ADDR_IS_NUM && cur_cmd->a1->addr_number == 0 && (!cur_cmd->a2 || cur_cmd->a2->addr_type != ADDR_IS_REGEX)) bad_prog(_(INVALID_LINE_0)); } if (ch == '!') { cur_cmd->addr_bang = true; ch = in_nonblank(); if (ch == '!') bad_prog(_(BAD_BANG)); } /* Do not accept extended commands in --posix mode. Also, a few commands only accept one address in that mode. */ if (posixicity == POSIXLY_BASIC) switch (ch) { case 'v': case 'L': case 'Q': case 'T': case 'R': case 'W': bad_command(ch); case 'a': case 'i': case 'l': case '=': case 'r': if (cur_cmd->a2) bad_prog(_(ONE_ADDR)); } cur_cmd->cmd = ch; switch (ch) { case '#': if (cur_cmd->a1) bad_prog(_(NO_SHARP_ADDR)); ch = inchar(); if (ch=='n' && first_script && cur_input.line < 2) if ( (prog.base && prog.cur==2+prog.base) || (prog.file && !prog.base && 2==ftell(prog.file))) no_default_output = true; while (ch != EOF && ch != '\n') ch = inchar(); continue; /* restart the for (;;) loop */ case 'v': /* This is an extension. Programs needing GNU sed might start * with a `v' command so that other seds will stop. * We compare the version and ignore POSIXLY_CORRECT. */ { char *version = read_label (); char *compared_version; compared_version = (*version == '\0') ? "4.0" : version; if (strverscmp (compared_version, SED_FEATURE_VERSION) > 0) bad_prog(_(ANCIENT_VERSION)); free (version); posixicity = POSIXLY_EXTENDED; } continue; case '{': blocks = setup_label(blocks, vector->v_length, NULL, &cur_input); cur_cmd->addr_bang = !cur_cmd->addr_bang; break; case '}': if (!blocks) bad_prog(_(EXCESS_CLOSE_BRACE)); if (cur_cmd->a1) bad_prog(_(NO_CLOSE_BRACE_ADDR)); ch = in_nonblank(); if (ch == CLOSE_BRACE || ch == '#') savchar(ch); else if (ch != EOF && ch != '\n' && ch != ';') bad_prog(_(EXCESS_JUNK)); vector->v[blocks->v_index].x.jump_index = vector->v_length; blocks = release_label(blocks); /* done with this entry */ break; case 'e': ch = in_nonblank(); if (ch == EOF || ch == '\n') { cur_cmd->x.cmd_txt.text_length = 0; break; } else goto read_text_to_slash; case 'a': case 'i': case 'c': ch = in_nonblank(); read_text_to_slash: if (ch == EOF) bad_prog(_(EXPECTED_SLASH)); if (ch == '\\') ch = inchar(); else { savchar(ch); ch = '\n'; } read_text(&cur_cmd->x.cmd_txt, ch); break; case ':': if (cur_cmd->a1) bad_prog(_(NO_COLON_ADDR)); labels = setup_label(labels, vector->v_length, read_label(), NULL); break; case 'T': case 'b': case 't': jumps = setup_label(jumps, vector->v_length, read_label(), NULL); break; case 'Q': case 'q': if (cur_cmd->a2) bad_prog(_(ONE_ADDR)); /* Fall through */ case 'L': case 'l': ch = in_nonblank(); if (ISDIGIT(ch)) { cur_cmd->x.int_arg = in_integer(ch); ch = in_nonblank(); } else cur_cmd->x.int_arg = -1; if (ch == CLOSE_BRACE || ch == '#') savchar(ch); else if (ch != EOF && ch != '\n' && ch != ';') bad_prog(_(EXCESS_JUNK)); break; case '=': case 'd': case 'D': case 'g': case 'G': case 'h': case 'H': case 'n': case 'N': case 'p': case 'P': case 'x': ch = in_nonblank(); if (ch == CLOSE_BRACE || ch == '#') savchar(ch); else if (ch != EOF && ch != '\n' && ch != ';') bad_prog(_(EXCESS_JUNK)); break; case 'r': b = read_filename(); cur_cmd->x.fname = ck_strdup(get_buffer(b)); free_buffer(b); break; case 'R': cur_cmd->x.fp = get_openfile(&file_read, "r", false)->fp; break; case 'W': case 'w': cur_cmd->x.outf = get_openfile(&file_write, "w", true); break; case 's': { struct buffer *b2; int flags; int slash; slash = inchar(); if ( !(b = match_slash(slash, true)) ) bad_prog(_(UNTERM_S_CMD)); if ( !(b2 = match_slash(slash, false)) ) bad_prog(_(UNTERM_S_CMD)); cur_cmd->x.cmd_subst = OB_MALLOC(&obs, 1, struct subst); setup_replacement(cur_cmd->x.cmd_subst, get_buffer(b2), size_buffer(b2)); free_buffer(b2); flags = mark_subst_opts(cur_cmd->x.cmd_subst); cur_cmd->x.cmd_subst->regx = compile_regex(b, flags, cur_cmd->x.cmd_subst->max_id + 1); free_buffer(b); } break; case 'y': { size_t len, dest_len; int slash; struct buffer *b2; char *src_buf, *dest_buf; slash = inchar(); if ( !(b = match_slash(slash, false)) ) bad_prog(_(UNTERM_Y_CMD)); src_buf = get_buffer(b); len = normalize_text(src_buf, size_buffer (b), TEXT_BUFFER); if ( !(b2 = match_slash(slash, false)) ) bad_prog(_(UNTERM_Y_CMD)); dest_buf = get_buffer(b2); dest_len = normalize_text(dest_buf, size_buffer (b2), TEXT_BUFFER); if (mb_cur_max > 1) { int i, j, idx, src_char_num; size_t *src_lens = MALLOC(len, size_t); char **trans_pairs; size_t mbclen; mbstate_t cur_stat; /* Enumerate how many character the source buffer has. */ memset(&cur_stat, 0, sizeof(mbstate_t)); for (i = 0, j = 0; i < len;) { mbclen = MBRLEN (src_buf + i, len - i, &cur_stat); /* An invalid sequence, or a truncated multibyte character. We treat it as a singlebyte character. */ if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0) mbclen = 1; src_lens[j++] = mbclen; i += mbclen; } src_char_num = j; memset(&cur_stat, 0, sizeof(mbstate_t)); idx = 0; /* trans_pairs = {src(0), dest(0), src(1), dest(1), ..., NULL} src(i) : pointer to i-th source character. dest(i) : pointer to i-th destination character. NULL : terminator */ trans_pairs = MALLOC(2 * src_char_num + 1, char*); cur_cmd->x.translatemb = trans_pairs; for (i = 0; i < src_char_num; i++) { if (idx >= dest_len) bad_prog(_(Y_CMD_LEN)); /* Set the i-th source character. */ trans_pairs[2 * i] = MALLOC(src_lens[i] + 1, char); strncpy(trans_pairs[2 * i], src_buf, src_lens[i]); trans_pairs[2 * i][src_lens[i]] = '\0'; src_buf += src_lens[i]; /* Forward to next character. */ /* Fetch the i-th destination character. */ mbclen = MBRLEN (dest_buf + idx, dest_len - idx, &cur_stat); /* An invalid sequence, or a truncated multibyte character. We treat it as a singlebyte character. */ if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0) mbclen = 1; /* Set the i-th destination character. */ trans_pairs[2 * i + 1] = MALLOC(mbclen + 1, char); strncpy(trans_pairs[2 * i + 1], dest_buf + idx, mbclen); trans_pairs[2 * i + 1][mbclen] = '\0'; idx += mbclen; /* Forward to next character. */ } trans_pairs[2 * i] = NULL; if (idx != dest_len) bad_prog(_(Y_CMD_LEN)); } else { char *translate = OB_MALLOC(&obs, YMAP_LENGTH, char); unsigned char *ustring = CAST(unsigned char *)src_buf; if (len != dest_len) bad_prog(_(Y_CMD_LEN)); for (len = 0; len < YMAP_LENGTH; len++) translate[len] = len; while (dest_len--) translate[(unsigned char)*ustring++] = *dest_buf++; cur_cmd->x.translate = translate; } if ((ch = in_nonblank()) != EOF && ch != '\n' && ch != ';') bad_prog(_(EXCESS_JUNK)); free_buffer(b); free_buffer(b2); } break; case EOF: bad_prog(_(NO_COMMAND)); /*NOTREACHED*/ default: bad_command (ch); /*NOTREACHED*/ } /* this is buried down here so that "continue" statements will miss it */ ++vector->v_length; } return vector; } /* deal with \X escapes */ size_t normalize_text(buf, len, buftype) char *buf; size_t len; enum text_types buftype; { const char *bufend = buf + len; char *p = buf; char *q = buf; /* This variable prevents normalizing text within bracket subexpressions when conforming to POSIX. If 0, we are not within a bracket expression. If -1, we are within a bracket expression but are not within [.FOO.], [=FOO=], or [:FOO:]. Otherwise, this is the '.', '=', or ':' respectively within these three types of subexpressions. */ int bracket_state = 0; int mbclen; mbstate_t cur_stat; memset(&cur_stat, 0, sizeof(mbstate_t)); while (p < bufend) { int c; mbclen = MBRLEN (p, bufend - p, &cur_stat); if (mbclen != 1) { /* An invalid sequence, or a truncated multibyte character. We treat it as a singlebyte character. */ if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0) mbclen = 1; memmove (q, p, mbclen); q += mbclen; p += mbclen; continue; } if (*p == '\\' && p+1 < bufend && bracket_state == 0) switch ( (c = *++p) ) { #if defined __STDC__ && __STDC__-0 case 'a': *q++ = '\a'; p++; continue; #else /* Not STDC; we'll just assume ASCII */ case 'a': *q++ = '\007'; p++; continue; #endif /* case 'b': *q++ = '\b'; p++; continue; --- conflicts with \b RE */ case 'f': *q++ = '\f'; p++; continue; case '\n': /*fall through */ case 'n': *q++ = '\n'; p++; continue; case 'r': *q++ = '\r'; p++; continue; case 't': *q++ = '\t'; p++; continue; case 'v': *q++ = '\v'; p++; continue; case 'd': /* decimal byte */ p = convert_number(q, p+1, bufend, 10, 3, 'd'); q++; continue; case 'x': /* hexadecimal byte */ p = convert_number(q, p+1, bufend, 16, 2, 'x'); q++; continue; #ifdef REG_PERL case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': if ((extended_regexp_flags & REG_PERL) && p+1 < bufend && p[1] >= '0' && p[1] <= '9') { p = convert_number(q, p, bufend, 8, 3, *p); q++; } else { /* we just pass the \ up one level for interpretation */ if (buftype != TEXT_BUFFER) *q++ = '\\'; } continue; case 'o': /* octal byte */ if (!(extended_regexp_flags & REG_PERL)) { p = convert_number(q, p+1, bufend, 8, 3, 'o'); q++; } else { /* we just pass the \ up one level for interpretation */ if (buftype != TEXT_BUFFER) *q++ = '\\'; } continue; #else case 'o': /* octal byte */ p = convert_number(q, p+1, bufend, 8, 3, 'o'); q++; continue; #endif case 'c': if (++p < bufend) { *q++ = toupper(*p) ^ 0x40; p++; continue; } else { /* we just pass the \ up one level for interpretation */ if (buftype != TEXT_BUFFER) *q++ = '\\'; continue; } default: /* we just pass the \ up one level for interpretation */ if (buftype != TEXT_BUFFER) *q++ = '\\'; break; } else if (buftype == TEXT_REGEX && posixicity != POSIXLY_EXTENDED) switch (*p) { case '[': if (!bracket_state) bracket_state = -1; break; case ':': case '.': case '=': if (bracket_state == -1 && p[-1] == '[') bracket_state = *p; break; case ']': if (bracket_state == 0) ; else if (bracket_state == -1) bracket_state = 0; else if (p[-2] != bracket_state && p[-1] == bracket_state) bracket_state = -1; break; } *q++ = *p++; } return (size_t)(q - buf); } /* `str' is a string (from the command line) that contains a sed command. Compile the command, and add it to the end of `cur_program'. */ struct vector * compile_string(cur_program, str, len) struct vector *cur_program; char *str; size_t len; { static countT string_expr_count = 0; struct vector *ret; prog.file = NULL; prog.base = CAST(unsigned char *)str; prog.cur = prog.base; prog.end = prog.cur + len; cur_input.line = 0; cur_input.name = NULL; cur_input.string_expr_count = ++string_expr_count; ret = compile_program(cur_program); prog.base = NULL; prog.cur = NULL; prog.end = NULL; first_script = false; return ret; } /* `cmdfile' is the name of a file containing sed commands. Read them in and add them to the end of `cur_program'. */ struct vector * compile_file(cur_program, cmdfile) struct vector *cur_program; const char *cmdfile; { size_t len; struct vector *ret; prog.file = stdin; if (cmdfile[0] != '-' || cmdfile[1] != '\0') prog.file = ck_fopen(cmdfile, "rt", true); cur_input.line = 1; cur_input.name = cmdfile; cur_input.string_expr_count = 0; ret = compile_program(cur_program); if (prog.file != stdin) ck_fclose(prog.file); prog.file = NULL; first_script = false; return ret; } /* Make any checks which require the whole program to have been read. In particular: this backpatches the jump targets. Any cleanup which can be done after these checks is done here also. */ void check_final_program(program) struct vector *program; { struct sed_label *go; struct sed_label *lbl; /* do all "{"s have a corresponding "}"? */ if (blocks) { /* update info for error reporting: */ MEMCPY(&cur_input, &blocks->err_info, sizeof (cur_input)); bad_prog(_(EXCESS_OPEN_BRACE)); } /* was the final command an unterminated a/c/i command? */ if (pending_text) { old_text_buf->text_length = size_buffer(pending_text); old_text_buf->text = MEMDUP(get_buffer(pending_text), old_text_buf->text_length, char); free_buffer(pending_text); pending_text = NULL; } for (go = jumps; go; go = release_label(go)) { for (lbl = labels; lbl; lbl = lbl->next) if (strcmp(lbl->name, go->name) == 0) break; if (lbl) { program->v[go->v_index].x.jump_index = lbl->v_index; } else { if (*go->name) panic(_("can't find label for jump to `%s'"), go->name); program->v[go->v_index].x.jump_index = program->v_length; } } jumps = NULL; for (lbl = labels; lbl; lbl = release_label(lbl)) ; labels = NULL; /* There is no longer a need to track file names: */ { struct output *p; for (p=file_read; p; p=p->link) if (p->name) { FREE(p->name); p->name = NULL; } for (p=file_write; p; p=p->link) if (p->name) { FREE(p->name); p->name = NULL; } } } /* Rewind all resources which were allocated in this module. */ void rewind_read_files() { struct output *p; for (p=file_read; p; p=p->link) if (p->fp) rewind(p->fp); } /* Release all resources which were allocated in this module. */ void finish_program(program) struct vector *program; { /* close all files... */ { struct output *p, *q; for (p=file_read; p; p=q) { if (p->fp) ck_fclose(p->fp); q = p->link; #if 0 /* We use obstacks. */ FREE(p); #endif } for (p=file_write; p; p=q) { if (p->fp) ck_fclose(p->fp); q = p->link; #if 0 /* We use obstacks. */ FREE(p); #endif } file_read = file_write = NULL; } #ifdef DEBUG_LEAKS obstack_free (&obs, NULL); #endif /*DEBUG_LEAKS*/ } kbuild-3686/src/oldsed/sed/sed.h0000664000175000017500000001644715053010104016455 0ustar locutuslocutus/* GNU SED, a batch stream editor. Copyright (C) 1989,90,91,92,93,94,95,98,99,2002,2003 Free Software Foundation, Inc. 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, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "basicdefs.h" #include "regex.h" #ifndef BOOTSTRAP #include #endif #include "utils.h" /* Struct vector is used to describe a compiled sed program. */ struct vector { struct sed_cmd *v; /* a dynamically allocated array */ size_t v_allocated; /* ... number slots allocated */ size_t v_length; /* ... number of slots in use */ }; /* This structure tracks files used by sed so that they may all be closed cleanly at normal program termination. A flag is kept that tells if a missing newline was encountered, so that it is added on the next line and the two lines are not concatenated. */ struct output { char *name; bool missing_newline; FILE *fp; struct output *link; }; struct text_buf { char *text; size_t text_length; }; struct regex { regex_t pattern; int flags; size_t sz; char re[1]; }; enum replacement_types { REPL_ASIS = 0, REPL_UPPERCASE = 1, REPL_LOWERCASE = 2, REPL_UPPERCASE_FIRST = 4, REPL_LOWERCASE_FIRST = 8, REPL_MODIFIERS = REPL_UPPERCASE_FIRST | REPL_LOWERCASE_FIRST, /* These are given to aid in debugging */ REPL_UPPERCASE_UPPERCASE = REPL_UPPERCASE_FIRST | REPL_UPPERCASE, REPL_UPPERCASE_LOWERCASE = REPL_UPPERCASE_FIRST | REPL_LOWERCASE, REPL_LOWERCASE_UPPERCASE = REPL_LOWERCASE_FIRST | REPL_UPPERCASE, REPL_LOWERCASE_LOWERCASE = REPL_LOWERCASE_FIRST | REPL_LOWERCASE }; enum text_types { TEXT_BUFFER, TEXT_REPLACEMENT, TEXT_REGEX }; enum posixicity_types { POSIXLY_EXTENDED, /* with GNU extensions */ POSIXLY_CORRECT, /* with POSIX-compatible GNU extensions */ POSIXLY_BASIC /* pedantically POSIX */ }; enum addr_state { RANGE_INACTIVE, /* never been active */ RANGE_ACTIVE, /* between first and second address */ RANGE_CLOSED /* like RANGE_INACTIVE, but range has ended once */ }; enum addr_types { ADDR_IS_NULL, /* null address */ ADDR_IS_REGEX, /* a.addr_regex is valid */ ADDR_IS_NUM, /* a.addr_number is valid */ ADDR_IS_NUM_MOD, /* a.addr_number is valid, addr_step is modulo */ ADDR_IS_STEP, /* address is +N (only valid for addr2) */ ADDR_IS_STEP_MOD, /* address is ~N (only valid for addr2) */ ADDR_IS_LAST /* address is $ */ }; struct addr { enum addr_types addr_type; countT addr_number; countT addr_step; struct regex *addr_regex; }; struct replacement { char *prefix; size_t prefix_length; int subst_id; enum replacement_types repl_type; struct replacement *next; }; struct subst { struct regex *regx; struct replacement *replacement; countT numb; /* if >0, only substitute for match number "numb" */ struct output *outf; /* 'w' option given */ unsigned global : 1; /* 'g' option given */ unsigned print : 2; /* 'p' option given (before/after eval) */ unsigned eval : 1; /* 'e' option given */ unsigned max_id : 4; /* maximum backreference on the RHS */ }; #ifdef REG_PERL /* This is the structure we store register match data in. See regex.texinfo for a full description of what registers match. */ struct re_registers { unsigned num_regs; regoff_t *start; regoff_t *end; }; #endif struct sed_cmd { struct addr *a1; /* save space: usually is NULL */ struct addr *a2; /* See description the enum, above. */ enum addr_state range_state; /* Non-zero if command is to be applied to non-matches. */ char addr_bang; /* The actual command character. */ char cmd; /* auxiliary data for various commands */ union { /* This structure is used for a, i, and c commands. */ struct text_buf cmd_txt; /* This is used for the l, q and Q commands. */ int int_arg; /* This is used for the {}, b, and t commands. */ countT jump_index; /* This is used for the r command. */ char *fname; /* This is used for the hairy s command. */ struct subst *cmd_subst; /* This is used for the w command. */ struct output *outf; /* This is used for the R command. */ FILE *fp; /* This is used for the y command. */ unsigned char *translate; char **translatemb; } x; }; void bad_prog P_((const char *why)); size_t normalize_text P_((char *text, size_t len, enum text_types buftype)); struct vector *compile_string P_((struct vector *, char *str, size_t len)); struct vector *compile_file P_((struct vector *, const char *cmdfile)); void check_final_program P_((struct vector *)); void rewind_read_files P_((void)); void finish_program P_((struct vector *)); struct regex *compile_regex P_((struct buffer *b, int flags, int needed_sub)); int match_regex P_((struct regex *regex, char *buf, size_t buflen, size_t buf_start_offset, struct re_registers *regarray, int regsize)); #ifdef DEBUG_LEAKS void release_regex P_((struct regex *)); #endif int process_files P_((struct vector *, char **argv)); int main P_((int, char **)); extern void fmt P_ ((const char *line, const char *line_end, int max_length, FILE *output_file)); extern int extended_regexp_flags; #ifndef CONFIG_WITHOUT_O_OPT /* The output file, defaults to stdout but can be overridden by the -o or --output option. main sets this to avoid problems. */ extern FILE *sed_stdout; #endif /* If set, fflush(stdout) on every line output. */ extern bool unbuffered_output; /* If set, don't write out the line unless explicitly told to. */ extern bool no_default_output; /* If set, reset line counts on every new file. */ extern bool separate_files; /* Do we need to be pedantically POSIX compliant? */ extern enum posixicity_types posixicity; /* How long should the `l' command's output line be? */ extern countT lcmd_out_line_len; /* How do we edit files in-place? (we don't if NULL) */ extern char *in_place_extension; /* Should we use EREs? */ extern bool use_extended_syntax_p; /* Declarations for multibyte character sets. */ extern int mb_cur_max; #ifdef HAVE_MBRTOWC #ifdef HAVE_BTOWC #define MBRTOWC(pwc, s, n, ps) \ (mb_cur_max == 1 ? \ (*(pwc) = btowc (*(unsigned char *) (s)), 1) : \ mbrtowc ((pwc), (s), (n), (ps))) #define WCRTOMB(s, wc, ps) \ (mb_cur_max == 1 ? \ (*(s) = wctob ((wint_t) (wc)), 1) : \ wcrtomb ((s), (wc), (ps))) #else #define MBRTOWC(pwc, s, n, ps) \ mbrtowc ((pwc), (s), (n), (ps)) #define WCRTOMB(s, wc, ps) \ wcrtomb ((s), (wc), (ps)) #endif #define MBRLEN(s, n, ps) \ (mb_cur_max == 1 ? 1 : mbrtowc (NULL, s, n, ps)) #define BRLEN(ch, ps) \ (mb_cur_max == 1 ? 1 : brlen (ch, ps)) #else #define MBRLEN(s, n, ps) 1 #define BRLEN(ch, ps) 1 #endif extern int brlen P_ ((int ch, mbstate_t *ps)); extern void initialize_mbcs P_ ((void)); kbuild-3686/src/oldsed/sed/fmt.c0000664000175000017500000003560215053010105016456 0ustar locutuslocutus/* `L' command implementation for GNU sed, based on GNU fmt 1.22. Copyright (C) 1994, 1995, 1996, 2002, 2003 Free Software Foundation, Inc. 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, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU fmt was written by Ross Paterson . */ #include "sed.h" #include #include #include #if HAVE_LIMITS_H # include #endif #ifndef UINT_MAX # define UINT_MAX ((unsigned int) ~(unsigned int) 0) #endif #ifndef INT_MAX # define INT_MAX ((int) (UINT_MAX >> 1)) #endif /* The following parameters represent the program's idea of what is "best". Adjust to taste, subject to the caveats given. */ /* Prefer lines to be LEEWAY % shorter than the maximum width, giving room for optimization. */ #define LEEWAY 7 /* Costs and bonuses are expressed as the equivalent departure from the optimal line length, multiplied by 10. e.g. assigning something a cost of 50 means that it is as bad as a line 5 characters too short or too long. The definition of SHORT_COST(n) should not be changed. However, EQUIV(n) may need tuning. */ typedef long COST; #define MAXCOST (~(((unsigned long) 1) << (8 * sizeof (COST) -1))) #define SQR(n) ((n) * (n)) #define EQUIV(n) SQR ((COST) (n)) /* Cost of a filled line n chars longer or shorter than best_width. */ #define SHORT_COST(n) EQUIV ((n) * 10) /* Cost of the difference between adjacent filled lines. */ #define RAGGED_COST(n) (SHORT_COST (n) / 2) /* Basic cost per line. */ #define LINE_COST EQUIV (70) /* Cost of breaking a line after the first word of a sentence, where the length of the word is N. */ #define WIDOW_COST(n) (EQUIV (200) / ((n) + 2)) /* Cost of breaking a line before the last word of a sentence, where the length of the word is N. */ #define ORPHAN_COST(n) (EQUIV (150) / ((n) + 2)) /* Bonus for breaking a line at the end of a sentence. */ #define SENTENCE_BONUS EQUIV (50) /* Cost of breaking a line after a period not marking end of a sentence. With the definition of sentence we are using (borrowed from emacs, see get_line()) such a break would then look like a sentence break. Hence we assign a very high cost -- it should be avoided unless things are really bad. */ #define NOBREAK_COST EQUIV (600) /* Bonus for breaking a line before open parenthesis. */ #define PAREN_BONUS EQUIV (40) /* Bonus for breaking a line after other punctuation. */ #define PUNCT_BONUS EQUIV(40) /* Credit for breaking a long paragraph one line later. */ #define LINE_CREDIT EQUIV(3) /* Size of paragraph buffer in words. Longer paragraphs are handled neatly (cf. flush_paragraph()), so there's little to gain by making these larger. */ #define MAXWORDS 1000 #define GETC() (parabuf == end_of_parabuf ? EOF : *parabuf++) /* Extra ctype(3)-style macros. */ #define isopen(c) (strchr ("([`'\"", (c)) != NULL) #define isclose(c) (strchr (")]'\"", (c)) != NULL) #define isperiod(c) (strchr (".?!", (c)) != NULL) /* Size of a tab stop, for expansion on input and re-introduction on output. */ #define TABWIDTH 8 /* Word descriptor structure. */ typedef struct Word WORD; struct Word { /* Static attributes determined during input. */ const char *text; /* the text of the word */ short length; /* length of this word */ short space; /* the size of the following space */ unsigned paren:1; /* starts with open paren */ unsigned period:1; /* ends in [.?!])* */ unsigned punct:1; /* ends in punctuation */ unsigned final:1; /* end of sentence */ /* The remaining fields are computed during the optimization. */ short line_length; /* length of the best line starting here */ COST best_cost; /* cost of best paragraph starting here */ WORD *next_break; /* break which achieves best_cost */ }; /* Forward declarations. */ static bool get_paragraph P_ ((void)); static int get_line P_ ((int c)); static int get_space P_ ((int c)); static int copy_rest P_ ((int c)); static bool same_para P_ ((int c)); static void flush_paragraph P_ ((void)); static void fmt_paragraph P_ ((void)); static void check_punctuation P_ ((WORD *w)); static COST base_cost P_ ((WORD *this)); static COST line_cost P_ ((WORD *next, int len)); static void put_paragraph P_ ((WORD *finish)); static void put_line P_ ((WORD *w, int indent)); static void put_word P_ ((WORD *w)); static void put_space P_ ((int space)); /* Option values. */ /* User-supplied maximum line width (default WIDTH). The only output lines longer than this will each comprise a single word. */ static int max_width; /* Space for the paragraph text. */ static const char *parabuf; /* End of space for the paragraph text. */ static const char *end_of_parabuf; /* The file on which we output */ static FILE *outfile; /* Values derived from the option values. */ /* The preferred width of text lines, set to LEEWAY % less than max_width. */ static int best_width; /* Dynamic variables. */ /* Start column of the character most recently read from the input file. */ static int in_column; /* Start column of the next character to be written to stdout. */ static int out_column; /* The words of a paragraph -- longer paragraphs are handled neatly (cf. flush_paragraph()). */ static WORD words[MAXWORDS]; /* A pointer into the above word array, indicating the first position after the last complete word. Sometimes it will point at an incomplete word. */ static WORD *word_limit; /* Indentation of the first line of the current paragraph. */ static int first_indent; /* Indentation of other lines of the current paragraph */ static int other_indent; /* The last character read from the input file. */ static int next_char; /* If nonzero, the length of the last line output in the current paragraph, used to charge for raggedness at the split point for long paragraphs chosen by fmt_paragraph(). */ static int last_line_length; /* read file F and send formatted output to stdout. */ void fmt (const char *line, const char *line_end, int max_length, FILE *output_file) { parabuf = line; end_of_parabuf = line_end; outfile = output_file; max_width = max_length; best_width = max_width * (201 - 2 * LEEWAY) / 200; in_column = 0; other_indent = 0; next_char = GETC(); while (get_paragraph ()) { fmt_paragraph (); put_paragraph (word_limit); } } /* Read a paragraph from input file F. A paragraph consists of a maximal number of non-blank (excluding any prefix) lines with the same indent. Return false if end-of-file was encountered before the start of a paragraph, else true. */ static bool get_paragraph () { register int c; last_line_length = 0; c = next_char; /* Scan (and copy) blank lines, and lines not introduced by the prefix. */ while (c == '\n' || c == EOF) { c = copy_rest (c); if (c == EOF) { next_char = EOF; return false; } putc ('\n', outfile); c = GETC(); } /* Got a suitable first line for a paragraph. */ first_indent = in_column; word_limit = words; c = get_line (c); /* Read rest of paragraph. */ other_indent = in_column; while (same_para (c) && in_column == other_indent) c = get_line (c); (word_limit - 1)->period = (word_limit - 1)->final = true; next_char = c; return true; } /* Copy to the output a blank line. In the latter, C is \n or EOF. Return the character (\n or EOF) ending the line. */ static int copy_rest (register int c) { out_column = 0; while (c != '\n' && c != EOF) { putc (c, outfile); c = GETC(); } return c; } /* Return true if a line whose first non-blank character after the prefix (if any) is C could belong to the current paragraph, otherwise false. */ static bool same_para (register int c) { return (c != '\n' && c != EOF); } /* Read a line from the input data given first non-blank character C after the prefix, and the following indent, and break it into words. A word is a maximal non-empty string of non-white characters. A word ending in [.?!]["')\]]* and followed by end-of-line or at least two spaces ends a sentence, as in emacs. Return the first non-blank character of the next line. */ static int get_line (register int c) { int start; register WORD *end_of_word; end_of_word = &words[MAXWORDS - 2]; do { /* for each word in a line */ /* Scan word. */ word_limit->text = parabuf - 1; do c = GETC(); while (c != EOF && !ISSPACE (c)); word_limit->length = parabuf - word_limit->text - (c != EOF); in_column += word_limit->length; check_punctuation (word_limit); /* Scan inter-word space. */ start = in_column; c = get_space (c); word_limit->space = in_column - start; word_limit->final = (c == EOF || (word_limit->period && (c == '\n' || word_limit->space > 1))); if (c == '\n' || c == EOF) word_limit->space = word_limit->final ? 2 : 1; if (word_limit == end_of_word) flush_paragraph (); word_limit++; if (c == EOF) { in_column = first_indent; return EOF; } } while (c != '\n'); in_column = 0; c = GETC(); return get_space (c); } /* Read blank characters from the input data, starting with C, and keeping in_column up-to-date. Return first non-blank character. */ static int get_space (register int c) { for (;;) { if (c == ' ') in_column++; else if (c == '\t') in_column = (in_column / TABWIDTH + 1) * TABWIDTH; else return c; c = GETC(); } } /* Set extra fields in word W describing any attached punctuation. */ static void check_punctuation (register WORD *w) { register const char *start, *finish; start = w->text; finish = start + (w->length - 1); w->paren = isopen (*start); w->punct = ISPUNCT (*finish); while (isclose (*finish) && finish > start) finish--; w->period = isperiod (*finish); } /* Flush part of the paragraph to make room. This function is called on hitting the limit on the number of words or characters. */ static void flush_paragraph (void) { WORD *split_point; register WORD *w; COST best_break; /* - format what you have so far as a paragraph, - find a low-cost line break near the end, - output to there, - make that the start of the paragraph. */ fmt_paragraph (); /* Choose a good split point. */ split_point = word_limit; best_break = MAXCOST; for (w = words->next_break; w != word_limit; w = w->next_break) { if (w->best_cost - w->next_break->best_cost < best_break) { split_point = w; best_break = w->best_cost - w->next_break->best_cost; } if (best_break <= MAXCOST - LINE_CREDIT) best_break += LINE_CREDIT; } put_paragraph (split_point); /* Copy words from split_point down to word -- we use memmove because the source and target may overlap. */ memmove ((char *) words, (char *) split_point, (word_limit - split_point + 1) * sizeof (WORD)); word_limit -= split_point - words; } /* Compute the optimal formatting for the whole paragraph by computing and remembering the optimal formatting for each suffix from the empty one to the whole paragraph. */ static void fmt_paragraph (void) { register WORD *start, *w; register int len; register COST wcost, best; int saved_length; word_limit->best_cost = 0; saved_length = word_limit->length; word_limit->length = max_width; /* sentinel */ for (start = word_limit - 1; start >= words; start--) { best = MAXCOST; len = start == words ? first_indent : other_indent; /* At least one word, however long, in the line. */ w = start; len += w->length; do { w++; /* Consider breaking before w. */ wcost = line_cost (w, len) + w->best_cost; if (start == words && last_line_length > 0) wcost += RAGGED_COST (len - last_line_length); if (wcost < best) { best = wcost; start->next_break = w; start->line_length = len; } len += (w - 1)->space + w->length; /* w > start >= words */ } while (len < max_width); start->best_cost = best + base_cost (start); } word_limit->length = saved_length; } /* Return the constant component of the cost of breaking before the word THIS. */ static COST base_cost (register WORD *this) { register COST cost; cost = LINE_COST; if (this > words) { if ((this - 1)->period) { if ((this - 1)->final) cost -= SENTENCE_BONUS; else cost += NOBREAK_COST; } else if ((this - 1)->punct) cost -= PUNCT_BONUS; else if (this > words + 1 && (this - 2)->final) cost += WIDOW_COST ((this - 1)->length); } if (this->paren) cost -= PAREN_BONUS; else if (this->final) cost += ORPHAN_COST (this->length); return cost; } /* Return the component of the cost of breaking before word NEXT that depends on LEN, the length of the line beginning there. */ static COST line_cost (register WORD *next, register int len) { register int n; register COST cost; if (next == word_limit) return 0; n = best_width - len; cost = SHORT_COST (n); if (next->next_break != word_limit) { n = len - next->line_length; cost += RAGGED_COST (n); } return cost; } /* Output to stdout a paragraph from word up to (but not including) FINISH, which must be in the next_break chain from word. */ static void put_paragraph (register WORD *finish) { register WORD *w; put_line (words, first_indent); for (w = words->next_break; w != finish; w = w->next_break) put_line (w, other_indent); } /* Output to stdout the line beginning with word W, beginning in column INDENT, including the prefix (if any). */ static void put_line (register WORD *w, int indent) { register WORD *endline; out_column = 0; put_space (indent); endline = w->next_break - 1; for (; w != endline; w++) { put_word (w); put_space (w->space); } put_word (w); last_line_length = out_column; putc ('\n', outfile); } /* Output to stdout the word W. */ static void put_word (register WORD *w) { register const char *s; register int n; s = w->text; for (n = w->length; n != 0; n--) putc (*s++, outfile); out_column += w->length; } /* Output to stdout SPACE spaces, or equivalent tabs. */ static void put_space (int space) { out_column += space; while (space--) putc (' ', outfile); } kbuild-3686/src/oldsed/sed/sed.c0000664000175000017500000003012215053010105016433 0ustar locutuslocutus#define COPYRIGHT_NOTICE "Copyright (C) 2003 Free Software Foundation, Inc." #define BUG_ADDRESS "bonzini@gnu.org" /* GNU SED, a batch stream editor. Copyright (C) 1989,90,91,92,93,94,95,98,99,2002,2003 Free Software Foundation, Inc. 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, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "sed.h" #include #ifdef HAVE_STRINGS_H # include #else # include #endif /*HAVE_STRINGS_H*/ #ifdef HAVE_MEMORY_H # include #endif #ifndef HAVE_STRCHR # define strchr index # define strrchr rindex #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #include "getopt.h" #ifndef BOOTSTRAP #ifndef HAVE_STDLIB_H extern char *getenv P_((const char *)); #endif #endif #ifndef HAVE_STRTOUL # define ATOI(x) atoi(x) #else # define ATOI(x) strtoul(x, NULL, 0) #endif int extended_regexp_flags = 0; #ifndef CONFIG_WITHOUT_O_OPT /* The output file, defaults to stdout but can be overridden by the -o or --output option. main sets this to avoid problems. */ FILE *sed_stdout = NULL; #endif /* If set, fflush(stdout) on every line output. */ bool unbuffered_output = false; /* If set, don't write out the line unless explicitly told to */ bool no_default_output = false; /* If set, reset line counts on every new file. */ bool separate_files = false; /* How do we edit files in-place? (we don't if NULL) */ char *in_place_extension = NULL; /* Do we need to be pedantically POSIX compliant? */ enum posixicity_types posixicity; /* How long should the `l' command's output line be? */ countT lcmd_out_line_len = 70; /* The complete compiled SED program that we are going to run: */ static struct vector *the_program = NULL; static void usage P_((int)); static void usage(status) int status; { FILE *out = status ? stderr : stdout; #ifdef REG_PERL #define PERL_HELP _(" -R, --regexp-perl\n use Perl 5's regular expressions syntax in the script.\n") #else #define PERL_HELP "" #endif fprintf(out, _("\ Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n\ \n"), myname); fprintf(out, _(" -n, --quiet, --silent\n\ suppress automatic printing of pattern space\n")); fprintf(out, _(" -e script, --expression=script\n\ add the script to the commands to be executed\n")); fprintf(out, _(" -f script-file, --file=script-file\n\ add the contents of script-file to the commands to be executed\n")); fprintf(out, _(" -i[SUFFIX], --in-place[=SUFFIX]\n\ edit files in place (makes backup if extension supplied)\n")); fprintf(out, _(" -l N, --line-length=N\n\ specify the desired line-wrap length for the `l' command\n")); #ifndef CONFIG_WITHOUT_O_LANG_C fprintf(out, _(" --codepage=N\n\ switches the locale to the given codepage, affecting how\n\ input files are treated and outputted\n\ windows only, ignored elsewhere\n")); # if _MSC_VER >= 1900 fprintf(out, _(" --utf8\n\ alias for --codepage=.UTF-8\n")); # endif fprintf(out, _(" --lang_c\n\ specify C locale\n")); #endif fprintf(out, _(" --posix\n\ disable all GNU extensions.\n")); #ifndef CONFIG_WITHOUT_O_OPT fprintf(out, _(" -o, --output=file, --append=file, --output-text=file,\n")); fprintf(out, _(" --output-binary=file, --append-text=file, append-binary=file\n\ use the specified file instead of stdout; the first\n\ three uses the default text/binary mode.\n")); #endif fprintf(out, _(" -r, --regexp-extended\n\ use extended regular expressions in the script.\n")); fprintf(out, "%s", PERL_HELP); fprintf(out, _(" -s, --separate\n\ consider files as separate rather than as a single continuous\n\ long stream.\n")); fprintf(out, _(" -u, --unbuffered\n\ load minimal amounts of data from the input files and flush\n\ the output buffers more often\n")); fprintf(out, _(" --help display this help and exit\n")); fprintf(out, _(" --version output version information and exit\n")); fprintf(out, _("\n\ If no -e, --expression, -f, or --file option is given, then the first\n\ non-option argument is taken as the sed script to interpret. All\n\ remaining arguments are names of input files; if no input files are\n\ specified, then the standard input is read.\n\ \n")); fprintf(out, _("E-mail bug reports to: %s .\n\ Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"), BUG_ADDRESS, PACKAGE); ck_fclose (NULL); exit (status); } int main(argc, argv) int argc; char **argv; { #ifdef REG_PERL # ifndef CONFIG_WITHOUT_O_OPT #define SHORTOPTS "snrRue:f:l:i::o:V:" # else #define SHORTOPTS "snrRue:f:l:i::V:" # endif #else # ifndef CONFIG_WITHOUT_O_OPT #define SHORTOPTS "snrue:f:l:i::o:V:" # else #define SHORTOPTS "snrue:f:l:i::V:" # endif #endif static struct option longopts[] = { {"regexp-extended", 0, NULL, 'r'}, #ifdef REG_PERL {"regexp-perl", 0, NULL, 'R'}, #endif {"expression", 1, NULL, 'e'}, {"file", 1, NULL, 'f'}, {"in-place", 2, NULL, 'i'}, {"line-length", 1, NULL, 'l'}, #ifndef CONFIG_WITHOUT_O_LANG_C {"lang_c", 0, NULL, 'L'}, {"codepage", 1, NULL, 305}, {"utf8", 0, NULL, 306}, #endif {"quiet", 0, NULL, 'n'}, {"posix", 0, NULL, 'p'}, {"silent", 0, NULL, 'n'}, {"separate", 0, NULL, 's'}, {"unbuffered", 0, NULL, 'u'}, #ifndef CONFIG_WITHOUT_O_OPT {"output", 1, NULL, 'o'}, {"output-binary", 1, NULL, 300}, {"output-text", 1, NULL, 301}, {"append", 1, NULL, 302}, {"append-binary", 1, NULL, 303}, {"append-text", 1, NULL, 304}, #endif {"version", 0, NULL, 'v'}, {"help", 0, NULL, 'h'}, {NULL, 0, NULL, 0} }; int opt; int return_code; const char *cols = getenv("COLS"); #ifdef KBUILD_OS_WINDOWS const char *locale; #endif initialize_main (&argc, &argv); #ifndef CONFIG_WITHOUT_O_OPT sed_stdout = stdout; #endif #if HAVE_SETLOCALE # ifdef KBUILD_OS_WINDOWS locale = setlocale (LC_ALL, ""); if (getenv("KMK_SED_CODEPAGE_DEBUG")) fprintf (stderr, "kmk_sed: codepage=%u locale=%s ACP=%u\n", get_crt_codepage(), locale, get_ansi_codepage()); # else setlocale (LC_ALL, ""); # endif #endif initialize_mbcs (); #if ENABLE_NLS /* Tell program which translations to use and where to find. */ bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); #endif if (getenv("POSIXLY_CORRECT") != NULL) posixicity = POSIXLY_CORRECT; else posixicity = POSIXLY_EXTENDED; /* If environment variable `COLS' is set, use its value for the baseline setting of `lcmd_out_line_len'. The "-1" is to avoid gratuitous auto-line-wrap on ttys. */ if (cols) { countT t = ATOI(cols); if (t > 1) lcmd_out_line_len = t-1; } myname = *argv; while ((opt = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != EOF) { switch (opt) { case 'n': no_default_output = true; break; case 'e': the_program = compile_string(the_program, optarg, strlen(optarg)); break; case 'f': the_program = compile_file(the_program, optarg); break; case 'i': separate_files = true; if (optarg == NULL) /* use no backups */ in_place_extension = ck_strdup ("*"); else if (strchr(optarg, '*') != NULL) in_place_extension = ck_strdup(optarg); else { in_place_extension = MALLOC (strlen(optarg) + 2, char); in_place_extension[0] = '*'; strcpy (in_place_extension + 1, optarg); } break; case 'l': lcmd_out_line_len = ATOI(optarg); break; #ifndef CONFIG_WITHOUT_O_LANG_C case 'L': # ifdef KBUILD_OS_WINDOWS locale = setlocale (LC_ALL, "C"); if (getenv("KMK_SED_CODEPAGE_DEBUG")) fprintf (stderr, "kmk_sed: codepage=%u locale=%s ACP=%u\n", get_crt_codepage(), locale, get_ansi_codepage()); # else setlocale (LC_ALL, "C"); # endif initialize_mbcs (); # if ENABLE_NLS bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); # endif break; case 306: /* --codepage=N */ # if _MSC_VER < 1900 break; /* does not work, so ignore */ # else optarg = ".UTF-8"; # endif /* fall through */ case 305: /* --codepage=N */ { # ifdef KBUILD_OS_WINDOWS char szTmp[64]; if (optarg[0] != '.') optarg = strncat (strcpy (szTmp, "."), optarg, sizeof (szTmp) - 1); locale = setlocale (LC_ALL, optarg); if (locale == NULL) fprintf (stderr, _("%s: warning: setlocale (LC_ALL, \"%s\") failed: %d\n"), myname, optarg, errno); else if (getenv("KMK_SED_CODEPAGE_DEBUG")) fprintf (stderr, "kmk_sed: codepage=%u locale=%s ACP=%u\n", get_crt_codepage(), locale, get_ansi_codepage()); initialize_mbcs(); # if ENABLE_NLS bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); # endif # endif break; } #endif #ifndef CONFIG_WITHOUT_O_OPT case 'o': sed_stdout = ck_fopen (optarg, "w", true /* fail on error */); break; case 300: sed_stdout = ck_fopen (optarg, "wb", true /* fail on error */); break; case 301: sed_stdout = ck_fopen (optarg, "wt", true /* fail on error */); break; case 302: sed_stdout = ck_fopen (optarg, "a", true /* fail on error */); break; case 303: sed_stdout = ck_fopen (optarg, "ab", true /* fail on error */); break; case 304: sed_stdout = ck_fopen (optarg, "at", true /* fail on error */); break; #endif case 'p': posixicity = POSIXLY_BASIC; break; case 'r': if (extended_regexp_flags) usage(4); extended_regexp_flags = REG_EXTENDED; break; #ifdef REG_PERL case 'R': if (extended_regexp_flags) usage(4); extended_regexp_flags = REG_PERL; break; #endif case 's': separate_files = true; break; case 'u': unbuffered_output = true; break; case 'v': #ifdef KBUILD_VERSION_MAJOR fprintf(stdout, _("kmk_sed - kBuild version %d.%d.%d\n" "\n" "Based on "), KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH); #endif #ifdef REG_PERL fprintf(stdout, _("super-sed version %s\n"), VERSION); fprintf(stdout, _("based on GNU sed version %s\n\n"), SED_FEATURE_VERSION); #else fprintf(stdout, _("GNU sed version %s\n"), VERSION); #endif fprintf(stdout, _("%s\n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n\ to the extent permitted by law.\n\ "), COPYRIGHT_NOTICE); ck_fclose (NULL); exit (0); case 'h': usage(0); break; default: usage(4); } } if (!the_program) { if (optind < argc) { char *arg = argv[optind++]; the_program = compile_string(the_program, arg, strlen(arg)); } else usage(4); } check_final_program(the_program); return_code = process_files(the_program, argv+optind); finish_program(the_program); ck_fclose(NULL); return return_code; } #ifdef __HAIKU__ /* mbrtowc is busted, just stub it and pray the input won't ever acutally be multibyte... */ size_t mbrtowc(wchar_t *pwc, const char *pch, size_t n, mbstate_t *ps) { if (!n) return 0; if (pwc) *pwc = *pch; return 1; } #endif kbuild-3686/src/oldsed/ChangeLog0000664000175000017500000027733515053010105016536 0ustar locutuslocutus2006-02-03 Paolo Bonzini * sed/compile.c (compile_program) : Pass false to match_slash. 2005-09-07 Paolo Bonzini * lib/regcomp.c: Update from upstream. * lib/regex.c: Update from upstream. * lib/regex_.h: Update from upstream. * lib/regex_internal.c: Update from upstream. * lib/regex_internal.h: Update from upstream. * lib/regexec.c: Update from upstream. 2005-08-30 Paolo Bonzini * sed/execute.c (reset_addresses): Never activate ADDR_IS_NUM_MOD addresses. * testsuite/modulo.good, testsuite/modulo.inp, testsuite/modulo.sed: New. * testsuite/Makefile.tests: Add new testcase. * testsuite/Makefile.am: Add new testcase. * testsuite/Makefile.in: Regenerate. 2005-05-18 Maciej W. Rozycki * configure.ac: Use a cache variable for the libcP test. * configure: Regenerate. 2005-05-16 Eero Hakkinen * sed/compile.c (snarf_char_class): Fix handling of [^]xyz]. 2005-04-04 Paolo Bonzini * sed/execute.c (process_files): Do not add a default command-line in in-place editing mode. 2005-02-10 Paolo Bonzini * testsuite/Makefile.tests: Add new testcase. * testsuite/Makefile.am: Add new testcase. * testsuite/Makefile.in: Regenerate. * testsuite/appquit.good, testsuite/appquit.inp, testsuite/appquit.sed: New testcase. * testsuite/readin.sed: Quit after the last r command. * testsuite/readin.good: Adjust. * sed/execute.c (execute_program): Dump the results of the a/r/R commands just before quitting. 2005-02-10 Paolo Bonzini * sed/regexp.c: Fix off-by-one error in the "invalid reference to subexpression" message. Debian bug 294339. 2005-02-08 Paolo Bonzini * lib/obstack.h: include config.h. 2005-02-01 Paolo Bonzini * doc/Makefile.am: Don't enable MAKEINFO_HTML and TEXI2HTML_HTML rules unless BUILD_HTML. 2005-01-25 Paolo Bonzini * sed/regexp.c: Fix building on GCC 2.95 and earlier. 2004-12-26 Paolo Bonzini Do not use leftmost-longest matching for addresses. * NEWS: Add a note about this. * testsuite/recall2.good, testsuite/recall2.inp, testsuite/recall2.sed: New test. * testsuite/Makefile.am, testsuite/Makefile.tests: Add the recall2 test. * sed/sed.h (struct regex): New. (struct addr, struct subst, compile_regex, match_regex, release_regex): Use it instead of regex_t. * sed/compile.c (compile_program): Update for new meaning of the third parameter of compile_regex. * sed/execute.c (do_subst): Pass less conservative value to the regsize parameter of match_regex. * sed/regexp.c (compile_regex_1): New, extracted out of compile_regex. The third parameter, needed_sub, now includes \0 (so 10 means that \0 .. \9 are needed). Pass RE_NO_SUB if needed_sub is zero. (compile_regex): Accept a struct regex instead of a regex_t. Save the regular expression's text. (match_regex): Accept a struct regex instead of a regex_t. Recompile the pattern if it was compiled with RE_NO_SUB. (release_regex): Accept a struct regex instead of a regex_t. * doc/Makefile.am: Generate sed.texi correctly when building outside srcdir. 2004-12-26 Paolo Bonzini * BUGS: Add section about [a-z] matching uppercase characters, and other locale issues. * doc/sed-in.texi [!PERL]: Likewise. 2004-11-15 Paolo Bonzini * sed/execute.c (str_append_modified): Copy the first character when using \l or \u in a multi-byte configuration. Use WCRTOMB instead of wcrtomb. * sed/sed.h (WCRTOMB): New. 2004-11-11 Paolo Bonzini * tst-rxspecer.c: Do not mix instructions and declarations. * basicdefs.h: Include locale.h before #defining gettext, to avoid breakage under Solaris. * sed/sed.c: do not include locale.h. 2004-11-03 Paolo Bonzini * bug-regex11.c: Improve portability. * bug-regex12.c: Improve portability. * bug-regex13.c: Improve portability. * bug-regex14.c: Improve portability. * bug-regex21.c: Improve portability. * bug-regex9.c: Improve portability. * tst-boost.c: Improve portability. * tst-pcre.c: Improve portability. * tst-regex.c: Improve portability. * tst-rxspencer.c: Improve portability. 2004-10-08 Paolo Bonzini * lib/utils.c (utils_id_s): Renamed to open_files. (struct id): Renamed to struct open_file. 2004-10-08 Jakub Jelinek * testsuite/Makefile.tests (bug-regex*, run-tests, run-ptests): Use $(SED). (version): Likewise; prepend $(SED) invocation with $(SEDENV). 2004-08-16 Paolo Bonzini *** Version 4.1.2 released. 2004-08-06 Paolo Bonzini * sed/compile.c (bad_command): Fix off-by-one error. (snarf_char_class): Fix problem with [.....[] (i.e. last char in class is a bracket. 2004-06-30 Paolo Bonzini *** Version 4.1.1 released. 2004-06-29 Paolo Bonzini * sed/compile.c (mark_subst_opts): Return int. * sed/execute.c (open_next_file): Fix uninitialized variable. 2004-06-10 Paolo Bonzini *** Version 4.1 released. 2004-03-25 Paolo Bonzini * lib/obstack.h: Get current version. 2004-03-13 Paolo Bonzini Exit as soon as possible on an I/O error, and with a better error message. * lib/utils.c (ck_mkstemp, ck_rename, ck_getline): New functions. Save temporary files into utils_id_s. (struct id): Add a field named temp. (ck_fopen): Init the new temp field of struct id. (panic): Unlink temporary files before exiting. * sed/execute.c (read_file_line): Use ck_getline. (closedown): Use ck_rename. (open_next_file): Use ck_mkstemp. 2004-01-20 Paolo Bonzini * sed/sed.h (enum addr_state): New definition. (enum addr_type): Remove ADDR_IS_NUM2. (struct sed_cmd): Replace a1_matched with range_state. * sed/compile.c (next_cmd_entry): Use range_state. (compile_program): Death to ADDR_IS_NUM2. Compile N,Mp as Np if N>=M. * sed/execute.c (match_address_p): Rewritten. Handle ADDR_IS_NUM here. (match_an_address_p): Suit to new match_address_p. (execute_program): Adjust to use range_state in `c'. Handle addr_bang here. (reset_addresses): Use range_state. (struct input): New field "reset_at_next_file". (read_pattern_space): Use it instead of "separate_files". (process_files): Initialize it. 2004-01-17 Paolo Bonzini * sed/sed.h: Do not include wchar.h and wctype.h, and do not include the alloca stuff. * basicdefs.h: Move all that here. 2004-01-15 Paolo Bonzini * sed/regexp.c [REG_PERL]: Use REG_STARTEND instead of regexec2. 2004-01-09 Paul Eggert Paolo Bonzini * sed/sed.h (posixicity): New variable, replaces POSIXLY_CORRECT. * sed/sed.c (main): Set it. * sed/compile.c: Use it instead of POSIXLY_CORRECT. * sed/execute.c: Use it instead of POSIXLY_CORRECT. * doc/sed-in.texi: Document it and --posix. 2004-01-05 Paul Eggert Paolo Bonzini * NEWS: Fix [\n] to match either backslash or n in POSIXLY_CORRECT mode. * doc/sed-in.texi: Document this. Also, document regular expressions a bit better overall, using terminology that's more similar to POSIX. * sed/sed.h (enum text_types): New definition. * sed/compile.c (normalize_text): Replace final parameter with one of type normalize_text. If TEXT_REGEX and in POSIXLY_CORRECT mode, grok character classes without replacing \n inside them. 2004-01-03 Paolo Bonzini * sed/execute.c (execute_program): print final line after executing N, if not POSIXLY_CORRECT. 2003-12-28 Paolo Bonzini * sed/compile.c: fix "\\\n" in RHS of s command. Reported by Mike Castle. * testsuite/bkslashes.inp, testsuite/bkslashes.good, testsuite/bkslashes.sed: New files. * testsuite/Makefile.am, testsuite/Makefile.tests: Add the bkslashes test. 2003-12-16 Paolo Bonzini *** Version 4.0b released. * sed/mbcs.c: New file. * sed/sed.h: Declare macros for mbcs.c. * sed/compile.c: Use them. (brlen): Moved to mbcs.c. * sed/execute.c: Use them. * sed/sed.c: call initialize_mbcs (). 2003-12-14 Paolo Bonzini * sed/regex.c (match_regex): fix memory leak. 2003-11-27 Paolo Bonzini * sed/execute.c (reset_addresses): leave addresses 0 and 0~STEP enabled. 2003-11-15 Jakub Jelinek * sed/regex.c: Use fastmap. 2003-09-21 Paolo Bonzini *** Version 4.0a released. * sed/execute.c (struct line): Add mbstate field. (str_append): Keep mbstate up to date. (str_append_modified): Likewise, and use towupper/towlower. (line_init): Initialize mbstate. (line_copy): Copy mbstate. (line_append): Copy mbstate. 2003-07-15 Stepan Kasal Paolo Bonzini Change the way we treat lines which are not terminated by a newline. Such lines are printed without the terminating newline (as before) but as soon as more text is sent to the same output stream, the missing newline is printed, so that the two lines don't concatenate. * sed/execute.c (output_file): Is now struct output; users adjusted to access the fp field, call output_missing_newline before, and call flush_output afterwards. (read_file_line): Set line.chomped FALSE each time we encounter a line without the newline terminator, no matter whether this is the last input file or not, and no matter whether we are in POSIXLY_CORRECT mode or not. (output_missing_newline): New function which prints the suppressed newline, if necessary. (flush_output): New function for a common pattern. (output_line): Use struct output, set its flag accordingly. (dump_append_queue): Use `ck_fwrite' instead of output_line. (do_list): Flush the output stream at the end. (closedown): The code ``if(separate_files) rewind_read_files();'' (read_pattern_space): ... has been moved here. (process_files): Don't do the default `p' at the end, ... (execute_program): ... as this function is now responsible for it; add the code to the end of the function and to the command `q'; the commands `d', `D' and `Q' thus no longer have to forge an empty line. (execute_program): Commands `c' and `i' no longer call the function output_line with chomped==FALSE; instead, they chomp the text and call the function with chomped==TRUE. (execute_program): Command `e' no longer uses output_line; it calls ck_fwrite directly. Commands `e', `L' and `=' flush the output stream at the end. * sed/compile.c (special_files): Use `struct output' instead of the file name. (get_openfile): ... special files are no longer copied to file_read or file_write. (fp_list): Move to sed.h (users adjusted) and rename as... * sed/sed.h (struct output): ...this. New flag missing_newline associated to the output stream. (struct sed_cmd, struct subst): Use `struct output *' instead of mere `FILE *'; adjust compile.c and execute.c. * testsuite/noeolw.sed, testsuite/noeolw.good, testsuite/noeolw.1good, testsuite/noeolw.2good: New tests 2003-07-15 Stepan Kasal * lib/utils.h, sed/sed.h: #include "basicdefs.h", don't include it from various *.c files. * sed/regex.c: Don't include regex.h as it's included via sed.h. 2003-06-11 Paolo Bonzini * lib/getline.c: Don't realloc with first param = NULL. 2003-05-07 Paolo Bonzini * sed/execute.c: Make treatment of ADDR_IS_NUM_MOD simpler, and fix bugs in 0~5,+1 * sed/compile.c: Complain about addresses like 0 and 0,3 which are sources of misunderstandings. Reported by Akim Demaille 2003-03-25 Paolo Bonzini *** Version 4.0.7 released * sed/execute.c (append_replacement): Extract from do_subst (do_subst): Don't update count when a match was skipped. * testsuite/xbxcx3.good, testsuite/xbxcx3.sed, testsuite/xbxcx3.inp: Regression tests 2003-03-23 Paolo Bonzini * sed/execute.c (do_subst): Fix several bugs with numbered matches * testsuite/numsub2.good, testsuite/numsub2.inp, testsuite/numsub2.sed, testsuite/numsub3.good, testsuite/numsub3.inp, testsuite/numsub3.sed, testsuite/numsub4.good, testsuite/numsub4.inp, testsuite/numsub4.sed, testsuite/numsub5.good, testsuite/numsub5.inp, testsuite/numsub5.sed: regression tests for the bugs 2003-03-15 Paolo Bonzini *** Version 4.0.6 released * lib/mkstemp.c: Include sys/file.h if available for the benefit of Ultrix 2003-03-14 Paolo Bonzini * sed/compile.c: Replace flagT with bool * sed/execute.c: Replace flagT with bool * sed/fmt.c: Replace flagT with bool * sed/sed.c: Replace flagT with bool * sed/regex.c: Replace flagT with bool 2003-03-13 Paolo Bonzini * sed/compile.c (compile_program): Understand parameter of `v'. * sed/sed.c (usage): Split help message into multiple strings (main): Don't understand -h and -V 2003-03-12 Paolo Bonzini * sed/compile.c (match_slash, snarf_char_class): More multibyte character support (brlen): New function * testsuite/classes.good, testsuite/classes.inp, testsuite/classes.sed: New files 2003-03-10 Paolo Bonzini * sed/compile.c (match_slash): Strip the \ in front of slashes (so that the matcher sees x/ for s/x\///). Don't match / and [ unless at the start of a character. 2003-02-18 Paolo Bonzini * sed/regex.c (compile_regex): // matches the last regular expression even in POSIXLY_CORRECT mode. * sed/compile.c (normalize_text): Treat multibyte character sets correctly (read_text): Don't swallow backslash sequences, run text through normalize_text (compile_program): Ditto for y command * sed/compile.c (normalize_text): Add parameter that says whether the text will be processed further to remove more backslash escapes. Callers adjusted (match_slash): Remove same parameter from here. Callers adjusted. 2003-02-15 Paolo Bonzini * sed/sed.h: Fix prototype for match_regex, declare re_registers if REG_PERL * sed/execute.c (do_subst): Use re_registers * sed/regex.c (copy_regs): New function [REG_PERL]: Use re_registers [!REG_PERL]: Avoid using internal entry points, support pre-glibc 2.3 regex for the sake of --without-included-regex. 2003-01-04 Paolo Bonzini * sed/sed.h: Move some stuff from here... * sed/basicdefs.h: ...to here * lib/utils.c (ck_fopen): Add FAIL parameter * lib/utils.h: Adjust parameter * sed/compile.c, sed/execute.c, sed/sed.c: Adjust callers * sed/basicdefs.h: Add TRUE/FALSE * sed/compile.c, sed/execute.c, sed/sed.c: Use them * sed/fmt.c: Do not redefine them 2003-01-02 Paolo Bonzini * sed/sed.c: Bump copyright year 2002-12-24 Paolo Bonzini * sed/sed.c: Use bindtextdomain * sed/basicdefs.h [__EMX__]: Define initialize_main * lib/getline.c [__EMX__]: Strip trailing CR * sed/regex.c: Don't use N_ on the lines that define error messages, some compilers complain. 2002-12-18 Paolo Bonzini *** Version 4.0.5 released * sed/compile.c: Don't use N_ on the lines that define error messages, some compilers complain. 2002-12-16 Paolo Bonzini * sed/compile.c: Improvements to some error messages; `a', `i', `l', `L', `r' accept two addresses except in POSIXLY_CORRECT mode. 2002-12-14 Paolo Bonzini * lib/regex_internal.c: Fix problem on non-glibc systems, from Jakub Jelinek * lib/regex.c (RE_ENABLE_I18N): Conditionalize on HAVE_MBRTOWC and HAVE_WCRTOMB. * lib/getline.c: Fix compilation on non-glibc system * lib/snprintf.c: Fix compilation on non-glibc system * lib/basicdefs.h [P_]: Make more portable 2002-12-12 Paolo Bonzini *** Version 4.0.4 released 2002-11-21 Paolo Bonzini *** Version 4.0.3 released 2002-11-19 Paolo Bonzini *** Version 4.0.2 released 2002-11-05 Paolo Bonzini *** Version 4.0.1 released 2002-10-23 Paolo Bonzini *** Version 4.0 released 2002-10-28 Paolo Bonzini * lib/utils.c: Don't fail for EBADF in fflush * src/sed.c: the_program is now a global 2002-10-19 Paolo Bonzini * src/sed.c: Print GNU sed in --version for GNU sed, and super-sed for super-sed (thanks to Bruno Haible) 2002-10-17 Paolo Bonzini *** Version 3.96 released 2002-10-16 Isamu Hasegawa * src/execute.c (execute_program): Multibyte 'y' * src/compile.c (compile_program): Likewise * src/sed.h: Likewise 2002-10-08 Paolo Bonzini *** Version 3.95 released 2002-07-15 Paolo Bonzini * src/sed.h: rfile --> fname, wfile --> fp * src/compile.c (compile_command): Parse 'R' like 'w', use separate lists for file read and file write * src/compile.c (get_openfile): New name of get_writefile * src/compile.c (rewind_read_files): New function * src/sed.h: Declared here * src/execute.c (closedown): And called here * src/execute.c (append_queue): Added 'free' field * src/execute.c (execute_program): Implement 'R' 2002-06-09 Paolo Bonzini * src/execute.c (do_subst): Replaced flag was set on every regexp match, while the first matches should not set it for s///N. 2002-06-08 Paolo Bonzini * src/compile.c (compile_file): Open the script in text mode * lib/utils.c (utils_fp_name): Shorten the output * lib/utils.c (ck_fread, ck_fwrite, ck_fflush): Clearerr after printing an error. * lib/utils.c (ck_fclose): Work on stdout as well if stream == NULL and flush before closing to check for errors 2002-05-30 Paolo Bonzini * src/compile.c (compile_program): Implement W * src/execute.c (execute_program): Likewise 2002-04-23 Paolo Bonzini * src/sed.c (usage, main): Parse -s * src/sed.h (separate_files): New variable * src/execute.c (separate_files): New variable * src/execute.c (reset_addresses): New function to make range addresses work separately on each file when using in-place editing * src/execute.c (execute_program): The `n' and `N' use test_eof so that the script restarts at end of file, not at end of input * src/execute.c (test_dollar_EOF): Make $ work separately on each file when using -s; renamed to test_eof 2002-02-28 Paolo Bonzini * src/sed.h (struct sed_cmd): exit_status -> int_arg * src/compile.c: Likewise * src/execute.c: Likewise * src/compile.c (compile_command): Parse `l' like `q' and `Q'; default for int_arg is -1 * src/execute.c (do_list): New argument, used instead of lcmd_out_line_len (execute_program): Interpret int_arg for the `l' command; return 0 for `q' and `Q' if int_arg is -1 * src/fmt.c: New file, looted from GNU textutils * src/compile.c: Parse `L' * src/execute.c: Execute `L' 2002-02-14 Paolo Bonzini * src/execute.c (str_append_modified): Fixed a stupid bug (stop condition was *start == *end, meant to be start == end) 2002-02-05 Paolo Bonzini * lib/utils.c: Added directory parameter to temp_file_template * lib/utils.h: Adjusted * src/execute.c: Adjusted 2002-01-29 Paolo Bonzini * src/compile.c (mark_subst_opts): Signal an error if there are multiple g or p options * src/compile.c (compile_program): Raise appropriate error if second string in y command is longer than first (used to be "excess junk after command") 2001-12-31 Paolo Bonzini * lib/getline.c: Strip the terminating \r under Windows or MS-DOS. * testsuite/xemacs.sed, testsuite/xemacs.inp, testsuite/xemacs.good: Submitted by John Fremlin (john@fremlin.de) 2001-12-27 Paolo Bonzini * sed/execute.c (do_subst): Flags in optimized s/^xx/ commands were discarded (see the change below) 2001-12-19 Paolo Bonzini * sed/execute.c (resize_line): Limit inactive space to two thirds of a buffer * sed/execute.c (line_init): Initialize buf->active * sed/execute.c (str_append, str_append_modified, line_copy, do_list, do_subst, execute_program, process_files): Operate on active space * sed/execute.c (do_subst): Optimize s/^xx// by making a part of the buffer inactive and s/xx$// by truncating it. * sed/execute.c (execute_program): Optimize D by making a part of the buffer inactive * testsuite/uniq.sed, testsuite/uniq.inp, testsuite/uniq.good: added to test P and D commands. * testsuite/fasts.sed, testsuite/fasts.inp, testsuite/fasts.good: added to test the new optimization done on the `s' command. 2001-12-17 Paolo Bonzini * testsuite/dc.inp: Also compute Easter of 2002 :-) * sed/execute.c [!HAVE_FCHMOD]: Don't chmod the output file if working in-place 2001-11-12 Paolo Bonzini * sed/sed.h (struct sed_cmd): a1 is a pointer too * sed/compile.c: Likewise * sed/execute.c: Likewise * sed/compile.c: Use obstacks * sed/execute.c: Likewise 2001-11-09 Paolo Bonzini * sed/compile.c (mark_subst_opts): Parse option `e', preserve two occurrences of the `e' and `p' options. * sed/execute.c (do_subst) [HAVE_POPEN]: Interpret option `e' (evaluate, like Perl's but uses Bourne shell). * sed/sed.h (struct subst): Add an `eval' flag. * sed/compile.c (compile_program): Compile command `e' like `c'. * sed/execute.c (execute_program): Execute command `e'. 2001-09-25 Paolo Bonzini * sed/compile.c (get_writefile) [!POSIXLY_CORRECT]: support /dev/stdout * sed/execute.c (open_next_file, closedown): Support in-place editing * sed/execute.c (backup_file_name): New function to support in-place editing * sed/main.c (usage, main): Parse -i. * sed/utils.c: Moved to lib directory * lib/utils.c (temp_file_template): New function. * sed/utils.h: Declared temp_file_template. 2001-09-05 Paolo Bonzini * sed/execute.c (do_subst): `baaac', if passed through s/a*/x/g, gave `xbxxcx' rather than `xbxcx' (because an empty string matched before the `c'. Fixed. * sed/execute.c: Removed mmap support, I/O is done using getline (slower but more bug-proof). * sed/utils.c: Likewise. * lib/getline.c: New file 2001-03-22 Paolo Bonzini * sed/compile.c (normalize_text) [POSIXLY_CORRECT]: Enable escapes in modes other than BRE. 2001-03-21 Paolo Bonzini * sed/compile.c (normalize_text): Support \XXX in Perl mode, \oXXX in non-Perl mode. 2001-03-18 Paolo Bonzini * sed/compile.c (compile_program): Fixed missing break when compiling 'q' and 'Q'. * sed/compile.c (check_final_program): Removed now spurious call to compile_regex * sed/regex.c (compile_regex): Don't track the last compiled regex * sed/regex.c (execute_regex): Track here the last compiled regex 2001-03-02 Paolo Bonzini * sed/compile.c (setup_replacement): Support \[lLuUE] like Perl and vi. * sed/compile.c (new_replacement): Accept new parameter to support \[lLUuE]. * sed/sed.h (enum replacement_types): New declaration * sed/execute.c (do_subst): Use new function str_append_modified to apply the changes required via \[lLUuE]. * sed/execute.c (str_append_modified): New function 2001-03-02 Paolo Bonzini * sed/compile.c (setup_replacement): Count the number of backreferences that the RHS needs * sed/regex.c (compile_regex): Check if there is a sufficient number of backreferences (new argument needed_sub replaces nosub) * sed/compile.c (compile_address, compile_program, check_final_program): Callers adjusted 2001-02-08 Paolo Bonzini * sed/compile.c (compile_program): Added `Q' (quit without output) * sed/execute.c (execute_program): Ditto * sed/compile.c (compile_program): Fill in exit_status for `q' and `Q' * sed/execute.c (execute_program): Return -1 for `go on', 0..255 to set the exit status * sed/execute.c (process_files): Interpret new convention for execute_program, return sed's exit code * sed/sed.c (main): Return process_files's exit code * sed/sed.h (struct sed_cmd): Declare exit_status 2001-01-07 Paolo Bonzini * sed/compile.c (compile_program): Added `T' (branch if failed) * sed/execute.c (shrink_program, execute_program): Ditto 2001-01-04 Paolo Bonzini * testsuite/Makefile.am: Use automake's implementation of `make check'. Removed the test targets * testsuite/Makefile.tests: Moved the test targets here (new file). * testsuite/runtest: New file * testsuite/Makefile.tests: `khadafy' test uses EREs. * testsuite/spencer.inp: Removed the ^* test * testsuite/spencer.sh: Don't rely on awk; more comments too 2001-01-03 Paolo Bonzini * sed/compile.c(snarf_char_class) [REG_PERL]: Don't parse `\n' specially * sed/compile.c(match_slash) [REG_PERL]: Ditto * sed/compile.c(read_text) [REG_PERL]: Support [xX] modifiers * sed/compile.c(mark_subst_opts) [REG_PERL]: Ditto 2000-12-21 Paolo Bonzini * lib/snprintf.c [BOOTSTRAP]: Don't include stdio.h * lib/strerror.c [BOOTSTRAP]: Don't include stdio.h * sed/execute.c [!HAVE_ISATTY]: Don't buffer stdin 2000-12-11 Paolo Bonzini * sed/compile.c(mark_subst_opts): Support [mMsS] flags * sed/compile.c(read_text): Support [MS] flags for addresses * sed/regex.c(compile_regex): Support arbitrary flags for regncomp. * sed/regex.c(compile_regex) [REG_PERL]: Don't call normalize_text. 2000-12-08 Paolo Bonzini * basicdefs.h: Moved here from the `sed' subdirectory. * configure.in: Removed crap to pick a regex engine. Added snprintf to the AC_REPLACE_FUNCS call. * lib/snprintf.c: New file. * sed/regex.c(compile_regex): Use regncomp * sed/regex.c(match_regex): Use regexec2 * sed/compile.c(compile_program): Implemented the `v' command. * sed/sed.c(main): Implemented the `r' and `R' options * sed/sed.h: Replaced use_extended_syntax_t with extended_regexp_flags to support Perl regular expressions. * sed/execute.c(open_next_file): Don't mmap stdin (because we cannot seek into it, so a redirected stdin's contents would not be "eaten" by sed) Mon Aug 30 23:40:08 PDT 1999 Ken Pizzini *** Version 3.02.80 released * sed/execute.c(do_subst): lib/regex.c(re_search_2) seems to want one extra backreference register; humor it. * sed/regex.c(compile_regex): work around some odd assumptions that lib/regex.c(re_compile_pattern) makes about our desired RE syntax. * configure.in: tweaked version to 3.02.80; added new entries to the ALL_LINGUAS definition. * doc/sed.1, doc/sed.texi, BUGS: explicitly request the output of sed --version in bug-reporting instructions. * doc/sed.texi: the old "informal seders list" is dead; document the new sed-users mailing list instead (under Other Resources). Thu Aug 19 23:27:54 PDT 1999 Ken Pizzini * sed/sed.h: Add explicit #include of "regex-sed.h" (rather than relying on parent file doing so); change the "cmd_regex" member of sed_cmd: make it a pointer (instead of a struct), and change its name to cmd_subst; add prototypes for newly exported functions bad_prog(), normalize_text(), compile_regex(), match_regex(), and release_regex(); drop rx_testing variable. * sed/compile.c: move the compile_regex() function to regex.c; export bad_prog() and normalize_text() functions; eliminate the rx_testing debris; rename the NOLEAKS symbol to more descriptive DEBUG_LEAKS; make cmd_regex to cmd_subst fixes (see above); make use of newly abstracted release_regex() function. * sed/execute.c: abstract out the regex matching to regex.c:match_regex(); NOLEAKS to DEBUG_LEAKS change; cmd_regex to cmd_subst structure member name change. * sed/execute.c(do_subst): use re_registers/regoff_t instead of regmatch_t to hold the backreference registers, make "offset" always be relative to the beginning of the string (rather than a delta from "start"), defer some matching bookkeeping (e.g., not_bol_p) to match_regex(). * sed/sed.c(main): loose rx_testing variable; NOLEAKS (aka DEBUG_LEAKS) code attempting to release _nl_current_default_domain is problematic, so omit it. * sed/regex.c: new file --- abstracts out the interface to the regex engine so that less conditional code is required in compile.c and execute.c, and so as to make a change of engine easier; implements compile_regex() (which looks an awful lot like the one that used to live in compile.c), match_regex(), and (if DEBUG_LEAKS is set) release_regex(). Sun Apr 18 04:40:46 PDT 1999 Ken Pizzini * sed/sed.c(main): conditionalize calls to setlocale() and textdomain() to only occur if their support is needed/wanted. Sun Apr 18 03:01:46 PDT 1999 Ken Pizzini * bootstrap.sh: "foo || bar && baz" was not grouping like I expected ("foo || (bar && baz)") under at least one shell, so change the test for a pre-existing config.h file to an if statement. * bootstrap.sh: added -DUSE_REGEX_GNU_H option to the compiler invocation, to ensure that we get a usable regex library included. Sun Apr 18 02:59:42 PDT 1999 Ken Pizzini * sed/sed.h, sed/utils.c: conditionalized inclusion of to occur only if ENABLE_NLS is defined. Sun Apr 18 01:48:45 PDT 1999 Ken Pizzini * sed/compile.c(xofa,normalize_text,convert_number): change name of xofa() function to convert_number(); change semantics to do all of the work of the text->number conversion. * sed/compile.c(normalize_text): add new \dDDD decimal and \oOOO octal escapes. Sun Mar 28 21:05:07 PST 1999 Ken Pizzini * sed/sed.c(main): if NOLEAKS is set, free up a word that the call to textdomain() allocated. * sed/execute.c(read_file_line): plug up (minor) memory leak: if buffer.alloc==0 we may have malloc()'d 1 byte anyway, so be sure to FREE(buffer.text) before calling line_init(); Fri Mar 26 16:52:10 PST 1999 Ken Pizzini * sed/compile.c(match_slash): somewhere between 3.02 and 3.02a we lost the ability to use a newline as the s/// delimiter; restore this ability. * sed/compile.c(compile_regex): forget about trying to cache the compiled form of the last RE --- it causes more problems than its worth. We now only cache the source form. * testsuite/help.good: update to reflect output containing new options. Sun Dec 6 00:51:23 PST 1998 Ken Pizzini * sed/utils.c(ck_fwrite): fix i18n bug of using a printf fragment of "item%s" to handle plural text. Mon Nov 23 11:03:40 PST 1998 Ken Pizzini * doc/sed.1, doc/sed.texi: ran ispell over these files to catch the more obvious typos... Sun Nov 1 00:09:07 PST 1998 Ken Pizzini * sed/execute.c(do_list): make a `lcmd_out_line_len' (--line-length) of zero mean "infinite length", i.e., "never wrap". Sat Oct 31 23:06:50 PST 1998 Ken Pizzini * execute.c(match_an_address_p,process_files), compile.c(compile_program): back out the "zero-address" changes of 1998-09-27. It was a neat idea, but there are too many dark corners which don't work well. The special code for handling line ranges starting at address zero (from 1998-08-31) are still there though: this seems to work fine with no surprises. Sat Oct 31 22:18:59 PST 1998 Ken Pizzini * sed/sed.c, sed/sed.h, sed/execute.c: added new `lcmd_out_line_len' variable. (Idea suggested by Carlos J. G. Duarte .) Also added ATOI macro (which uses strtoul() if available, with fall-back to atoi()). * sed/sed.c(main): attempt to use COLS environment variable to set a reasonable `lcmd_out_line_len'; added -l/--line-length command-line options to set the new `lcmd_out_line_len' flag. * sed/sed.c(usage): documented new -l/--line-length options. * sed/execute.c(do_list): use `lcmd_out_line_len' variable instead of `LCMD_OUT_LINE_LEN'. * sed/execute.c: deleted now obsolete LCMD_OUT_LINE_LEN define. * configure.in: added strtoul to the AC_CHECK_FUNCS call. Sat Oct 31 21:37:17 PST 1998 Ken Pizzini * sed/sed.c, sed/sed.h, sed/execute.c: added new `force_unbuffered' flag. (Idea suggested by Frank Strauss .) * sed/sed.c(main): added -u/--unbuffered command-line options to set the new `force_unbuffered' flag. * sed/sed.c(usage): documented new -u/--unbuffered options. * sed/execute.c: changed the name of the `is_tty' flag in struct input to a more generic `no_buffering'; also removed HAVE_ISATTY conditional on this member. * sed/execute.c(slow_getline): removed HAVE_ISATTY conditonal compilation of this function. * sed/execute.c(output_line): if force_unbuffered is set, then force a fflush() even if writing to stdout. * sed/execute.c(open_next_file): added handling of the new `force_unbuffered' flag so that slow_getline() will always be used for input. * sed/execute.c(read_file_line): changed the (conditionally compiled) test of `input->is_tty' to (unconditionally) use the new spelling `input->no_buffering'. Thu Oct 15 12:08:09 PDT 1998 Ken Pizzini * configure.in: deleted AC_ARG_PROGRAM call; this is already done for us by AM_INIT_AUTOMAKE, and we were winding up with a doubled-transform. Sun Sep 27 01:42:42 PDT 1998 Ken Pizzini * compile.c(compile_program): remove special-case code for matching address range with a `0' beginning. * compile.c(compile_address): change default addr_number to be a pragmatically impossible countT value, instead of zero. * execute.c: spell macro REGNEXEC() unconditionally instead of playing with conditional definition of regnexec() macro. * execute.c(match_an_address_p): added third argument (and changed callers in match_address_p). Added special code to ignore non-numeric matches when processing "line zero". * execute.c(process_files): added a "line zero" pass through the commands script. Sun Sep 27 00:20:53 PDT 1998 Ken Pizzini * compile.c(xofa,normalize_text): new functions. * compile.c(compile_regex): cache last_compiled_re (with its associated flags); add POSIXLY_CORRECT behavior for empty RE. Make use of the new normalize_text() function. * compile.c(setup_replacement): Make use of the new normalize_text() function. Sat Sep 26 22:59:13 PDT 1998 Ken Pizzini * lib/regex-gnu.h: added missing prototype for regncomp(). Mon Sep 14 20:47:23 PDT 1998 Ken Pizzini * sed/sed.c(main): use EXIT_SUCCESS instead of 0, in case we are built on a system (such as VMS) where EXIT_SUCCESS is distinct from 0. Wed Sep 9 22:17:28 PDT 1998 Ken Pizzini * sed/Makefile.am: added -I../intl the INCLUDES line; if we are building in a directory outside the source tree and the system we are building on does not have a header, then the build was failing, because libintl.h is a build-time constructed source file. * configure.in: tweaked version to be 3.02b. Wed Sep 9 19:28:14 PDT 1998 Ken Pizzini *** Version 3.02a released * sed/compile.c(mark_subst_opts,read_label,compile_program): wherever we accept a ; as a command terminator, also allow a } or a # to appear. (This allows for less cluttered-looking scripts, such as: sed '/foo/{x;G}' (instead of: sed '/foo/{x;G;}').) Wed Sep 9 18:17:07 PDT 1998 Ken Pizzini * sed/compile.c(compile_regex): use regncomp() instead of regcomp(), so that a script with NULs in its REs will work in the expected manner. * sed/compile.c(ADDNUL,REGNCOMP): added support macros for above. * lib/regex.c(regncomp,regcomp): added regncomp() and made regcomp() a simple wrapper function. Mon Aug 31 21:48:30 PDT 1998 Ken Pizzini * sed/sed.c(compile_program): if the first address of a range is the number 0 (or a 0~N sequence), start out in the "a1_matched" state. This allows one to match an initial chunk of a file without undue convolutions for handling the case where the match for the end of the sequence happens to be the first line. Sun Aug 16 03:34:25 PDT 1998 Ken Pizzini * sed/compile.c(snarf_char_class,match_slash): simplify handling of "premature newline" error. Also, get the line number right in the error message if we encounter a "premature newline" during char-class snarfing. Sun Aug 16 02:59:20 PDT 1998 Ken Pizzini * sed/compile.c: added N_() markers and corresponding gettext() (er, _()) calls. * Merged in i18n contribution from Erick Branderhorst . His ChangeLog entry for the changes I've incorporated so far: 1998-07-24 Erick Branderhorst * configure.in (ALL_LINGUAS, AM_GNU_GETTEXT): nl * sed/{sed.h,utils.c}: #include #define _(String) gettext (String) * sed/sed.c: #include * po/POTFILES.in: sed/{compile,execute,sed,utils}.c * run gettextize -f * acconfig.h: #undef LOCALEDIR ENABLE_NLS HAVE_CATGETS HAVE_GETTEXT HAVE_LC_MESSAGES HAVE_STPCPY Fri Aug 14 13:52:57 PDT 1998 Ken Pizzini * Merged code from 3.02 with a branched development tree from late May; the following (out-of-order) changelog entry is from the branched tree. Sat May 30 12:23:16 PDT 1998 Ken Pizzini * sed/compile.c, sed/execute.c: added (conditional on NOLEAKS macro) code to free all dynamically allocated memory. * sed/sed.c, sed/compile.c, sed/execute.c: much shuffling of code --- ordered functions such that no forward declarations are necessary, and placed all static prototypes immediately before the actual function definition. This accomplished two things: first, I find the new ordering a more natural way to read the code than the previous ordering, and second, the new ordering give the compiler a better opportunity to discover inlining possibilities. (The odd "prototype declaration+old-style definition" style is used because I feel it is the least ugly way of supporting K&R1 C while still getting the benefit of prototypes when they are available.) * sed/basicdefs.h: added MEMCPY() macro to hide the VCAST()s that ought to be used with memcpy(). * sed/execute.c: Change calls to memcpy() to go through the new MEMCPY() macro. Various prototypes: elide variable name if it does not add any human-useful documentary information to the bare type. * sed/sed.c(main): Updated calls to compile_string() to add third (length) argument. Changed call to obsolete close_all_files() to a call to the new finish_program(). * sed/sed.c(map_file): Attempt to clean-up how "size" gets cast and tested; remove spurious S_ISREG test (just let mmap() fail if it doesn't support the underlying file type). * sed/sed.c: Deleted old RX library stub declarations. * sed/sed.c(map_file,unmap_file): added VCAST()s to the mmap()/munmap() calls. * sed/utils.c(ck_fclose): added support for ANSI C functionality where passing a NULL argument means to fclose() _all_ open streams. (Well, almost. Only closes streams which were previously ck_fopen()ed, as I don't care to figure out how to autoconf-detect whether fclose(NULL) is properly supported on a given platform.) * sed/sed.h: Renamed `struct text_buf' member `text_len' to `text_length'. Abstracted out `enum addr_types' from `struct addr'; added new enum types num2,step,step_mod; renamed mod to num_mod. De-unionized the regex,number, {modulo-offset/step} components of `struct addr', in anticipation of new features. Changed type of `a2' member of `struct sed_cmd': now a pointer to save space. Abstracted out `struct replacement' from `struct subst'. Cleaned up declaration of `x' union of `struct addr'. Fixed prototype for compile_string(). Replaced prototype for old close_all_files() with one for new finish_program(). * sed/sed.h, sed/compile.c, sed/execute.c: changed to simplify the data structures used for branches and command blocks: simplified `struct vector'; made `struct label' local to compile.c; `struct sed_cmd' was modified to support a simpler design for branches and blocks. * sed/execute.c: Conditionally added ADDNUL() macro so that the function call overhead is only incurred if nul_append() _must_ be called. Made some commentary edits, including typo fixes. * sed/execute.c(resize_line): changed semantics of "len" argument from "additional length" to "target length"; made INITIAL_BUFFER_SIZE a minimum allocation length. * sed/execute.c(str_append): adjusted to new resize_line() semantics. * sed/execute.c(line_copy): use FREE()+MALLOC() instead of REALLOC() to avoid unnecessary copying of old text; add the "try doubling first" allocation heuristic (just like resize_line() does). * sed/execute.c(line_exchange): new function. * sed/execute.c(nul_append): make whole function (not just its body) conditional on HAVE_REGNEXEC macro; adjust to new resize_line() semantics. * sed/execute.c(read_mem_line): use str_append() instead if custom in-line code; compensate for new default of "line.chomped = 0" in read_pattern_space() by setting "line.chomped = 1" where appropriate. * sed/execute.c(read_file_line): use different trigger to determine that "buffer" is uninitialized, and do a full initialization if required; use str_append() instead of custom in-line code in two places; compensate for new default of "line.chomped = 0" in read_pattern_space() by setting "line.chomped = 1" where appropriate. * sed/execute.c(output_line): don't bother calling ck_fwrite() if length==0. * sed/execute.c(release_append_queue): new function. * sed/execute.c(dump_append_queue): use release_append_queue() instead of in-line equivalent. * sed/execute.c(read_pattern_space): conditionalize call to dump_append_queue() for alleged performance reasons; changed default "line.chomped" value to more common "1", and added an assignment of "0" where this made a difference. * sed/execute.c(match_an_address_p): deleted "is_addr2_p" argument; reorder cases to match order in enum declaration; add cases for new "addr_is_num2", "addr_is_step", and "addr_is_step_mod" address types; alter nul_append() call to be through ADDNUL() macro; fix to new struct member and enum spellings in (formerly addr_is_mod); addr_is_num_mod case. * sed/execute.c(match_address_p): remove oblsolete third argument to calls to match_address_p(); alter references to sed_cmd member a2 to reflect new pointer status; add new support for a2->addr_type addr_is_step and addr_is_step_mod cases. * sed/execute.c(do_subst): add NOLEAKS support logic; use ADDNUL() wrapper to nul_append(); simplify replacement expansion by using the new "struct replacement" data structure; use line_exchange() function instead of custom in-line code. * sed/execute.c(process_files): added NOLEAKS code. * sed/execute.c(execute_program): updated implementations of the `{', `}', `:', `b', and `t' commands; modified `c' command gratuituosly; fixed potential memory overrun in `D' command. Simplified how nonstandard `loop increments' work. Use line_exchange() instead of custom in-line code in 'x' case. * sed/execute.c[EXPERIMENTAL_DASH_N_OPTIMIZATION conditional code]: various modifications intended to keep this code in sync with the new changes, but the code still retains its previous bugs. * sed/compile.c: use "exit(EXIT_FAILURE) instead of "exit(1)", just in case we get compiled under VMS. * sed/compile.c: Change type of prog_info.base to decrease needs for casting; then elimiated the casts in question ;-). * sed/compile.c: Added struct sed_label (moved from sed.h, then modified). * sed/compile.c: Removed "readit_p" flag from struct fp_list. * sed/compile.c: Added module-global "blocks" variable. * sed/compile.c: Extracted more error-message constant strings to named variables. * sed/compile.c(check_final_program): updated to reflect new data structures and use new fucntions. Added call to compile_regex() to release unneeded memory. * sed/compile.c: deleted obsolete new_vector() function; abstracted new read_label() function; abstracted new release_label() function; added new `blocks' module-static variable. * sed/compile.c(compile_program): updated implementations of the `{', `}', `:', `b', and `t' commands; modified initialization from NULL vector. * sed/compile.c(compile_regex): added mechanism to release memory consumed by the cached `last' RE. * sed/compile.c(setup_jump,setup_label): updated name (from setup_jump to setup_label) and prototype; changed body to reflect data structure changes. * sed/compile.c: Add OPEN_BRACE and CLOSE_BRACE macros for better "vi" editing behavior. * sed/compile.c(compile_filename,read_filename,get_writefile): Replaced function compile_filename() with more orthogonal functions read_filename(), get_writefile(). * sed/compile.c(compile_regex): Added ability to free the remembered "last RE" in compile_regex (for benifit of "NOLEAKS" code). * Made adjustments dictated by the change to struct sed_cmd which made the a2 member a pointer-to-addr instead of an addr. * sed/compile.c(setup_jump,read_label,setup_label,release_label): Added functions read_label(), setup_label(), release_label(); deleted function setup_jump(). * sed/compile.c(new_replacement,setup_replacement,release_replacement): new functions. * sed/compile.c: Adjusted to new spelling of text_buf member ("text_length" instead of "text_len"). * sed/compile.c(new_vector): deleted function. (Due to new handling of blocks, only one instance remained, and that one was just as clear in-lined.) * sed/compile.c(compile_string): Added third argument; it now takes a counted string instead of a NUL-terminated string. * sed/compile.c(compile_file): added variable "map_base" to compensate for new type of prog_info.base. * sed/compile.c(check_final_program): reflect new style of handling blocks and struct sed_label. * sed/compile.c(close_all_files,finish_program): replaced function close_all_files() with more generic finish_program(). * sed/compile.c(read_text): added new feature: if first non-blank character after the {a,i,c} command character is not "\", then use the trailing text on that line as the (first) line of text. Also added code conditional on NO_INPUT_INDENT to support the "feature" of stripping leading blanks from each input line; I do not read POSIX as permitting this behavior, nor do I think it is a good idea, so it is disabled by default, but some have argued that this blank-stripping is the "correct" behavior, so I offer them the option of building their sed that way. * sed/compile.c(compile_address): added xxx,+n and xxx,~n addressing; simplified code. * sed/compile.c(compile_program): added BAD_PLUS error detection; adjusted to new cur_cmd->a2 pointer status; added addr_is_num2 detection; deleted pointless "a2->addr_number < a1.addr_number" check (addr_is_num2 semantics handle this just fine); updated code for '{', '}', ':', 'b', and 't' to reflect new design of branch handling, including making use of new functions related to the new design); added support for feature already mentioned in read_text() where {a,i,c} commands are able to have their text start on the same line as the command; changed some error messages (hopefully for the better); localized variables specific to individual commands (particularly 's' and 'y'); made use of new setup_replacement() function in 's' command. Mon Aug 10 19:58:49 PDT 1998 Ken Pizzini * doc/sed.texi, doc/sed.1: sedtut10.txt is apparently dead. Deleted references to it and added a pointer to http://seders.icheme.org/tutorials/. (Pointed out by Joerg Heitkoetter .) Sat Aug 8 18:11:57 PDT 1998 Ken Pizzini * djgpp/config.btm: per request by Michel de Ruiter , added "%1" to "%9" parameters. Mon Aug 3 11:44:55 PDT 1998 Ken Pizzini * doc/sed.texi: fix a couple of typos. (Submitted by Alan Modra .) Sat Aug 01 17:49:06 PDT 1998 Ken Pizzini *** Version 3.02 released * configure.in: Because of code change in 3.01a, bump the minor revision number for the release (now 3.02). Sun Jul 26 16:07:55 PDT 1998 Ken Pizzini *** Version 3.01a released * sed/compile.c(snarf_char_class): the POSIX char-class recognition loop forgot to update its concept of "prev" as the loop progressed. * testsuite/Makefile.am: The dependency of version.good on [testsuite/]Makefile introduced in the previous release was botched -- it referred to "Makefile" as "$(srcdir)/Makefile, which of course doesn't work if you aren't building in the source tree. * djgpp/Makefile.am: add forgotten "config.btm" EXTRA_DIST member. * configure.in: update version. Tue Jul 21 06:04:42 PDT 1998 Ken Pizzini *** Version 3.01 released * configure.in: mark as release version! * Makefile.am: add BUGS and THANKS to the EXTRA_DIST target. * testsuite/Makefile.am: add dependency of version.good on [testsuite/]Makefile. Mon Jul 20 12:38:10 PDT 1998 Ken Pizzini * djgpp/config.btm: New file to support the 4DOS alternative to command.com. (Sumitted by Eli Zaretskii on behalf of an anonymous 4DOS user.) Fri Jul 17 00:36:34 PDT 1998 Ken Pizzini *** Version 3.01-beta18 released * djgpp/config.sed: my "tweak" in beta17 was too hastily considered. Back it out. * configure.in: update to beta18. Wed Jul 15 01:02:15 PDT 1998 Ken Pizzini *** Version 3.01-beta17 released * djgpp/config.sed: tweak/simplify s,,, commands at end. * configure.in: update to beta17. 1998-07-14 Eli Zaretskii * djgpp/config.sed: Edit all the occurences of = in the context of --option=value, including in the help messages, into --option:value, but leave DOS-style d:/foo/bar file names intact. * djgpp/config.bat: Use --srcdir:foo instead of --srcdir=foo. * testsuite/Makefile.am (help, version): Remove temporary files explicitly, don't use shell wildcards, so it works under DOS 8+3 limits. Thu Jul 9 13:06:00 PDT 1998 16:51:43 PDT 1998 Ken Pizzini *** Version 3.01-beta16 released * djgpp/config.sed: tweak the configure script to use : instead of = for --with-foo=bar option parsing, to work around problems with how command.com handles =s. Wed Jul 8 16:51:43 PDT 1998 Ken Pizzini * djgpp/config.bat: correct inappropriate behavior that I introduced in the beta13 changes (if first argument is a directory, it needs to be handled as the --srcdir). * testsuite/version.gin, testsuite/version.good, testsuite/Makefile.am: Add target to automake to automatically update version.good from (new file) version.gin, instead of hand-editing the version number each release. * testsuite/Makefile.am: miscellaneous gratuitious tweakage -- mainly adding $(RM) commands just because I didn't like leaving the tmp* files from successful runs laying about. Also some editorial comments. * configure.in: update to beta16. Added and commented out experiment with AC_OUTPUT() for testsuite/version.good. Added code to properly handle bare (without =xxx) "--with-regex" option. Sun Jul 5 21:02:16 PDT 1998 Ken Pizzini *** Version 3.01-beta15 released * sed/utils.c(ck_fflush), sed/utils.h, sed/execute.c(output_line): add and use new ck_fflush() function. Sun Jul 5 15:23:47 PDT 1998 Ken Pizzini * sed/compile.c(bad_prog): add more detail to error messages about -e strings. Sun Jul 5 14:29:45 PDT 1998 Ken Pizzini * sed/compile.c(mark_subst_opts), sed/execute.c(do_subst): Define better semantics for interaction of the `g' flag with a numeric flag to the s/// command. It used to be that the `g' command siezed control; now the first (number-1) matches are skipped and then `g' gets control after that. (It is not clear whether this is a feature sneaking in during late beta, or a bug fix; the changes involved were trivial, so I decided to treat it as a bug fix.) * configure.in, testsuite/version.good: update to beta15. Sat Jul 4 09:54:45 PDT 1998 Ken Pizzini *** Version 3.01-beta14 released * sed/basicdefs.h, sed/compile.c, sed/execute.c: per report by "Kaveh R. Ghazi" , copied the ISXXX macros from lib/regex.c so that silly machines which require isascii() to be true before the other isXXX() macros are valid will still work. * configure.in, testsuite/version.good: update to beta14. Thu Jul 2 23:46:13 PDT 1998 Ken Pizzini *** Version 3.01-beta13 released * configure.in, acconfig.h: set USE_REGEX_GNU_H symbol if we are going to be using lib/regex.c. * lib/Makefile.am, lib/regex.h, lib/regex-gnu.h, lib/regex.c: rename lib/regex.h to lib/regex-gnu.h, so that those who choose to use a different regex implementation will not pick-up lib/regex.h when doing "#include ". * sed/regex-sed.h, sed/Makefile.am, sed/compile.c, sed/execute.c, sed/sed.c: create sed/regex-sed.h which acts as a switch to choose either lib/regex.h or the user-supplied , depending on the value passed to configure's --with-regex= option. Thu Jul 2 17:22:31 PDT 1998 Ken Pizzini * configure.in: if an alternative --with-regex= is given, do an AC_CHECK_FUNCS(regnexec regexec) to ensure that at least one of these functions is available. Also, parallel changes for the default case. * sed/execute.c, acconfig.h: retire use of the WITH_REGNEXEC test macro in favor of HAVE_REGNEXEC test macro created by above change. * djgpp/config.bat: Play games to handle "install-sh", DOS filename restrictions, GNU makefile default rules, and getting a correct run of "configure" (contributed by Eli Zaretskii ). * djgpp/Makefile.am, testsuite/Makefile.am, testsuite/Makefile.in, Makefile.am, configure.in: Various automake targets (such as distcheck) failed with old configuration. The simplest solution was to just add these .am files. (The testsuite/Makefile.in was just renamed to testsuite/Makefile.am, then various redundant defines and targets were deleted.) (Reported by Erick Branderhorst .) * testsuite/dc.good, testsuite/dc.inp: per suggestion from Greg Ubben , use base 16 output to exercise even more of the dc.sed script. * configure.in, testsuite/version.good: update to beta13. Sun Jun 28 16:21:02 PDT 1998 Ken Pizzini *** Version 3.01-beta12 released * doc/sed.texi: Avoid mixing @code and @samp markups together: they look ugly in Info. Use @url and @email instead of @example. Add indexes. (Basis of changes contributed by Eli Zaretskii.) * djgpp/*, Makefile.am: add support for the DJGPP compiler, contributed by Eli Zaretskii . * dc.sed, testsuite/Makefile.in, testsuite/dc.inp, testsuite/dc.good: added this remarkable script, written and contributed by Greg Ubben , both as a work of art for general admiration, and also for use in regression testing. * configure.in, lib/Makefile.am: add --with-regex=regexlib option, which overrides the use of lib/regex.c. * configure.in, testsuite/version.good: update to beta12. Fri Jun 12 16:41:48 PDT 1998 Ken Pizzini *** Version 3.01-beta11 released * sed/compile.c: add module-static variables first_script (for #n change below) and pending_text (for a/c/i change below). * sed/compile.c(compile_file), sed/compile.c(compile_program): Instead of having #n trigger the -n option in *any file*, have #n trigger the -n option only if they are the first two bytes of the first script or script-file. * sed/compile.c(compile_string), sed/compile.c(compile_file): clear the first_script variable at end of these functions. * sed/sed.h: tease out the struct text_buf declaration from struct sed_cmd, so that a pointer to such can be passed to new sed/compile.c(read_text) function. * sed/compile.c(compile_program), sed/compile.c(read_text): Tease out handling of text to a/c/i commands to new read_text() function. Handle (via aid of pending_text variable) texts which span more than one script/script-file option. In particular, restore the ability to have this work: sed -e '1i\' -e 'foo' * sed/compile.c(check_final_program): close off any dangling pending_text allocation. Thu Jun 11 11:17:46 PDT 1998 Ken Pizzini * sed/execute.c(do_subst): fixed two bugs: s/ */X/g was failing to match the final empty string after the end of the pattern space; and /^foo$/s/o/x/3p was printing, despite the failure to do a substition. Fri Jun 5 04:40:24 PDT 1998 Ken Pizzini * configure.in: change the AC_ARG_WITH(regnexec, ...) to be the more appropriate AC_ARG_ENABLE(regnexec, ...). * configure.in, testsuite/version.good: update to beta11. Fri Jun 5 00:54:25 PDT 1998 Ken Pizzini *** Version 3.01-beta10 released * sed/execute.c: forgot to P_() the prototype and old-style the declaration for bootstrap_memchr()! Thu Jun 4 18:42:30 PDT 1998 Ken Pizzini * sed/compile.c(snarf_char_class): added code to recognize \n or \ sequence within a char-class as the newline character. Tue Jun 2 11:56:02 PDT 1998 Ken Pizzini * configure.in: added check for and a AC_ARG_WITH(regnexec,...) check, to simplify use of other regex libraries which have regexec() but not regnexec(), with the corresponding loss of functionality (regexps will not work right against input lines which contain NULs). * sed/execute.c: add nul_append() function, a #define for a regnexec() -> regexec() macro (conditional on the lack of the WITH_REGNEXEC symbol), and a couple of calls to nul_append() (in match_an_address_p() and do_subst()) to permit the use of the POSIX standard regexec() function call instead of the suggested regnexec() call. * sed/compile.c, sed/execute.c, sed/sed.c: check for and include it (before "regex.h") if available. This makes it simpler to use the system's regex library instead of the one in lib/regex.c, should that be desired. Tue Jun 2 08:41:05 PDT 1998 Ken Pizzini * sed/basicdefs.h: define VCAST macros to allow sed to compile on systems which predate the definition of "void *", and yet still get feedback about stupid programming errors from systems which *do* know about "void *"s. Also define MALLOC, REALLOC, MEMDUP, and FREE macros to keep under control the degree of code ugliness which would otherwise be introduced in making use of the VCAST macro. * sed/compile.c, sed/execute.c, sed/sed.c, sed/utils.c: pervasively use the new VCAST, MALLOC, REALLOC, MEMDUP, and FREE macros wherever appropriate. * sed/utils.c, sed/utils.h: correct type of first arguments to ck_fread() and ck_fwrite() to be [const] VOID *. * sed/basicdefs.h, sed/execute.c: protect against the rumored systems which stupidly #define __STDC__ 0. * testsuite/help.good, testsuite/Makefile.in: make the ``help'' test insensitive to the spelling of the executable's name. Also, enhanced `make clean' target. * doc/sed.texi, doc/sed.1: correct documentation of `q' command; fix typos. * configure, testsuite/version.good: update to beta10. Sat May 30 17:28:00 PDT 1998 Ken Pizzini *** Version 3.01-beta9 released * Makefile.am: make testsuite a normal SUBDIR. * configure.in: discontinue using AC_ISC_POSIX -- check for -lcposix library instead; added testsuite/Makefile to AC_OUTPUT list. * lib/memmove.c(memmove): fixed wrong sense used for HAVE_BCOPY test. * sed/execute.c: checked more specifically for a version of gcc which supports __attribute__ (i.e., >= 2.7). * testsuite/*: renamed files to fit 14 char limit. * testsuite/Makefile, testsuite/Makefile.in: Makefile renamed to Makefile.in and then modified so that "make -j check" from top directory will work. * testsuite/subwrite.sed, testsuite/writeout.sed: changed file name of the "w" command to be consistent with the new naming used in testsuite/Makefile.in. * doc/sed.1, doc/sed.texi: fixed some typos, formatting glitches, and poor wordings. Sat May 30 04:02:29 PDT 1998 Ken Pizzini * configure.in: specify that config.h is to be derived from config_h.in in order to avoid the braindead DOS filesystem limitations. Fri May 29 21:56:30 PDT 1998 Ken Pizzini * sed/compile.c(compile_address), doc/sed.texi: gave a better definition to the meaning of N~0 address forms -- N~M addresses now mean that lines match when there exists a non-negative x such that lineno == N+x*M. Fri May 29 12:07:38 PDT 1998 Ken Pizzini * sed/compile.c(compile_address), sed/execute.c(match_an_address_p): update semantics of N~M address form: now N is the first line which will match and M is the step between succeeding matches. If N=M seems more useful. * doc/sed.1, doc/sed.texi: update documentation of N~M address form; added "Other Resources" node to sed.texi; minor formatting changes to some items in sed.1 with an eye to improving clarity. * configure.in, testsuite/version.good: update to beta9. Sat May 23 20:04:31 HST 1998 Ken Pizzini *** Version 3.01-beta8 released * sed/compile.c(compile_regex): forgot to make last_re be a *copy* of the buffered text in today's earlier fix. * sed/execute.c(read_file_line): EOF check was wrong -- it forgot to allow for the possibility that we were appending to the end of the ``line'' (instead of merely reading a fresh line). Sat May 23 18:07:18 HST 1998 Ken Pizzini * sed/compile.c(compile_regex): don't track compiled version of regex -- the modifiers may change. Track the regex source instead. (For "last regex" (aka //) notation.) * configure.in, testsuite/version.good: update to beta8. Sat May 23 16:07:09 HST 1998 Ken Pizzini *** Version 3.01-beta7 released * sed/execute.c: #undef'd EXPERIMENTAL_DASH_N_OPTIMIZATION because its code is buggy. Tue May 19 17:03:52 HST 1998 Ken Pizzini * sed/sed.c: label rx library code as such with #ifdefs (instead of just #if 0). * sed/compile.c(compile_program): make incremental improvement to the "Unknown command" error message. Sat May 16 23:16:26 HST 1998 Ken Pizzini * testsuite/Makefile: simplify: get rid of automatic run against system's sed; don't time by default; allow for alternative comparison command. * configure.in, testsuite/version.good: update to beta7. Wed May 13 21:44:28 PDT 1998 Ken Pizzini *** Version 3.01-beta6 released * lib/Makefile.am: fix spelling of libsed_a_LIBADD in libsed_a_DEPENDENCIES. * configure.in, testsuite/version.good: update to beta6. Wed May 13 14:38:08 PDT 1998 Ken Pizzini *** Version 3.01-beta5 released * sed/execute.c(do_subst): added not_bol_p variable to track when we have iterated past the beginning of the pattern. [Thanks to Jim Meyering for the bug report.] Wed May 13 13:54:04 PDT 1998 Ken Pizzini * sed/execute.c(bootstrap_memchr): new function. When bootstrapping we don't know if we are on a 64-bit machine, so lib/memchr.c breaks. Supply this (slow) implementation just to get us bootstrapped. * bootstrap.sh: add a #define BOOTSTRAP symbol; add -I. for emphasis for the compiles in sed/; be explicit about what files we're bothering to compile. * configure.in, testsuite/version.good: update version to beta5. Wed May 13 06:39:06 PDT 1998 Ken Pizzini *** Version 3.01-beta4 released * rename writeout.good? to wrtout?.good and subwrite.good? to subwrt?.good to comply with DOS 8+3 file name restrictions. [Eli Zaretskii suggested this to simplify DJGPP ports, and it was easy.] * testsuite/Makefile: reflect above name changes. Wed May 12 21:09:32 PDT 1998 Ken Pizzini * sed/sed.c(usage): fix non-portable omission of \n\ at end of lines within long string. * sed/sed.c(main): remove spurious argument to fprintf() in the 'V'ersion output. * sed/execute.c(line_append): embed newline between the two text fragments unconditionally. * sed/execute.c(do_subst): change structure assignment to memcpy() (for portability reasons). * README.bootstrap: suggest using -w option. Tue May 12 10:02:37 PDT 1998 Ken Pizzini * configure.in: use AC_REPLACE_FUNCS where appropriate. * lib/Makefile.am: updated to reflect AC_REPLACE_FUNCS change in configure.in. * lib/memchr.c lib/memcmp.c: revert to standard GNU versions. * lib/alloca.c: added this missing file. * testsuite/version.good: updated for new version identifier. Mon May 11 18:50:56 PDT 1998 Ken Pizzini *** Version 3.01-beta3 released * sed/Makefile.am: fix INCLUDES to work right with VPATH. [Thanks to Jim Meyering for the bug report.] * sed/sed.c(usage): make --help output more user-friendly? * sed/execute.c(execute_program): fix bug in 'x' command introduced in the alleged portability fix of May 9. * configure.in: update version to 3.01-beta3. * testsuite/version.good, testsuite/help.good: freshen with latest output. Sat May 9 22:35:45 PDT 1998 Ken Pizzini *** Version 3.01-beta2 released * sed/sed.c: add #include in HAVE_MMAP block (needed on some machines). * lib/memmove.c: #include , if HAVE_MEMORY_H. Sat May 9 21:29:00 PDT 1998 Ken Pizzini * configure.in: remove dangling references to rx library; added HEADER and FUNC checks for items used by source in lib/. * lib/ansidecl.h, lib/memcopy.h, lib/pagecopy.h, lib/string.h lib/memcpy.c, lib/memmove.c: deletes these files. There are still pieces of glibc missing to support these, and it isn't worth the headache right now. * lib/memmove.c: de novo, simpler version. Uses bcopy() if available, and slow-but-simple code if not. * lib/Makefile.am: remove references to deleted files. Added forgotten reference to memcpy.c. Re-ordered SOURCE entries to reflect dependencies for systems which lack ranlib. * sed/basicdefs.h: updated to reflect above changes to lib/, and experience with non-STDC compilers. * lib/regex.c: made regerror() function publicly visible. * lib/strerror.c: use old-style function declaration. * sed/compile.c, sed/execute.c, sed/sed.c, sed/utils.c, sed/sed.h, sed/utils.h: ensure that private definitions of some symbols do not cause problems when #include'ing system headers (mainly by re-ordering the #include directives). (This is particularly an issue for bootstrap.sh runs.) * sed/execute.c (execute_program): use memcpy() instead of structure assingment ('x' command), for portablility to old compilers. * sed/execute.c (slow_getline): use old-style function declaration, with a P_ prototype. * sed/sed.c: change the type of the fallback MAP_FAILED definition to work on archaic systems. (Modern systems should be defining it themselves, so the change from void * shouldn't be a problem.) * bootstrap.sh, README.bootstrap: actual testing of bootstrap code revealed that I was too optimistic. Redesigned and replaced implementation. * testsuite/Makefile: ignore errors from reference-implementation seds that aren't up to snuff. * testsuite/help.good, testsuite/version.good: update to current version's output. Fri May 8 15:08:28 PDT 1998 Ken Pizzini *** Version 3.01-beta1 released * sed/sed.c (main, usage): once again tweak the --help and --version output to bettery comply with GNU coding standards. * testsuite/help.good, testsuite/version.good: update to reflect above change. * doc/sed.texi: fix "Invoking" node's spelling to comply with GNU standards. Fri May 8 11:43:10 PDT 1998 Ken Pizzini * doc/sed.1, doc/Makefile.am: wrote (very basic) man page. Thu May 7 20:40:21 PDT 1998 Ken Pizzini * lib/Makefile.am, lib/memmove.c, lib/memchr.c, lib/regex.c, lib/memcpy.c, lib/regex.h, lib/memcopy.h, lib/string.h, lib/pagecopy.h, lib/ansidecl.h: grab yet-another-version from gnu.org for baseline and/or edit copyright boilerplate using official lgpl2gpl.sed script. Take care not to loose regnexec() interface or special conditional-compilation code. Wed May 6 23:35:12 PDT 1998 Ken Pizzini * lib/regex.c, lib/regex.h: take from grep-2.1 distribution, then trivially added the regnexec() interface. * sed/sed.c, sed/compile.c, sed/execute.c: made modifications to work with regex instead of rx. * rx/*: deleted directory; the code is just too slow. I think it will be easier to extend regex to fully support POSIX.2 than to tune rx to be reasonable. Even if this supposition is wrong, I'd rather make the 3.01 release with the slightly deficient regex. * Makefile.am lib/Makefile.am, sed/Makefile.am: made changes related to the substitution of regex for rx. * lib/Makefile.am, sed/Makefile.am: since regex is not a ``compatability'' module, changed name of library to ``libsed.a''. * lib/memchr.c, lib/memcpy.c, lib/memmove.c: add conditional compilation code to leave zero-sized .o file if system already supports the implemented function. * testsuite/help.good, testsuite/version.good: brought up-to-date (once again). * NEWS, ANNOUNCE: changes to reflect this batch of changes. Wed May 6 18:40:47 PDT 1998 Ken Pizzini * sed/execute.c: discovered awful bug in '}' handling: it could read past the end of vec (because `n' was being decremented below zero)! Needed to "continue" instead of "break". Tue May 5 14:34:38 PDT 1998 Ken Pizzini * doc/sed.texi, doc/version.texi: wrote some rudimentary texinfo documentation. * ANNOUNCE, NEWS, README, README.rx, Makefile.am: more updates for the upcoming beta-release. * sed/compile.c, sed/execute.c, sed/sed.c, sed/utils.c, sed/sed.h, lib/strerror.c: update copyright notice text. Fri May 1 15:41:37 PDT 1998 Ken Pizzini * sed/execute.c (match_an_address_p, match_address_p): if the second element of an address range is a line number, and that line number is *less than* (or equal to) the current line number, we only match the one line (per POSIX.2, section 4.55.7.1). [Bug discovered as reported in the seders mailing list FAQ.] * AUTHORS, NEWS, acconfig.h, configure.in, doc/Makefile.am, lib/Makefile.am, sed/Makefile.am, lib/README, testsuite/help.good, testsuite/version.good: Updated in anticipation of the 3.01-beta1 release. Reorganized development source tree to make creation of a distribution simpler. Most notable changes were to the various Makefile.am files and configure.in, but some minor edits (such as deleting or changing #include directives) have been made in many other source files. * bootstrap.sh, README.bootstrap: created a mechanism for creating sed on a system which lacks a working sed. Thu Apr 16 23:52:11 PDT 1998 Ken Pizzini * sed.h, sed.c, execute.c, compile.c: did a spell-check on the comments; fixed several typos. Thu Apr 16 13:43:01 PDT 1998 Ken Pizzini * execute.c (do_subst): fixed bug where the "replaced" flag was being set to one inappropriately when at least one but fewer than sub->numb matches of the regexp were found. (Thanks to Simon Taylor for the bug report.) Wed Apr 15 11:35:31 PDT 1998 Ken Pizzini * sed.h, sed.c, compile.c, execute.c: having a concern that a cast was being done inappropriately, and realizing that there is no quick way to locate all casts in a program, I went through and marked all casts with a simple macro. Now it is a simple matter to locate the casts, and it is also a simple matter to turn of casts for a lint session (if it should be desired). Wed Apr 15 10:29:21 PDT 1998 Ken Pizzini * compile.c, sed.c: redo compile phase so that brace expressions can be spread across multiple files. For example: printf '{' >a; printf 'l;d' >b; printf '}' >c sed -f a -f b -f c foo will now compile (and work), instead of complaining about an unmatched '{'. The mess created in compile.c allowed a little simplification to the command-line processing of "-e" options in sed.c. sed.h: added (opaque) err_info member to struct vector; added comments to the members of struct vector. Wed Apr 14 23:50:50 PDT 1998 Ken Pizzini * sed.h, sed.c, compile.c, execute.c: added types countT and flagT in order to clarify what various "int"s were doing. Also makes it easy to change the type used for counts (for example, to "unsigned long long") if desired, although there are still some gotchas (such as the printf() format for the '=' command). Tue Apr 14 17:34:54 PDT 1998 Ken Pizzini * execute.c (execute_program, process_files, count_branches, shrink_program): Added a first attempt at program optimization. We now can quit early if we are running with the "-n" and all of the commands are known to be valid only for lines less than the current line. Thus the "sed" in "foo | sed -n 1,2p" will print read three lines, printint the first two, and then quit, regardless of how much longer "foo" might run or output. This optimization does not buy much in most cases (it sometimes even costs a little), but when it does help it can help big. The code is all conditionally compiled based on the EXPERIMENTAL_DASH_N_OPTIMIZATION symbol being #defined, so it can be easily omitted if it causes problems. Tue Apr 14 12:25:06 PDT 1998 Ken Pizzini * execute.c (test_dollar_EOF, last_file_with_data_p): test_dollar_EOF() was incorrectly returning a false (0) when there were unprocessed files, none of which had any data (either unopenable or zero-length). Created last_file_with_data_p() to detect this situation, and modified test_dollar_EOF() to make use of it. Thu Apr 2 23:02:18 PST 1998 Ken Pizzini * compile.c (match_slash): match_slash() did not handle [.coll.], [=equiv=], and [:class:] sequences within a character class. Added snarf_char_class() [which is a remote derivative of parse_char_class() from GNU ed-0.2] to deal with the details, and altered match_slash() to make use of it. Also created the trivial add_then_next() to avoid clutter in snarf_char_class(). Thu Apr 2 20:34:42 PST 1998 Ken Pizzini * execute.c, sed.c, sed.h: There was a severe bug in how the code handled "sed 5n a b" when "a" consists of exactly five lines -- it behaved like "sed 5q a b"! Rearranged where files get opened -- large scale changes primarily involving main(), process_files(), and read_pattern_space(), but also touching on several other parts of execute.c. The read_pattern_space() function became unwieldly and parts were split into open_next_file(), closedown(), read_always_fail(), read_mem_line(), and read_file_line(). The at_end_of_file_p() function became obsolete and was eliminated; test_dollar_EOF_p() was updated. A few global and module-static variables were elminated, and "struct line" was extended; comments were added to the "struct line" declartation to document some important dependencies in it. I undertook the reorganization with dread, but I feel that the new organization is an improvement well beyond just fixing the bug that inspired it. Thu Apr 2 01:16:25 PST 1998 Ken Pizzini * execute.c (read_file_line, slow_getline): the fread() buffering code gives insufficient feedback to a user running sed with a tty input device, so I created slow_getline() for reading from a tty device. Additionally, EOF detection has been made a little more sensitive to avoid requiring multiple EOFs to be entered from a tty. * configure.in: added isatty() check. Wed Apr 1 11:04:30 PST 1998 Ken Pizzini * configure.in (CPPFLAGS, LDFLAGS, LIBS): Set to appropriate values if large file support needs explicit enabling. Code fragment taken from a 1997-10-25 patch to gawk by Paul Eggert Thu Aug 14 17:43:27 PDT 1997 Ken Pizzini * utils.c (ck_fclose): modified to ignore NULL parameter. Thu Aug 14 12:08:45 PDT 1997 Ken Pizzini * execute.c: tweaked execute_program() to eliminate gratuitous "goto" usage. Thu Aug 14 11:30:04 PDT 1997 Ken Pizzini * compile.c: added case-insensitive modifier ('I') to address and s/// regexps. The s/// case also accepts the more popular 'i' modifier. (The address regexp cannot use 'i' as a modifier, as that conflicts with the use of the 'i'nsert command.) Thu Aug 14 09:29:06 PDT 1997 Ken Pizzini * compile.c: abstracted out match_slash() from the s///, y///, and address-regexp special-case codes. * execute.c: made dump_append_queue() use ck_fread() instead of hand-rolled error checking. Mon Jul 28 10:50:41 PDT 1997 Ken Pizzini * sed.c, sed.h, execute.c: POSIX.2, section 4.55.7, says that a newline must end *every* output line. But I think that it is useful (when seding a binary file) to omit a trailing newline if the input lacks one. Thus the addition of POSIXLY_CORRECT behavior. * execute.c: however, when seding multiple files my feeling is that it makes sense to have each file but the last behave as-if it ended in a newline. Modified read_pattern_space() accordingly. * utils.c: realized that add1_buffer(), for performance reasons, shouldn't be calling memcpy() (indirectly via add_buffer()), so rewrote it. Sat Jul 26 23:08:28 PDT 1997 Ken Pizzini * execute.c: attempted to make read_pattern_space more efficient for the the non-mmap() case. * utils.c, utils.h, execute.c: new function ck_fread() created and used. Sat Jul 26 20:22:14 PDT 1997 Ken Pizzini * execute.c, compile.c, sed.c: abstracted the mmap() interface into map_file()/unmap_file() [sed.c], and changed the ad-hoc code in compile_file() [compile.c] and process_file() [execute.c] to make use of the new interface. Sat Jul 26 19:45:46 PDT 1997 Ken Pizzini * execute.c, compile.c, configure.in: Check to see if mmap() is available; if so make use of it on regular files. * compile.c: compile_file() now closes the input file when it is through! Sun Jul 20 23:57:02 PDT 1997 Ken Pizzini * compile.c: modified parsing to permit whitespace in more places where it makes sense; added backslash escaping to the y/// command, per POSIX. * execute.c: Merged append_pattern_space() into read_pattern_space(); moved body of 's' command to new function do_subst(); moved body of 'l' command to new function do_list(); changed output of 'l' command to conform to POSIX.2; made line handling conform to POSIX; added output_line() function; redesigned append-space algorithm; added append_queue structure and the next_append_slot() and dump_append_queue() functions. * sed.h: moved the definition of what is now struct subst outside of the definition of struct sed_cmd. Sat Jul 19 16:29:09 PDT 1997 Ken Pizzini * sed.c, execute.c, sed.h, Makefile.am: Separated out the pieces dealing with executing the program from the top-level parameter parsing and control. Sat Jul 19 01:16:35 PDT 1997 Ken Pizzini * sed.c, compile.c, sed.h, Makefile.am: separate out the pieces dealing with compiling the program from the pieces dealing with interpreting the result. * compile.c: add functions in_nonblank() and in_integer(), and change interface to compile_address() with an eye to making code clearer. Fri Jul 18 13:35:50 PDT 1997 Ken Pizzini * utils.c: attempt at a quasi-unification of the STDC and traditional C approaches to panic(). * sed.c: eliminate some gratuitous bit twiddling. (Using flag bits can be a useful technique, but this code is cleaner without them.) * sed.c: place mutually exclusive members of struct addr within a union, mainly to document the exclusivity; eliminate unused structure members from struct fp_list; eliminate unnecessary module-global variables; remove some #if 0 code that is too odd to keep; allegedly simplified the 'l' case of execute_program(); allegedly simplified inchar(); localized some static variables; renamed some variables to better document their purpose; removed some goto-s rendered obsolete by other changes. Thu Jul 17 15:30:44 PDT 1997 Ken Pizzini * utils.c, utils.h, sed.c: added and made use of ck_free() function. * utils.c, utils.h, sed.c: changed all the *_buffer() functions to take/return an incomplete type "struct buffer *" instead of using VOID *. * utils.c, utils.h, sed.c: renamed "finish_buffer()" to "free_buffer()", on the premise that the new name better describes the function's purpose. Wed Jul 16 13:52:14 PDT 1997 Ken Pizzini * utils.c, utils.h, sed.c: added and made use of ck_memdup() function. * sed.c: protected a call to add1_buffer() in compile_program() which could have tried to push an EOF if a a/i/c command ended with a '\', EOF sequence. * utils.c: added sanity check to add1_buffer() so that EOF will not be added to the buffer. Wed Jul 16 03:56:26 PDT 1997 Ken Pizzini * configure.in, compat.h, compat.c: added memchr. * sed.c: got rid of arbitrary NUM_FPS limit; made global functions and variables "static" where appropriate; make various cosmetic changes, hopefully improving readability; simplified some redundant predicates; simplified some code, but nothing fundamental (yet?). Wed Jul 16 00:24:54 PDT 1997 Ken Pizzini * alloca.c, getopt.c, getopt.h, getopt1.c: updated from versions in textutils-1.22. * Makefile.in, Makefile.am, configure.in: put in automake support. * basicdefs.h, compat.h, compat.c [, sed.c, utils.c]: took out some very ugly compatibility #ifdefs and packaged into one place. * sed.c, utils.c: some gratuitous formatting changes. * utils.c: changed datatype of utils_id_s in order to eliminate arbitrary array size. Sun Jul 13 17:00:26 PDT 1997 Ken Pizzini * sed.c, utils.c, utils.h: de-linting oriented cleanup. Sun Jul 13 00:46:48 PDT 1997 Ken Pizzini * sed.c: fixed bug which caused SEGV for files missing a final newline. Corrected calls to regnexec to pass the proper parameters, in the proper order. Sat Dec 30 20:16:59 1995 Tom Lord *** Version 3.00 released * sed.c: Use posix entry points to regexp functions. Fix enough bugs to pass the test-suite. ....... Jason Molenda * testsuite/: trippy test suite. Wed May 11 07:46:24 1994 Chip Salzenberg (chip@fin.uucp) *** Version 2.05 released * sed.c (compile_address): Recognize numeric addresses. Fixes typo made during installation of "~" feature. Sat Apr 30 17:17:38 1994 Tom Lord (lord@x1.cygnus.com) *** Version 2.04 released * sed.c: applied a patch from From: kap1@tao.cpe.uchicago.edu (Dietrich Kappe) Dietrich writes: As my contribution to the creeping feature creature in sed, here is a new type of address. The address has form n~m, which means "the line number is equal to n modulo m." The modifications to sed are trivial, and the general usefulness of this address should be obvious. If m is 0 or missing, 1 is used in its place (could be a bug or a feature :-). Sat Apr 30 17:17:38 1994 Tom Lord (lord@x1.cygnus.com) * rx.c (solve_destination): protect `solution' more carefully. This is a cleanup of a patch from Kevin Buettner (kev@cujo.geg.mot.com). Sat Apr 30 17:17:38 1994 Tom Lord (lord@x1.cygnus.com) * rx.c: make translation tables unsigned chars * sed.c (main): Compile accumulated -e commands as soon as a -f command comes along. This ensures that the commands are executed in the right order. Mon Oct 25 14:41:47 1993 Tom Lord (lord@rtl.cygnus.com) * sed.c (execute_program): 'w' flushes the buffer after it writes -- diagnosed by doug@research.att.com. 'r' and 'w' to the same file is now supported -- hopefully even in a way that satisfies Posix (it now behaves differently from some /bin/sed's and the spec is hard to read so i'm not sure). Also, 'r' of a non-existent file is now permitted. Mon Oct 11 21:06:10 1993 Tom Lord (lord@cygnus.com) * sed.c (execute_program): remember that 'b' and 't' are more like longjmp than goto. Patch from tom@basil.icce.rug.nl (Tom R.Hageman) * rx.c: patch from From: fin!chip@rutgers.edu (Chip Salzenberg) to get rid of compiler warnings. Sat Aug 7 01:04:59 1993 Tom Lord (lord@unix7.andrew.cmu.edu) *** Version 2.03 released * sed.c (compile_regex): report error messages for bogus regexps. SEE ALSO: ChangeLog.rx Wed Jul 21 00:28:03 1993 Tom Lord (lord@unix8.andrew.cmu.edu) * alloca.c: upgraded to a more recent version * rx.c (re_search_2): prefer matches with longer subexpressions to those with shorter ones, giving precedence to low numbered subexpressions. * rx.c (re_compile): don't free `params' if its null. Fri Jul 16 01:12:08 1993 Tom Lord (lord@unix8.andrew.cmu.edu) * rx.[ch], sed.c: rx replaces regex. Thu May 27 11:13:03 1993 Tom Lord (lord@unix3.andrew.cmu.edu) * sed.c (execute_program, match_addr): caught more cases that need to be sensitive to a missing \n at EOF. Fri May 21 00:39:22 1993 Tom Lord (lord@unix8.andrew.cmu.edu) * sed.c (execute_program): apply gaumondp's patch to fix '\xabcxs/foo/bar/'. * sed.c (execute_program): If a second address is a regexp, never match it on the same line as the first address. * sed.c (compile_regexp): Numeric ranges x,y s.t. y < x are now treated as x,x. There was a bug in that they were being handled like x,x+1. * sed.c (execute_program, read_pattern_space, append_pattern_space) don't add newlines to lines that don't have them. Wed May 19 13:34:45 1993 Tom Lord (lord@unix9.andrew.cmu.edu) * sed.c (compile_program): grok \\n in comments. Mon May 17 16:34:50 1993 Tom Lord (lord@unix9.andrew.cmu.edu) * alloca.c: new (standard) file * configure.in: AC_CONSTified * sed.c (compile_program): properly diagnose the error of a missing command (e.g. sed /x/). (thanks gaumondp) * sed.c (compile_regexp): handle character classes correctly. Thanks gaumondp@ERE.UMontreal.CA and schwab@issan.informatik.uni-dortmund.de. Thu May 6 12:37:18 1993 Tom Lord (lord@unix10.andrew.cmu.edu) * sed.c (compile_filename, execute_program): don't use `access' or `/dev/null'. * sed.c (execute_program): 'N' at EOF should delete the pat buf. * sed.c (compile_filename): truncate, don't append files being openned for `w' or `s///w' * sed.c (execute_program): -n switch shouldn't effect `i' or `c'. * sed.c (compile_program): don't compile unescaped newlines into the substitution string of an `s' command (they are an error). * sed.c (compile_regex): correctly skip over character sets that contain `]'. * sed.c (execute_program): patch from gaumondp Correctly handle empty-string matches in the case of an `s' command with a repeat count. * sed.c (compile_program): patch from gaumondp@ere.UMontreal.ca. Don't consume characters after the label of a `b', `t' or `:' command. * sed.c (compile_program): unmatched open braces are an error. * sed.c (compile_file): when consuming an initial comment, count lines correctly. Wed Nov 18 02:10:58 1992 Tom Lord (lord@unix2.andrew.cmu.edu) * sed.c (execute_program): Made s///p print even if -n was specified. * sed.c (compile_string): Changed the type of this function to fix a compile warning. Wed Nov 4 17:15:34 1992 Tom Lord (lord@unix7.andrew.cmu.edu) * sed.c (main): Initialize the hold area to contain "\n" instead of "". In execute_program, all lines are expected to be newline terminated. Also, if H is the first command in the script, the result is a pattern buffer that begins with a blank line. Thanks to pinard@iro.umontreal.ca (Francois Pinard) for pointing out this and many other bugs. * sed.c (execute_program): Fixed a case of `D' command. Thanks Chris Weber * sed.c: added new tests of no_default_output to make -n work. Thanks Andrew Herbert * sed.c, configure.in,Makefile.in: autoconfed bcopy and const. Thanks "J.T. Conklin" * sed.c: made prog_cur, prog_start, and prog_end unsigned so that users could write `sed -e s/ÿ/foo/g'. Tue Oct 13 00:04:05 1992 Tom Lord (lord@unix3.andrew.cmu.edu) * sed.c (execute_program): fixed the cycling behavior of 'D' * sed.c: integrated patch that closes files * sed.c: changed regexp syntax Fri May 22 15:11:12 1992 Tom Lord (lord at moriarty.bh.andrew.cmu.edu) * regex.c: this is not my change, but a pointer to the fact that karl@gnu fixed some regexp bugs that were plaguing sed. Thu Apr 30 13:02:21 1992 Tom Lord (lord at unix3.andrew.cmu.edu) * sed.c (compile_program, execute_program) subprograms are now compiled with an explicit continuation ;) return_v and return_i in struct vector. execute_program no longer recurses to execute subprograms (case '{') and now understands a return instruction (case '{'). Tue Apr 28 17:13:04 1992 Tom Lord (lord at unix7.andrew.cmu.edu) * sed.c (compile_address) added \?regexp? syntax for addresses. * sed.c (main) added {} intervals to the obscure regexp syntax. * sed.c (compile_program) after calling compile_address, normalize numeric addresses (make a2.addr_number > a1.addr_number). This is necessary because line numbers must match exactly, but sed does not try to match a2 until after a1 has matched, yet a1,a2 where a2 <= a1 is defined to be equivelent to a1,a1+1 Sat Feb 29 10:55:54 1992 David J. MacKenzie (djm@nutrimat) * sed.c (usage): Document long options as starting with `--'. Mon Dec 9 23:56:40 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu) * sed.c: Include sys/types.h, for new regex.h. Tue Nov 5 02:16:01 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu) * utils.c: Change NO_VFPRINTF to VPRINTF_MISSING, for compatibility with autoconf. Mon Sep 2 22:02:40 1991 David J. MacKenzie (djm at apple-gunkies) * sed.c (compile_regex): Treat \ as a normal character when in a char class. Thu Aug 8 00:15:33 1991 David J. MacKenzie (djm at bleen) * Version 1.08. * sed.c (compile_filename): If reading a file fails, read /dev/null instead. It's what Unix and POSIX do, effectively. * sed.c (compile_regex): The 'slash' character doesn't terminate the regex if it's in a character class. * sed.c (main): If given no args, or bad option, print usage message. (usage): New function. * sed.c (execute_program): Amount written for 'P' command was wrong. From stephend@ksr.com (Stephen Davis). Wed Aug 7 16:51:14 1991 David J. MacKenzie (djm at apple-gunkies) * sed.c (append_pattern_space): Check for buffer full before instead of after writing to buffer. Don't need to test for EOF initially anymore, due to the next change. (execute_program): For 'n' and 'N' commands, if eof is reached in input, quit the script like Unix sed does. Fix memory allocation problems for 'a' and 'r' commands. (compile_program): Fix off by one error in processing comments. All of the above are from Tapani Tarvainen, tarvaine@tukki.jyu.fi. * sed.c (setup_jump): Use isblank instead of testing for ' ' or '\t', for POSIX locales. * utils.c (ck_strdup): Renamed from strdup. * sed.c: Change callers. * sed.c, utils.c: Clean up declarations and includes to get rid of compiler warnings. * sed.c (main): Add long-named options. Don't complain if -n is given twice. Fri Aug 2 12:33:16 1991 David J. MacKenzie (djm at apple-gunkies) * configure: Support +srcdir arg. Create config.status and remove it and Makefile if interrupted while creating them. * Makefile.in: Change DESTDIR to prefix. Mon Jul 15 13:07:39 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu) * sed.c (main): Add -V option to print version number. (USAGE): Mention -V. Mon Jul 8 01:42:22 1991 David J. MacKenzie (djm at geech.gnu.ai.mit.edu) * sed.c: Define bcopy in terms of memcpy if STDC_HEADERS as well as if USG. (compile_filename): Don't glob filename (for 'r' and 'w' commands). Unix sed doesn't do it and it's not very useful, since it can only match 0 or 1 files. (execute_program): Change '\a' to 007 since some compilers don't recognize \a. * utils.c: New file; code moved from sed.c. * Replace Makefile with Makefile.in and configure. Update README. Tue Mar 26 13:00:48 EST 1991 Jay Fenlason (hack@gnu.ai.mit.edu) * sed.c (match_address) Added a trivial cast for portability. Mon Feb 25 13:23:29 EST 1991 Jay Fenlason (hack@ai.mit.edu) * sed.c Changed 's' command to work with latest version of regex() routines, which mysteriously changed somewhere in there. . . A one-line patch from David Eckelkamp (eckelkamp@mcc.com). Initialize the fastmap in the hopes that it'll make sed faster. Thu Feb 21 13:42:27 EST 1991 Jay Fenlason (hack@ai.mti.edu) * sed.c Change panic to compile with other __STDC__ compilers. Wed Jan 30 10:46:38 EST 1991 Jay Fenlason (hack@ai.mit.edu) * sed.c Changed version number. Made new release. Tue Nov 27 15:34:51 EST 1990 Jay Fenlason (hack@ai.mit.edu) * sed.c (setup_jump) Don't blow chunks if there isn't a label after a b or t command. (main) Don't panic if it a branch command doesn't have a label to branch to. (main) Collect all the -e arguments together and parse them all at once. This way, -e { -e mumble -e } will work. All these small patches from David Schmidt (davids@isc-br.isc-br.com) Tue Sep 11 12:51:37 EDT 1990 Jay Fenlason (hack@ai.mit.edu) * sed.c Changed some function forward declarations to use VOID * instead of char * Mon Jul 16 11:12:54 EDT 1990 Jay Fenlason (hack@ai.mit.edu) * sed.c (ck_malloc) Use malloc(1) instead of malloc(0) if given a request for zero bytes. Tue Jun 5 02:05:37 1990 David J. MacKenzie (djm at albert.ai.mit.edu) * sed.c: Remove excess newlines from calls to panic. Reformat some comments to fit in 79 columns. Base whether to use void * on __STDC__, not __GNU__. (main): Add missing arg when printing usage message. Print usage if given invalid arg. (panic) [__STDC__]: Add missing ", ...". (compile_filename): Print correct error message if glob_filename returns NULL. Thu Apr 5 21:41:12 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu) * sed.c (execute_program, case 'r'): When need to realloc append.text, multiply append.alloc by 2 instead of adding cur_cmd->x.cmd_txt.text_len. Tue Mar 6 15:55:35 EST 1990 Jay Fenlason (hack@ai.mit.edu) * sed.c (compile_regex) Allocate 10 bytes extra space needed by re_compile_pattern. Sun Feb 25 16:32:10 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu) * sed.c (execute_program, case 'l'): Print \00 instead of \0. Print backslash as \\ not \. Print \xx instead of /xx. Thu Feb 1 14:02:28 EST 1990 hack@wookumz * sed.c (memchr) Use () inside inner loop so it will work correctly. A two character patch from Robert A Bruce (rab@allspice.berkeley.edu) Wed Sep 27 18:47:39 EDT 1989 hack@ai.mit.edu * sed.c (compile_regex) New function. When compiling regex, turn ^ into \` and $ into \' so that they won't match on embedded newlines. UN*X pattern matching is a crock. (compile_program, compile_address) call compile_regex. Mon Sep 18 10:15:32 EDT 1989 hack@ai.mit.edu * sed.c (compile_program): define translate as unsigned char * so that y command will work on non-ascii characters. Changed version number to 1.06. Thu Sep 14 15:57:08 EDT 1989 hack@ai.mit.edu * sed.c (compile_program) Let programs use ; to terminate } as well as newline. (read_file) Print an error msg to stderr if it can't open an input file. Thu Mar 23 18:04:46 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) * Makefile, sed.c: Added new copyright notice. * Makefile: Make distributions which follow the symlinks. hack@ai.mit.edu 1.05 Fixed error in 'r' (now does things in the right order) 1.04 Fixed s/re/rep/[number] 1.03 Fixes from Mike Haertel for regexps that match the empty string, and for Ritchie stdio (non-sticky EOF) 1.02 Fixed 't', 'b', ':' to trim leading spaces and tabs Fixed \\ in replacement of 's' command Added comments 1.01 Added s/re/rep/[digits] added #n as first line of script added filename globbing added 'l' command All in the name of POSIX 1.00 Began (thinking about) distributing this file Local Variables: mode: indented-text left-margin: 8 version-control: never End: kbuild-3686/src/oldsed/intl/0000775000175000017500000000000015053010106015712 5ustar locutuslocutuskbuild-3686/src/oldsed/intl/localename.c0000664000175000017500000004650315053010106020166 0ustar locutuslocutus/* Determine the current selected locale. Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. 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, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Ulrich Drepper , 1995. */ /* Win32 code written by Tor Lillqvist . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #if defined _WIN32 || defined __WIN32__ # undef WIN32 /* avoid warning on mingw32 */ # define WIN32 #endif #ifdef WIN32 # define WIN32_LEAN_AND_MEAN # include /* Mingw headers don't have latest language and sublanguage codes. */ # ifndef LANG_AFRIKAANS # define LANG_AFRIKAANS 0x36 # endif # ifndef LANG_ALBANIAN # define LANG_ALBANIAN 0x1c # endif # ifndef LANG_ARABIC # define LANG_ARABIC 0x01 # endif # ifndef LANG_ARMENIAN # define LANG_ARMENIAN 0x2b # endif # ifndef LANG_ASSAMESE # define LANG_ASSAMESE 0x4d # endif # ifndef LANG_AZERI # define LANG_AZERI 0x2c # endif # ifndef LANG_BASQUE # define LANG_BASQUE 0x2d # endif # ifndef LANG_BELARUSIAN # define LANG_BELARUSIAN 0x23 # endif # ifndef LANG_BENGALI # define LANG_BENGALI 0x45 # endif # ifndef LANG_CATALAN # define LANG_CATALAN 0x03 # endif # ifndef LANG_ESTONIAN # define LANG_ESTONIAN 0x25 # endif # ifndef LANG_FAEROESE # define LANG_FAEROESE 0x38 # endif # ifndef LANG_FARSI # define LANG_FARSI 0x29 # endif # ifndef LANG_GEORGIAN # define LANG_GEORGIAN 0x37 # endif # ifndef LANG_GUJARATI # define LANG_GUJARATI 0x47 # endif # ifndef LANG_HEBREW # define LANG_HEBREW 0x0d # endif # ifndef LANG_HINDI # define LANG_HINDI 0x39 # endif # ifndef LANG_INDONESIAN # define LANG_INDONESIAN 0x21 # endif # ifndef LANG_KANNADA # define LANG_KANNADA 0x4b # endif # ifndef LANG_KASHMIRI # define LANG_KASHMIRI 0x60 # endif # ifndef LANG_KAZAK # define LANG_KAZAK 0x3f # endif # ifndef LANG_KONKANI # define LANG_KONKANI 0x57 # endif # ifndef LANG_LATVIAN # define LANG_LATVIAN 0x26 # endif # ifndef LANG_LITHUANIAN # define LANG_LITHUANIAN 0x27 # endif # ifndef LANG_MACEDONIAN # define LANG_MACEDONIAN 0x2f # endif # ifndef LANG_MALAY # define LANG_MALAY 0x3e # endif # ifndef LANG_MALAYALAM # define LANG_MALAYALAM 0x4c # endif # ifndef LANG_MANIPURI # define LANG_MANIPURI 0x58 # endif # ifndef LANG_MARATHI # define LANG_MARATHI 0x4e # endif # ifndef LANG_NEPALI # define LANG_NEPALI 0x61 # endif # ifndef LANG_ORIYA # define LANG_ORIYA 0x48 # endif # ifndef LANG_PUNJABI # define LANG_PUNJABI 0x46 # endif # ifndef LANG_SANSKRIT # define LANG_SANSKRIT 0x4f # endif # ifndef LANG_SERBIAN # define LANG_SERBIAN 0x1a # endif # ifndef LANG_SINDHI # define LANG_SINDHI 0x59 # endif # ifndef LANG_SLOVAK # define LANG_SLOVAK 0x1b # endif # ifndef LANG_SWAHILI # define LANG_SWAHILI 0x41 # endif # ifndef LANG_SORBIAN # define LANG_SORBIAN 0x2e # endif # ifndef LANG_TAMIL # define LANG_TAMIL 0x49 # endif # ifndef LANG_TATAR # define LANG_TATAR 0x44 # endif # ifndef LANG_TELUGU # define LANG_TELUGU 0x4a # endif # ifndef LANG_THAI # define LANG_THAI 0x1e # endif # ifndef LANG_UKRAINIAN # define LANG_UKRAINIAN 0x22 # endif # ifndef LANG_URDU # define LANG_URDU 0x20 # endif # ifndef LANG_UZBEK # define LANG_UZBEK 0x43 # endif # ifndef LANG_VIETNAMESE # define LANG_VIETNAMESE 0x2a # endif # ifndef SUBLANG_ARABIC_SAUDI_ARABIA # define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 # endif # ifndef SUBLANG_ARABIC_IRAQ # define SUBLANG_ARABIC_IRAQ 0x02 # endif # ifndef SUBLANG_ARABIC_EGYPT # define SUBLANG_ARABIC_EGYPT 0x03 # endif # ifndef SUBLANG_ARABIC_LIBYA # define SUBLANG_ARABIC_LIBYA 0x04 # endif # ifndef SUBLANG_ARABIC_ALGERIA # define SUBLANG_ARABIC_ALGERIA 0x05 # endif # ifndef SUBLANG_ARABIC_MOROCCO # define SUBLANG_ARABIC_MOROCCO 0x06 # endif # ifndef SUBLANG_ARABIC_TUNISIA # define SUBLANG_ARABIC_TUNISIA 0x07 # endif # ifndef SUBLANG_ARABIC_OMAN # define SUBLANG_ARABIC_OMAN 0x08 # endif # ifndef SUBLANG_ARABIC_YEMEN # define SUBLANG_ARABIC_YEMEN 0x09 # endif # ifndef SUBLANG_ARABIC_SYRIA # define SUBLANG_ARABIC_SYRIA 0x0a # endif # ifndef SUBLANG_ARABIC_JORDAN # define SUBLANG_ARABIC_JORDAN 0x0b # endif # ifndef SUBLANG_ARABIC_LEBANON # define SUBLANG_ARABIC_LEBANON 0x0c # endif # ifndef SUBLANG_ARABIC_KUWAIT # define SUBLANG_ARABIC_KUWAIT 0x0d # endif # ifndef SUBLANG_ARABIC_UAE # define SUBLANG_ARABIC_UAE 0x0e # endif # ifndef SUBLANG_ARABIC_BAHRAIN # define SUBLANG_ARABIC_BAHRAIN 0x0f # endif # ifndef SUBLANG_ARABIC_QATAR # define SUBLANG_ARABIC_QATAR 0x10 # endif # ifndef SUBLANG_AZERI_LATIN # define SUBLANG_AZERI_LATIN 0x01 # endif # ifndef SUBLANG_AZERI_CYRILLIC # define SUBLANG_AZERI_CYRILLIC 0x02 # endif # ifndef SUBLANG_CHINESE_MACAU # define SUBLANG_CHINESE_MACAU 0x05 # endif # ifndef SUBLANG_ENGLISH_SOUTH_AFRICA # define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07 # endif # ifndef SUBLANG_ENGLISH_JAMAICA # define SUBLANG_ENGLISH_JAMAICA 0x08 # endif # ifndef SUBLANG_ENGLISH_CARIBBEAN # define SUBLANG_ENGLISH_CARIBBEAN 0x09 # endif # ifndef SUBLANG_ENGLISH_BELIZE # define SUBLANG_ENGLISH_BELIZE 0x0a # endif # ifndef SUBLANG_ENGLISH_TRINIDAD # define SUBLANG_ENGLISH_TRINIDAD 0x0b # endif # ifndef SUBLANG_ENGLISH_ZIMBABWE # define SUBLANG_ENGLISH_ZIMBABWE 0x0c # endif # ifndef SUBLANG_ENGLISH_PHILIPPINES # define SUBLANG_ENGLISH_PHILIPPINES 0x0d # endif # ifndef SUBLANG_FRENCH_LUXEMBOURG # define SUBLANG_FRENCH_LUXEMBOURG 0x05 # endif # ifndef SUBLANG_FRENCH_MONACO # define SUBLANG_FRENCH_MONACO 0x06 # endif # ifndef SUBLANG_GERMAN_LUXEMBOURG # define SUBLANG_GERMAN_LUXEMBOURG 0x04 # endif # ifndef SUBLANG_GERMAN_LIECHTENSTEIN # define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 # endif # ifndef SUBLANG_KASHMIRI_INDIA # define SUBLANG_KASHMIRI_INDIA 0x02 # endif # ifndef SUBLANG_MALAY_MALAYSIA # define SUBLANG_MALAY_MALAYSIA 0x01 # endif # ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM # define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 # endif # ifndef SUBLANG_NEPALI_INDIA # define SUBLANG_NEPALI_INDIA 0x02 # endif # ifndef SUBLANG_SERBIAN_LATIN # define SUBLANG_SERBIAN_LATIN 0x02 # endif # ifndef SUBLANG_SERBIAN_CYRILLIC # define SUBLANG_SERBIAN_CYRILLIC 0x03 # endif # ifndef SUBLANG_SPANISH_GUATEMALA # define SUBLANG_SPANISH_GUATEMALA 0x04 # endif # ifndef SUBLANG_SPANISH_COSTA_RICA # define SUBLANG_SPANISH_COSTA_RICA 0x05 # endif # ifndef SUBLANG_SPANISH_PANAMA # define SUBLANG_SPANISH_PANAMA 0x06 # endif # ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC # define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07 # endif # ifndef SUBLANG_SPANISH_VENEZUELA # define SUBLANG_SPANISH_VENEZUELA 0x08 # endif # ifndef SUBLANG_SPANISH_COLOMBIA # define SUBLANG_SPANISH_COLOMBIA 0x09 # endif # ifndef SUBLANG_SPANISH_PERU # define SUBLANG_SPANISH_PERU 0x0a # endif # ifndef SUBLANG_SPANISH_ARGENTINA # define SUBLANG_SPANISH_ARGENTINA 0x0b # endif # ifndef SUBLANG_SPANISH_ECUADOR # define SUBLANG_SPANISH_ECUADOR 0x0c # endif # ifndef SUBLANG_SPANISH_CHILE # define SUBLANG_SPANISH_CHILE 0x0d # endif # ifndef SUBLANG_SPANISH_URUGUAY # define SUBLANG_SPANISH_URUGUAY 0x0e # endif # ifndef SUBLANG_SPANISH_PARAGUAY # define SUBLANG_SPANISH_PARAGUAY 0x0f # endif # ifndef SUBLANG_SPANISH_BOLIVIA # define SUBLANG_SPANISH_BOLIVIA 0x10 # endif # ifndef SUBLANG_SPANISH_EL_SALVADOR # define SUBLANG_SPANISH_EL_SALVADOR 0x11 # endif # ifndef SUBLANG_SPANISH_HONDURAS # define SUBLANG_SPANISH_HONDURAS 0x12 # endif # ifndef SUBLANG_SPANISH_NICARAGUA # define SUBLANG_SPANISH_NICARAGUA 0x13 # endif # ifndef SUBLANG_SPANISH_PUERTO_RICO # define SUBLANG_SPANISH_PUERTO_RICO 0x14 # endif # ifndef SUBLANG_SWEDISH_FINLAND # define SUBLANG_SWEDISH_FINLAND 0x02 # endif # ifndef SUBLANG_URDU_PAKISTAN # define SUBLANG_URDU_PAKISTAN 0x01 # endif # ifndef SUBLANG_URDU_INDIA # define SUBLANG_URDU_INDIA 0x02 # endif # ifndef SUBLANG_UZBEK_LATIN # define SUBLANG_UZBEK_LATIN 0x01 # endif # ifndef SUBLANG_UZBEK_CYRILLIC # define SUBLANG_UZBEK_CYRILLIC 0x02 # endif #endif /* XPG3 defines the result of 'setlocale (category, NULL)' as: "Directs 'setlocale()' to query 'category' and return the current setting of 'local'." However it does not specify the exact format. Neither do SUSV2 and ISO C 99. So we can use this feature only on selected systems (e.g. those using GNU C Library). */ #if defined _LIBC || (defined __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 2) # define HAVE_LOCALE_NULL #endif /* Determine the current locale's name, and canonicalize it into XPG syntax language[_territory[.codeset]][@modifier] The codeset part in the result is not reliable; the locale_charset() should be used for codeset information instead. The result must not be freed; it is statically allocated. */ const char * _nl_locale_name (category, categoryname) int category; const char *categoryname; { const char *retval; #ifndef WIN32 /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'. On some systems this can be done by the 'setlocale' function itself. */ # if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL retval = setlocale (category, NULL); # else /* Setting of LC_ALL overwrites all other. */ retval = getenv ("LC_ALL"); if (retval == NULL || retval[0] == '\0') { /* Next comes the name of the desired category. */ retval = getenv (categoryname); if (retval == NULL || retval[0] == '\0') { /* Last possibility is the LANG environment variable. */ retval = getenv ("LANG"); if (retval == NULL || retval[0] == '\0') /* We use C as the default domain. POSIX says this is implementation defined. */ retval = "C"; } } # endif return retval; #else /* WIN32 */ /* Return an XPG style locale name language[_territory][@modifier]. Don't even bother determining the codeset; it's not useful in this context, because message catalogs are not specific to a single codeset. */ LCID lcid; LANGID langid; int primary, sub; /* Let the user override the system settings through environment variables, as on POSIX systems. */ retval = getenv ("LC_ALL"); if (retval != NULL && retval[0] != '\0') return retval; retval = getenv (categoryname); if (retval != NULL && retval[0] != '\0') return retval; retval = getenv ("LANG"); if (retval != NULL && retval[0] != '\0') return retval; /* Use native Win32 API locale ID. */ lcid = GetThreadLocale (); /* Strip off the sorting rules, keep only the language part. */ langid = LANGIDFROMLCID (lcid); /* Split into language and territory part. */ primary = PRIMARYLANGID (langid); sub = SUBLANGID (langid); switch (primary) { case LANG_AFRIKAANS: return "af_ZA"; case LANG_ALBANIAN: return "sq_AL"; case LANG_ARABIC: switch (sub) { case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA"; case SUBLANG_ARABIC_IRAQ: return "ar_IQ"; case SUBLANG_ARABIC_EGYPT: return "ar_EG"; case SUBLANG_ARABIC_LIBYA: return "ar_LY"; case SUBLANG_ARABIC_ALGERIA: return "ar_DZ"; case SUBLANG_ARABIC_MOROCCO: return "ar_MA"; case SUBLANG_ARABIC_TUNISIA: return "ar_TN"; case SUBLANG_ARABIC_OMAN: return "ar_OM"; case SUBLANG_ARABIC_YEMEN: return "ar_YE"; case SUBLANG_ARABIC_SYRIA: return "ar_SY"; case SUBLANG_ARABIC_JORDAN: return "ar_JO"; case SUBLANG_ARABIC_LEBANON: return "ar_LB"; case SUBLANG_ARABIC_KUWAIT: return "ar_KW"; case SUBLANG_ARABIC_UAE: return "ar_AE"; case SUBLANG_ARABIC_BAHRAIN: return "ar_BH"; case SUBLANG_ARABIC_QATAR: return "ar_QA"; } return "ar"; case LANG_ARMENIAN: return "hy_AM"; case LANG_ASSAMESE: return "as_IN"; case LANG_AZERI: switch (sub) { /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */ case SUBLANG_AZERI_LATIN: return "az_AZ@latin"; case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic"; } return "az"; case LANG_BASQUE: return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */ case LANG_BELARUSIAN: return "be_BY"; case LANG_BENGALI: return "bn_IN"; case LANG_BULGARIAN: return "bg_BG"; case LANG_CATALAN: return "ca_ES"; case LANG_CHINESE: switch (sub) { case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW"; case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN"; case SUBLANG_CHINESE_HONGKONG: return "zh_HK"; case SUBLANG_CHINESE_SINGAPORE: return "zh_SG"; case SUBLANG_CHINESE_MACAU: return "zh_MO"; } return "zh"; case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN * What used to be called Serbo-Croatian * should really now be two separate * languages because of political reasons. * (Says tml, who knows nothing about Serbian * or Croatian.) * (I can feel those flames coming already.) */ switch (sub) { /* FIXME: How to distinguish Croatian and Latin Serbian locales? */ case SUBLANG_SERBIAN_LATIN: return "sr_YU"; case SUBLANG_SERBIAN_CYRILLIC: return "sr_YU@cyrillic"; default: return "hr_HR"; } case LANG_CZECH: return "cs_CZ"; case LANG_DANISH: return "da_DK"; case LANG_DUTCH: switch (sub) { case SUBLANG_DUTCH: return "nl_NL"; case SUBLANG_DUTCH_BELGIAN: return "nl_BE"; } return "nl"; case LANG_ENGLISH: switch (sub) { /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought * English was the language spoken in England. * Oh well. */ case SUBLANG_ENGLISH_US: return "en_US"; case SUBLANG_ENGLISH_UK: return "en_GB"; case SUBLANG_ENGLISH_AUS: return "en_AU"; case SUBLANG_ENGLISH_CAN: return "en_CA"; case SUBLANG_ENGLISH_NZ: return "en_NZ"; case SUBLANG_ENGLISH_EIRE: return "en_IE"; case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA"; case SUBLANG_ENGLISH_JAMAICA: return "en_JM"; case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */ case SUBLANG_ENGLISH_BELIZE: return "en_BZ"; case SUBLANG_ENGLISH_TRINIDAD: return "en_TT"; case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW"; case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH"; } return "en"; case LANG_ESTONIAN: return "et_EE"; case LANG_FAEROESE: return "fo_FO"; case LANG_FARSI: return "fa_IR"; case LANG_FINNISH: return "fi_FI"; case LANG_FRENCH: switch (sub) { case SUBLANG_FRENCH: return "fr_FR"; case SUBLANG_FRENCH_BELGIAN: return "fr_BE"; case SUBLANG_FRENCH_CANADIAN: return "fr_CA"; case SUBLANG_FRENCH_SWISS: return "fr_CH"; case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU"; case SUBLANG_FRENCH_MONACO: return "fr_MC"; } return "fr"; case LANG_GEORGIAN: return "ka_GE"; case LANG_GERMAN: switch (sub) { case SUBLANG_GERMAN: return "de_DE"; case SUBLANG_GERMAN_SWISS: return "de_CH"; case SUBLANG_GERMAN_AUSTRIAN: return "de_AT"; case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU"; case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI"; } return "de"; case LANG_GREEK: return "el_GR"; case LANG_GUJARATI: return "gu_IN"; case LANG_HEBREW: return "he_IL"; case LANG_HINDI: return "hi_IN"; case LANG_HUNGARIAN: return "hu_HU"; case LANG_ICELANDIC: return "is_IS"; case LANG_INDONESIAN: return "id_ID"; case LANG_ITALIAN: switch (sub) { case SUBLANG_ITALIAN: return "it_IT"; case SUBLANG_ITALIAN_SWISS: return "it_CH"; } return "it"; case LANG_JAPANESE: return "ja_JP"; case LANG_KANNADA: return "kn_IN"; case LANG_KASHMIRI: switch (sub) { case SUBLANG_DEFAULT: return "ks_PK"; case SUBLANG_KASHMIRI_INDIA: return "ks_IN"; } return "ks"; case LANG_KAZAK: return "kk_KZ"; case LANG_KONKANI: /* FIXME: Adjust this when such locales appear on Unix. */ return "kok_IN"; case LANG_KOREAN: return "ko_KR"; case LANG_LATVIAN: return "lv_LV"; case LANG_LITHUANIAN: return "lt_LT"; case LANG_MACEDONIAN: return "mk_MK"; case LANG_MALAY: switch (sub) { case SUBLANG_MALAY_MALAYSIA: return "ms_MY"; case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN"; } return "ms"; case LANG_MALAYALAM: return "ml_IN"; case LANG_MANIPURI: /* FIXME: Adjust this when such locales appear on Unix. */ return "mni_IN"; case LANG_MARATHI: return "mr_IN"; case LANG_NEPALI: switch (sub) { case SUBLANG_DEFAULT: return "ne_NP"; case SUBLANG_NEPALI_INDIA: return "ne_IN"; } return "ne"; case LANG_NORWEGIAN: switch (sub) { case SUBLANG_NORWEGIAN_BOKMAL: return "no_NO"; case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO"; } return "no"; case LANG_ORIYA: return "or_IN"; case LANG_POLISH: return "pl_PL"; case LANG_PORTUGUESE: switch (sub) { case SUBLANG_PORTUGUESE: return "pt_PT"; /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT. Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */ case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR"; } return "pt"; case LANG_PUNJABI: return "pa_IN"; case LANG_ROMANIAN: return "ro_RO"; case LANG_RUSSIAN: return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA". */ case LANG_SANSKRIT: return "sa_IN"; case LANG_SINDHI: return "sd"; case LANG_SLOVAK: return "sk_SK"; case LANG_SLOVENIAN: return "sl_SI"; case LANG_SORBIAN: /* FIXME: Adjust this when such locales appear on Unix. */ return "wen_DE"; case LANG_SPANISH: switch (sub) { case SUBLANG_SPANISH: return "es_ES"; case SUBLANG_SPANISH_MEXICAN: return "es_MX"; case SUBLANG_SPANISH_MODERN: return "es_ES@modern"; /* not seen on Unix */ case SUBLANG_SPANISH_GUATEMALA: return "es_GT"; case SUBLANG_SPANISH_COSTA_RICA: return "es_CR"; case SUBLANG_SPANISH_PANAMA: return "es_PA"; case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO"; case SUBLANG_SPANISH_VENEZUELA: return "es_VE"; case SUBLANG_SPANISH_COLOMBIA: return "es_CO"; case SUBLANG_SPANISH_PERU: return "es_PE"; case SUBLANG_SPANISH_ARGENTINA: return "es_AR"; case SUBLANG_SPANISH_ECUADOR: return "es_EC"; case SUBLANG_SPANISH_CHILE: return "es_CL"; case SUBLANG_SPANISH_URUGUAY: return "es_UY"; case SUBLANG_SPANISH_PARAGUAY: return "es_PY"; case SUBLANG_SPANISH_BOLIVIA: return "es_BO"; case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV"; case SUBLANG_SPANISH_HONDURAS: return "es_HN"; case SUBLANG_SPANISH_NICARAGUA: return "es_NI"; case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR"; } return "es"; case LANG_SWAHILI: return "sw"; case LANG_SWEDISH: switch (sub) { case SUBLANG_DEFAULT: return "sv_SE"; case SUBLANG_SWEDISH_FINLAND: return "sv_FI"; } return "sv"; case LANG_TAMIL: return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */ case LANG_TATAR: return "tt"; case LANG_TELUGU: return "te_IN"; case LANG_THAI: return "th_TH"; case LANG_TURKISH: return "tr_TR"; case LANG_UKRAINIAN: return "uk_UA"; case LANG_URDU: switch (sub) { case SUBLANG_URDU_PAKISTAN: return "ur_PK"; case SUBLANG_URDU_INDIA: return "ur_IN"; } return "ur"; case LANG_UZBEK: switch (sub) { /* FIXME: Adjust this when Uzbek locales appear on Unix. */ case SUBLANG_UZBEK_LATIN: return "uz_UZ@latin"; case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic"; } return "uz"; case LANG_VIETNAMESE: return "vi_VN"; default: return "C"; } #endif } kbuild-3686/src/oldsed/intl/localcharset.c0000664000175000017500000002070415053010105020524 0ustar locutuslocutus/* Determine a canonical name for the current locale's character encoding. Copyright (C) 2000-2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Bruno Haible . */ #ifdef HAVE_CONFIG_H # include #endif #if HAVE_STDDEF_H # include #endif #include #if HAVE_STRING_H # include #else # include #endif #if HAVE_STDLIB_H # include #endif #if defined _WIN32 || defined __WIN32__ # undef WIN32 /* avoid warning on mingw32 */ # define WIN32 #endif #if defined __EMX__ /* Assume EMX program runs on OS/2, even if compiled under DOS. */ # define OS2 #endif #if !defined WIN32 # if HAVE_LANGINFO_CODESET # include # else # if HAVE_SETLOCALE # include # endif # endif #elif defined WIN32 # define WIN32_LEAN_AND_MEAN # include #endif #if defined OS2 # define INCL_DOS # include #endif #if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ /* Win32, OS/2, DOS */ # define ISSLASH(C) ((C) == '/' || (C) == '\\') #endif #ifndef DIRECTORY_SEPARATOR # define DIRECTORY_SEPARATOR '/' #endif #ifndef ISSLASH # define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) #endif #ifdef HAVE_GETC_UNLOCKED # undef getc # define getc getc_unlocked #endif /* The following static variable is declared 'volatile' to avoid a possible multithread problem in the function get_charset_aliases. If we are running in a threaded environment, and if two threads initialize 'charset_aliases' simultaneously, both will produce the same value, and everything will be ok if the two assignments to 'charset_aliases' are atomic. But I don't know what will happen if the two assignments mix. */ #if __STDC__ != 1 # define volatile /* empty */ #endif /* Pointer to the contents of the charset.alias file, if it has already been read, else NULL. Its format is: ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0' */ static const char * volatile charset_aliases; /* Return a pointer to the contents of the charset.alias file. */ static const char * get_charset_aliases () { const char *cp; cp = charset_aliases; if (cp == NULL) { #if !defined WIN32 FILE *fp; const char *dir = LIBDIR; const char *base = "charset.alias"; char *file_name; /* Concatenate dir and base into freshly allocated file_name. */ { size_t dir_len = strlen (dir); size_t base_len = strlen (base); int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1])); file_name = (char *) malloc (dir_len + add_slash + base_len + 1); if (file_name != NULL) { memcpy (file_name, dir, dir_len); if (add_slash) file_name[dir_len] = DIRECTORY_SEPARATOR; memcpy (file_name + dir_len + add_slash, base, base_len + 1); } } if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL) /* Out of memory or file not found, treat it as empty. */ cp = ""; else { /* Parse the file's contents. */ int c; char buf1[50+1]; char buf2[50+1]; char *res_ptr = NULL; size_t res_size = 0; size_t l1, l2; for (;;) { c = getc (fp); if (c == EOF) break; if (c == '\n' || c == ' ' || c == '\t') continue; if (c == '#') { /* Skip comment, to end of line. */ do c = getc (fp); while (!(c == EOF || c == '\n')); if (c == EOF) break; continue; } ungetc (c, fp); if (fscanf (fp, "%50s %50s", buf1, buf2) < 2) break; l1 = strlen (buf1); l2 = strlen (buf2); if (res_size == 0) { res_size = l1 + 1 + l2 + 1; res_ptr = (char *) malloc (res_size + 1); } else { res_size += l1 + 1 + l2 + 1; res_ptr = (char *) realloc (res_ptr, res_size + 1); } if (res_ptr == NULL) { /* Out of memory. */ res_size = 0; break; } strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1); strcpy (res_ptr + res_size - (l2 + 1), buf2); } fclose (fp); if (res_size == 0) cp = ""; else { *(res_ptr + res_size) = '\0'; cp = res_ptr; } } if (file_name != NULL) free (file_name); #else /* To avoid the troubles of installing a separate file in the same directory as the DLL and of retrieving the DLL's directory at runtime, simply inline the aliases here. */ # if defined WIN32 cp = "CP936" "\0" "GBK" "\0" "CP1361" "\0" "JOHAB" "\0"; # endif #endif charset_aliases = cp; } return cp; } /* Determine the current locale's character encoding, and canonicalize it into one of the canonical names listed in config.charset. The result must not be freed; it is statically allocated. If the canonical name cannot be determined, the result is a non-canonical name. */ #ifdef STATIC STATIC #endif const char * locale_charset () { const char *codeset; const char *aliases; #if !(defined WIN32 || defined OS2) # if HAVE_LANGINFO_CODESET /* Most systems support nl_langinfo (CODESET) nowadays. */ codeset = nl_langinfo (CODESET); # else /* On old systems which lack it, use setlocale or getenv. */ const char *locale = NULL; /* But most old systems don't have a complete set of locales. Some (like SunOS 4 or DJGPP) have only the C locale. Therefore we don't use setlocale here; it would return "C" when it doesn't support the locale name the user has set. */ # if HAVE_SETLOCALE && 0 locale = setlocale (LC_CTYPE, NULL); # endif if (locale == NULL || locale[0] == '\0') { locale = getenv ("LC_ALL"); if (locale == NULL || locale[0] == '\0') { locale = getenv ("LC_CTYPE"); if (locale == NULL || locale[0] == '\0') locale = getenv ("LANG"); } } /* On some old systems, one used to set locale = "iso8859_1". On others, you set it to "language_COUNTRY.charset". In any case, we resolve it through the charset.alias file. */ codeset = locale; # endif #elif defined WIN32 static char buf[2 + 10 + 1]; /* Win32 has a function returning the locale's codepage as a number. */ sprintf (buf, "CP%u", GetACP ()); codeset = buf; #elif defined OS2 const char *locale; static char buf[2 + 10 + 1]; ULONG cp[3]; ULONG cplen; /* Allow user to override the codeset, as set in the operating system, with standard language environment variables. */ locale = getenv ("LC_ALL"); if (locale == NULL || locale[0] == '\0') { locale = getenv ("LC_CTYPE"); if (locale == NULL || locale[0] == '\0') locale = getenv ("LANG"); } if (locale != NULL && locale[0] != '\0') { /* If the locale name contains an encoding after the dot, return it. */ const char *dot = strchr (locale, '.'); if (dot != NULL) { const char *modifier; dot++; /* Look for the possible @... trailer and remove it, if any. */ modifier = strchr (dot, '@'); if (modifier == NULL) return dot; if (modifier - dot < sizeof (buf)) { memcpy (buf, dot, modifier - dot); buf [modifier - dot] = '\0'; return buf; } } /* Resolve through the charset.alias file. */ codeset = locale; } else { /* OS/2 has a function returning the locale's codepage as a number. */ if (DosQueryCp (sizeof (cp), cp, &cplen)) codeset = ""; else { sprintf (buf, "CP%u", cp[0]); codeset = buf; } } #endif if (codeset == NULL) /* The canonical name cannot be determined. */ codeset = ""; /* Resolve alias. */ for (aliases = get_charset_aliases (); *aliases != '\0'; aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1) if (strcmp (codeset, aliases) == 0 || (aliases[0] == '*' && aliases[1] == '\0')) { codeset = aliases + strlen (aliases) + 1; break; } return codeset; } kbuild-3686/src/oldsed/intl/plural.c0000664000175000017500000007750015053010105017365 0ustar locutuslocutus /* A Bison parser, made from plural.y by GNU Bison version 1.28 */ #define YYBISON 1 /* Identify Bison output. */ #define yyparse __gettextparse #define yylex __gettextlex #define yyerror __gettexterror #define yylval __gettextlval #define yychar __gettextchar #define yydebug __gettextdebug #define yynerrs __gettextnerrs #define EQUOP2 257 #define CMPOP2 258 #define ADDOP2 259 #define MULOP2 260 #define NUMBER 261 #line 1 "plural.y" /* Expression parsing for plural form selection. Copyright (C) 2000, 2001 Free Software Foundation, Inc. Written by Ulrich Drepper , 2000. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* The bison generated parser uses alloca. AIX 3 forces us to put this declaration at the beginning of the file. The declaration in bison's skeleton file comes too late. This must come before because may include arbitrary system headers. */ #if defined _AIX && !defined __GNUC__ #pragma alloca #endif #ifdef HAVE_CONFIG_H # include #endif #include #include #include "plural-exp.h" /* The main function generated by the parser is called __gettextparse, but we want it to be called PLURAL_PARSE. */ #ifndef _LIBC # define __gettextparse PLURAL_PARSE #endif #define YYLEX_PARAM &((struct parse_args *) arg)->cp #define YYPARSE_PARAM arg #line 49 "plural.y" typedef union { unsigned long int num; enum operator op; struct expression *exp; } YYSTYPE; #line 55 "plural.y" /* Prototypes for local functions. */ static struct expression *new_exp PARAMS ((int nargs, enum operator op, struct expression * const *args)); static inline struct expression *new_exp_0 PARAMS ((enum operator op)); static inline struct expression *new_exp_1 PARAMS ((enum operator op, struct expression *right)); static struct expression *new_exp_2 PARAMS ((enum operator op, struct expression *left, struct expression *right)); static inline struct expression *new_exp_3 PARAMS ((enum operator op, struct expression *bexp, struct expression *tbranch, struct expression *fbranch)); static int yylex PARAMS ((YYSTYPE *lval, const char **pexp)); static void yyerror PARAMS ((const char *str)); /* Allocation of expressions. */ static struct expression * new_exp (nargs, op, args) int nargs; enum operator op; struct expression * const *args; { int i; struct expression *newp; /* If any of the argument could not be malloc'ed, just return NULL. */ for (i = nargs - 1; i >= 0; i--) if (args[i] == NULL) goto fail; /* Allocate a new expression. */ newp = (struct expression *) malloc (sizeof (*newp)); if (newp != NULL) { newp->nargs = nargs; newp->operation = op; for (i = nargs - 1; i >= 0; i--) newp->val.args[i] = args[i]; return newp; } fail: for (i = nargs - 1; i >= 0; i--) FREE_EXPRESSION (args[i]); return NULL; } static inline struct expression * new_exp_0 (op) enum operator op; { return new_exp (0, op, NULL); } static inline struct expression * new_exp_1 (op, right) enum operator op; struct expression *right; { struct expression *args[1]; args[0] = right; return new_exp (1, op, args); } static struct expression * new_exp_2 (op, left, right) enum operator op; struct expression *left; struct expression *right; { struct expression *args[2]; args[0] = left; args[1] = right; return new_exp (2, op, args); } static inline struct expression * new_exp_3 (op, bexp, tbranch, fbranch) enum operator op; struct expression *bexp; struct expression *tbranch; struct expression *fbranch; { struct expression *args[3]; args[0] = bexp; args[1] = tbranch; args[2] = fbranch; return new_exp (3, op, args); } #include #ifndef __cplusplus #ifndef __STDC__ #define const #endif #endif #define YYFINAL 27 #define YYFLAG -32768 #define YYNTBASE 16 #define YYTRANSLATE(x) ((unsigned)(x) <= 261 ? yytranslate[x] : 18) static const char yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 5, 2, 14, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 6, 7, 8, 9, 11 }; #if YYDEBUG != 0 static const short yyprhs[] = { 0, 0, 2, 8, 12, 16, 20, 24, 28, 32, 35, 37, 39 }; static const short yyrhs[] = { 17, 0, 17, 3, 17, 12, 17, 0, 17, 4, 17, 0, 17, 5, 17, 0, 17, 6, 17, 0, 17, 7, 17, 0, 17, 8, 17, 0, 17, 9, 17, 0, 10, 17, 0, 13, 0, 11, 0, 14, 17, 15, 0 }; #endif #if YYDEBUG != 0 static const short yyrline[] = { 0, 174, 182, 186, 190, 194, 198, 202, 206, 210, 214, 218, 223 }; #endif #if YYDEBUG != 0 || defined (YYERROR_VERBOSE) static const char * const yytname[] = { "$","error","$undefined.","'?'","'|'", "'&'","EQUOP2","CMPOP2","ADDOP2","MULOP2","'!'","NUMBER","':'","'n'","'('","')'", "start","exp", NULL }; #endif static const short yyr1[] = { 0, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17 }; static const short yyr2[] = { 0, 1, 5, 3, 3, 3, 3, 3, 3, 2, 1, 1, 3 }; static const short yydefact[] = { 0, 0, 11, 10, 0, 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 3, 4, 5, 6, 7, 8, 0, 2, 0, 0, 0 }; static const short yydefgoto[] = { 25, 5 }; static const short yypact[] = { -9, -9,-32768,-32768, -9, 34,-32768, 11, -9, -9, -9, -9, -9, -9, -9,-32768, 24, 39, 43, 16, 26, -3,-32768, -9, 34, 21, 53,-32768 }; static const short yypgoto[] = {-32768, -1 }; #define YYLAST 53 static const short yytable[] = { 6, 1, 2, 7, 3, 4, 14, 16, 17, 18, 19, 20, 21, 22, 8, 9, 10, 11, 12, 13, 14, 26, 24, 12, 13, 14, 15, 8, 9, 10, 11, 12, 13, 14, 13, 14, 23, 8, 9, 10, 11, 12, 13, 14, 10, 11, 12, 13, 14, 11, 12, 13, 14, 27 }; static const short yycheck[] = { 1, 10, 11, 4, 13, 14, 9, 8, 9, 10, 11, 12, 13, 14, 3, 4, 5, 6, 7, 8, 9, 0, 23, 7, 8, 9, 15, 3, 4, 5, 6, 7, 8, 9, 8, 9, 12, 3, 4, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 6, 7, 8, 9, 0 }; #define YYPURE 1 /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ #line 3 "/usr/local/share/bison.simple" /* This file comes from bison-1.28. */ /* Skeleton output parser for bison, Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. 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, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ /* This is the parser code that is written into each bison parser when the %semantic_parser declaration is not specified in the grammar. It was written by Richard Stallman by simplifying the hairy parser used when %semantic_parser is specified. */ #ifndef YYSTACK_USE_ALLOCA #ifdef alloca #define YYSTACK_USE_ALLOCA #else /* alloca not defined */ #ifdef __GNUC__ #define YYSTACK_USE_ALLOCA #define alloca __builtin_alloca #else /* not GNU C. */ #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) #define YYSTACK_USE_ALLOCA #include #else /* not sparc */ /* We think this test detects Watcom and Microsoft C. */ /* This used to test MSDOS, but that is a bad idea since that symbol is in the user namespace. */ #if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) #if 0 /* No need for malloc.h, which pollutes the namespace; instead, just don't use alloca. */ #include #endif #else /* not MSDOS, or __TURBOC__ */ #if defined(_AIX) /* I don't know what this was needed for, but it pollutes the namespace. So I turned it off. rms, 2 May 1997. */ /* #include */ #pragma alloca #define YYSTACK_USE_ALLOCA #else /* not MSDOS, or __TURBOC__, or _AIX */ #if 0 #ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, and on HPUX 10. Eventually we can turn this on. */ #define YYSTACK_USE_ALLOCA #define alloca __builtin_alloca #endif /* __hpux */ #endif #endif /* not _AIX */ #endif /* not MSDOS, or __TURBOC__ */ #endif /* not sparc */ #endif /* not GNU C */ #endif /* alloca not defined */ #endif /* YYSTACK_USE_ALLOCA not defined */ #ifdef YYSTACK_USE_ALLOCA #define YYSTACK_ALLOC alloca #else #define YYSTACK_ALLOC malloc #endif /* Note: there must be only one dollar sign in this file. It is replaced by the list of actions, each action as one case of the switch. */ #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY -2 #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrlab1 /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(token, value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { yychar = (token), yylval = (value); \ yychar1 = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { yyerror ("syntax error: cannot back up"); YYERROR; } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 #ifndef YYPURE #define YYLEX yylex() #endif #ifdef YYPURE #ifdef YYLSP_NEEDED #ifdef YYLEX_PARAM #define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) #else #define YYLEX yylex(&yylval, &yylloc) #endif #else /* not YYLSP_NEEDED */ #ifdef YYLEX_PARAM #define YYLEX yylex(&yylval, YYLEX_PARAM) #else #define YYLEX yylex(&yylval) #endif #endif /* not YYLSP_NEEDED */ #endif /* If nonreentrant, generate the variables here */ #ifndef YYPURE int yychar; /* the lookahead symbol */ YYSTYPE yylval; /* the semantic value of the */ /* lookahead symbol */ #ifdef YYLSP_NEEDED YYLTYPE yylloc; /* location data for the lookahead */ /* symbol */ #endif int yynerrs; /* number of parse errors so far */ #endif /* not YYPURE */ #if YYDEBUG != 0 int yydebug; /* nonzero means print parse trace */ /* Since this is uninitialized, it does not stop multiple parsers from coexisting. */ #endif /* YYINITDEPTH indicates the initial size of the parser's stacks */ #ifndef YYINITDEPTH #define YYINITDEPTH 200 #endif /* YYMAXDEPTH is the maximum size the stacks can grow to (effective only if the built-in stack extension method is used). */ #if YYMAXDEPTH == 0 #undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH #define YYMAXDEPTH 10000 #endif /* Define __yy_memcpy. Note that the size argument should be passed with type unsigned int, because that is what the non-GCC definitions require. With GCC, __builtin_memcpy takes an arg of type size_t, but it can handle unsigned int. */ #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ #define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) #else /* not GNU C or C++ */ #ifndef __cplusplus /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void __yy_memcpy (to, from, count) char *to; char *from; unsigned int count; { register char *f = from; register char *t = to; register int i = count; while (i-- > 0) *t++ = *f++; } #else /* __cplusplus */ /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void __yy_memcpy (char *to, char *from, unsigned int count) { register char *t = to; register char *f = from; register int i = count; while (i-- > 0) *t++ = *f++; } #endif #endif #line 217 "/usr/local/share/bison.simple" /* The user can define YYPARSE_PARAM as the name of an argument to be passed into yyparse. The argument should have type void *. It should actually point to an object. Grammar actions can access the variable by casting it to the proper pointer type. */ #ifdef YYPARSE_PARAM #ifdef __cplusplus #define YYPARSE_PARAM_ARG void *YYPARSE_PARAM #define YYPARSE_PARAM_DECL #else /* not __cplusplus */ #define YYPARSE_PARAM_ARG YYPARSE_PARAM #define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; #endif /* not __cplusplus */ #else /* not YYPARSE_PARAM */ #define YYPARSE_PARAM_ARG #define YYPARSE_PARAM_DECL #endif /* not YYPARSE_PARAM */ /* Prevent warning if -Wstrict-prototypes. */ #ifdef __GNUC__ #ifdef YYPARSE_PARAM int yyparse (void *); #else int yyparse (void); #endif #endif int yyparse(YYPARSE_PARAM_ARG) YYPARSE_PARAM_DECL { register int yystate; register int yyn; register short *yyssp; register YYSTYPE *yyvsp; int yyerrstatus; /* number of tokens to shift before error messages enabled */ int yychar1 = 0; /* lookahead token as an internal (translated) token number */ short yyssa[YYINITDEPTH]; /* the state stack */ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ short *yyss = yyssa; /* refer to the stacks thru separate pointers */ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ #ifdef YYLSP_NEEDED YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ YYLTYPE *yyls = yylsa; YYLTYPE *yylsp; #define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) #else #define YYPOPSTACK (yyvsp--, yyssp--) #endif int yystacksize = YYINITDEPTH; int yyfree_stacks = 0; #ifdef YYPURE int yychar; YYSTYPE yylval; int yynerrs; #ifdef YYLSP_NEEDED YYLTYPE yylloc; #endif #endif YYSTYPE yyval; /* the variable used to return */ /* semantic values from the action */ /* routines */ int yylen; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Starting parse\n"); #endif yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss - 1; yyvsp = yyvs; #ifdef YYLSP_NEEDED yylsp = yyls; #endif /* Push a new state, which is found in yystate . */ /* In all cases, when you get here, the value and location stacks have just been pushed. so pushing a state here evens the stacks. */ yynewstate: *++yyssp = yystate; if (yyssp >= yyss + yystacksize - 1) { /* Give user a chance to reallocate the stack */ /* Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; short *yyss1 = yyss; #ifdef YYLSP_NEEDED YYLTYPE *yyls1 = yyls; #endif /* Get the current used size of the three stacks, in elements. */ int size = yyssp - yyss + 1; #ifdef yyoverflow /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. */ #ifdef YYLSP_NEEDED /* This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow("parser stack overflow", &yyss1, size * sizeof (*yyssp), &yyvs1, size * sizeof (*yyvsp), &yyls1, size * sizeof (*yylsp), &yystacksize); #else yyoverflow("parser stack overflow", &yyss1, size * sizeof (*yyssp), &yyvs1, size * sizeof (*yyvsp), &yystacksize); #endif yyss = yyss1; yyvs = yyvs1; #ifdef YYLSP_NEEDED yyls = yyls1; #endif #else /* no yyoverflow */ /* Extend the stack our own way. */ if (yystacksize >= YYMAXDEPTH) { yyerror("parser stack overflow"); if (yyfree_stacks) { free (yyss); free (yyvs); #ifdef YYLSP_NEEDED free (yyls); #endif } return 2; } yystacksize *= 2; if (yystacksize > YYMAXDEPTH) yystacksize = YYMAXDEPTH; #ifndef YYSTACK_USE_ALLOCA yyfree_stacks = 1; #endif yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); __yy_memcpy ((char *)yyss, (char *)yyss1, size * (unsigned int) sizeof (*yyssp)); yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); __yy_memcpy ((char *)yyvs, (char *)yyvs1, size * (unsigned int) sizeof (*yyvsp)); #ifdef YYLSP_NEEDED yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); __yy_memcpy ((char *)yyls, (char *)yyls1, size * (unsigned int) sizeof (*yylsp)); #endif #endif /* no yyoverflow */ yyssp = yyss + size - 1; yyvsp = yyvs + size - 1; #ifdef YYLSP_NEEDED yylsp = yyls + size - 1; #endif #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Stack size increased to %d\n", yystacksize); #endif if (yyssp >= yyss + yystacksize - 1) YYABORT; } #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Entering state %d\n", yystate); #endif goto yybackup; yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ /* yyresume: */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYFLAG) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* yychar is either YYEMPTY or YYEOF or a valid token in external form. */ if (yychar == YYEMPTY) { #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Reading a token: "); #endif yychar = YYLEX; } /* Convert token to internal form (in yychar1) for indexing tables with */ if (yychar <= 0) /* This means end of input. */ { yychar1 = 0; yychar = YYEOF; /* Don't call YYLEX any more */ #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Now at end of input.\n"); #endif } else { yychar1 = YYTRANSLATE(yychar); #if YYDEBUG != 0 if (yydebug) { fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); /* Give the individual parser a way to print the precise meaning of a token, for further debugging info. */ #ifdef YYPRINT YYPRINT (stderr, yychar, yylval); #endif fprintf (stderr, ")\n"); } #endif } yyn += yychar1; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) goto yydefault; yyn = yytable[yyn]; /* yyn is what to do for this token type in this state. Negative => reduce, -yyn is rule number. Positive => shift, yyn is new state. New state is final state => don't bother to shift, just return success. 0, or most negative number => error. */ if (yyn < 0) { if (yyn == YYFLAG) goto yyerrlab; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrlab; if (yyn == YYFINAL) YYACCEPT; /* Shift the lookahead token. */ #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); #endif /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; #ifdef YYLSP_NEEDED *++yylsp = yylloc; #endif /* count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; /* Do the default action for the current state. */ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; /* Do a reduction. yyn is the number of a rule to reduce with. */ yyreduce: yylen = yyr2[yyn]; if (yylen > 0) yyval = yyvsp[1-yylen]; /* implement default value of the action */ #if YYDEBUG != 0 if (yydebug) { int i; fprintf (stderr, "Reducing via rule %d (line %d), ", yyn, yyrline[yyn]); /* Print the symbols being reduced, and their result. */ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) fprintf (stderr, "%s ", yytname[yyrhs[i]]); fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); } #endif switch (yyn) { case 1: #line 175 "plural.y" { if (yyvsp[0].exp == NULL) YYABORT; ((struct parse_args *) arg)->res = yyvsp[0].exp; ; break;} case 2: #line 183 "plural.y" { yyval.exp = new_exp_3 (qmop, yyvsp[-4].exp, yyvsp[-2].exp, yyvsp[0].exp); ; break;} case 3: #line 187 "plural.y" { yyval.exp = new_exp_2 (lor, yyvsp[-2].exp, yyvsp[0].exp); ; break;} case 4: #line 191 "plural.y" { yyval.exp = new_exp_2 (land, yyvsp[-2].exp, yyvsp[0].exp); ; break;} case 5: #line 195 "plural.y" { yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); ; break;} case 6: #line 199 "plural.y" { yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); ; break;} case 7: #line 203 "plural.y" { yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); ; break;} case 8: #line 207 "plural.y" { yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); ; break;} case 9: #line 211 "plural.y" { yyval.exp = new_exp_1 (lnot, yyvsp[0].exp); ; break;} case 10: #line 215 "plural.y" { yyval.exp = new_exp_0 (var); ; break;} case 11: #line 219 "plural.y" { if ((yyval.exp = new_exp_0 (num)) != NULL) yyval.exp->val.num = yyvsp[0].num; ; break;} case 12: #line 224 "plural.y" { yyval.exp = yyvsp[-1].exp; ; break;} } /* the action file gets copied in in place of this dollarsign */ #line 543 "/usr/local/share/bison.simple" yyvsp -= yylen; yyssp -= yylen; #ifdef YYLSP_NEEDED yylsp -= yylen; #endif #if YYDEBUG != 0 if (yydebug) { short *ssp1 = yyss - 1; fprintf (stderr, "state stack now"); while (ssp1 != yyssp) fprintf (stderr, " %d", *++ssp1); fprintf (stderr, "\n"); } #endif *++yyvsp = yyval; #ifdef YYLSP_NEEDED yylsp++; if (yylen == 0) { yylsp->first_line = yylloc.first_line; yylsp->first_column = yylloc.first_column; yylsp->last_line = (yylsp-1)->last_line; yylsp->last_column = (yylsp-1)->last_column; yylsp->text = 0; } else { yylsp->last_line = (yylsp+yylen-1)->last_line; yylsp->last_column = (yylsp+yylen-1)->last_column; } #endif /* Now "shift" the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTBASE] + *yyssp; if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTBASE]; goto yynewstate; yyerrlab: /* here on detecting error */ if (! yyerrstatus) /* If not already recovering from an error, report this error. */ { ++yynerrs; #ifdef YYERROR_VERBOSE yyn = yypact[yystate]; if (yyn > YYFLAG && yyn < YYLAST) { int size = 0; char *msg; int x, count; count = 0; /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ for (x = (yyn < 0 ? -yyn : 0); x < (sizeof(yytname) / sizeof(char *)); x++) if (yycheck[x + yyn] == x) size += strlen(yytname[x]) + 15, count++; msg = (char *) malloc(size + 15); if (msg != 0) { strcpy(msg, "parse error"); if (count < 5) { count = 0; for (x = (yyn < 0 ? -yyn : 0); x < (sizeof(yytname) / sizeof(char *)); x++) if (yycheck[x + yyn] == x) { strcat(msg, count == 0 ? ", expecting `" : " or `"); strcat(msg, yytname[x]); strcat(msg, "'"); count++; } } yyerror(msg); free(msg); } else yyerror ("parse error; also virtual memory exceeded"); } else #endif /* YYERROR_VERBOSE */ yyerror("parse error"); } goto yyerrlab1; yyerrlab1: /* here on error raised explicitly by an action */ if (yyerrstatus == 3) { /* if just tried and failed to reuse lookahead token after an error, discard it. */ /* return failure if at end of input */ if (yychar == YYEOF) YYABORT; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); #endif yychar = YYEMPTY; } /* Else will try to reuse lookahead token after shifting the error token. */ yyerrstatus = 3; /* Each real token shifted decrements this */ goto yyerrhandle; yyerrdefault: /* current state does not do anything special for the error token. */ #if 0 /* This is wrong; only states that explicitly want error tokens should shift them. */ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ if (yyn) goto yydefault; #endif yyerrpop: /* pop the current state because it cannot handle the error token */ if (yyssp == yyss) YYABORT; yyvsp--; yystate = *--yyssp; #ifdef YYLSP_NEEDED yylsp--; #endif #if YYDEBUG != 0 if (yydebug) { short *ssp1 = yyss - 1; fprintf (stderr, "Error: state stack now"); while (ssp1 != yyssp) fprintf (stderr, " %d", *++ssp1); fprintf (stderr, "\n"); } #endif yyerrhandle: yyn = yypact[yystate]; if (yyn == YYFLAG) goto yyerrdefault; yyn += YYTERROR; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) goto yyerrdefault; yyn = yytable[yyn]; if (yyn < 0) { if (yyn == YYFLAG) goto yyerrpop; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrpop; if (yyn == YYFINAL) YYACCEPT; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Shifting error token, "); #endif *++yyvsp = yylval; #ifdef YYLSP_NEEDED *++yylsp = yylloc; #endif yystate = yyn; goto yynewstate; yyacceptlab: /* YYACCEPT comes here. */ if (yyfree_stacks) { free (yyss); free (yyvs); #ifdef YYLSP_NEEDED free (yyls); #endif } return 0; yyabortlab: /* YYABORT comes here. */ if (yyfree_stacks) { free (yyss); free (yyvs); #ifdef YYLSP_NEEDED free (yyls); #endif } return 1; } #line 229 "plural.y" void internal_function FREE_EXPRESSION (exp) struct expression *exp; { if (exp == NULL) return; /* Handle the recursive case. */ switch (exp->nargs) { case 3: FREE_EXPRESSION (exp->val.args[2]); /* FALLTHROUGH */ case 2: FREE_EXPRESSION (exp->val.args[1]); /* FALLTHROUGH */ case 1: FREE_EXPRESSION (exp->val.args[0]); /* FALLTHROUGH */ default: break; } free (exp); } static int yylex (lval, pexp) YYSTYPE *lval; const char **pexp; { const char *exp = *pexp; int result; while (1) { if (exp[0] == '\0') { *pexp = exp; return YYEOF; } if (exp[0] != ' ' && exp[0] != '\t') break; ++exp; } result = *exp++; switch (result) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { unsigned long int n = result - '0'; while (exp[0] >= '0' && exp[0] <= '9') { n *= 10; n += exp[0] - '0'; ++exp; } lval->num = n; result = NUMBER; } break; case '=': if (exp[0] == '=') { ++exp; lval->op = equal; result = EQUOP2; } else result = YYERRCODE; break; case '!': if (exp[0] == '=') { ++exp; lval->op = not_equal; result = EQUOP2; } break; case '&': case '|': if (exp[0] == result) ++exp; else result = YYERRCODE; break; case '<': if (exp[0] == '=') { ++exp; lval->op = less_or_equal; } else lval->op = less_than; result = CMPOP2; break; case '>': if (exp[0] == '=') { ++exp; lval->op = greater_or_equal; } else lval->op = greater_than; result = CMPOP2; break; case '*': lval->op = mult; result = MULOP2; break; case '/': lval->op = divide; result = MULOP2; break; case '%': lval->op = module; result = MULOP2; break; case '+': lval->op = plus; result = ADDOP2; break; case '-': lval->op = minus; result = ADDOP2; break; case 'n': case '?': case ':': case '(': case ')': /* Nothing, just return the character. */ break; case ';': case '\n': case '\0': /* Be safe and let the user call this function again. */ --exp; result = YYEOF; break; default: result = YYERRCODE; #if YYDEBUG != 0 --exp; #endif break; } *pexp = exp; return result; } static void yyerror (str) const char *str; { /* Do nothing. We don't print error messages here. */ } kbuild-3686/src/oldsed/intl/VERSION0000664000175000017500000000004615053010106016762 0ustar locutuslocutusGNU gettext library from gettext-0.11 kbuild-3686/src/oldsed/intl/ref-add.sin0000664000175000017500000000210515053010105017724 0ustar locutuslocutus# Add this package to a list of references stored in a text file. # # Copyright (C) 2000 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU Library General Public License as published # by the Free Software Foundation; either version 2, 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # # Written by Bruno Haible . # /^# Packages using this file: / { s/# Packages using this file:// ta :a s/ @PACKAGE@ / @PACKAGE@ / tb s/ $/ @PACKAGE@ / :b s/^/# Packages using this file:/ } kbuild-3686/src/oldsed/intl/os2compat.h0000664000175000017500000000301215053010106017766 0ustar locutuslocutus/* OS/2 compatibility defines. This file is intended to be included from config.h Copyright (C) 2001-2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* When included from os2compat.h we need all the original definitions */ #ifndef OS2_AWARE #undef LIBDIR #define LIBDIR _os2_libdir extern char *_os2_libdir; #undef LOCALEDIR #define LOCALEDIR _os2_localedir extern char *_os2_localedir; #undef LOCALE_ALIAS_PATH #define LOCALE_ALIAS_PATH _os2_localealiaspath extern char *_os2_localealiaspath; #endif #undef HAVE_STRCASECMP #define HAVE_STRCASECMP 1 #define strcasecmp stricmp #define strncasecmp strnicmp /* We have our own getenv() which works even if library is compiled as DLL */ #define getenv _nl_getenv /* Older versions of gettext used -1 as the value of LC_MESSAGES */ #define LC_MESSAGES_COMPAT (-1) kbuild-3686/src/oldsed/intl/loadinfo.h0000664000175000017500000000751515053010105017665 0ustar locutuslocutus/* Copyright (C) 1996-1999, 2000, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1996. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _LOADINFO_H #define _LOADINFO_H 1 /* Declarations of locale dependent catalog lookup functions. Implemented in localealias.c Possibly replace a locale name by another. explodename.c Split a locale name into its various fields. l10nflist.c Generate a list of filenames of possible message catalogs. finddomain.c Find and open the relevant message catalogs. The main function _nl_find_domain() in finddomain.c is declared in gettextP.h. */ #ifndef PARAMS # if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES # define PARAMS(args) args # else # define PARAMS(args) () # endif #endif #ifndef internal_function # define internal_function #endif /* Tell the compiler when a conditional or integer expression is almost always true or almost always false. */ #ifndef HAVE_BUILTIN_EXPECT # define __builtin_expect(expr, val) (expr) #endif /* Separator in PATH like lists of pathnames. */ #if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ /* Win32, OS/2, DOS */ # define PATH_SEPARATOR ';' #else /* Unix */ # define PATH_SEPARATOR ':' #endif /* Encoding of locale name parts. */ #define CEN_REVISION 1 #define CEN_SPONSOR 2 #define CEN_SPECIAL 4 #define XPG_NORM_CODESET 8 #define XPG_CODESET 16 #define TERRITORY 32 #define CEN_AUDIENCE 64 #define XPG_MODIFIER 128 #define CEN_SPECIFIC (CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE) #define XPG_SPECIFIC (XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER) struct loaded_l10nfile { const char *filename; int decided; const void *data; struct loaded_l10nfile *next; struct loaded_l10nfile *successor[1]; }; /* Normalize codeset name. There is no standard for the codeset names. Normalization allows the user to use any of the common names. The return value is dynamically allocated and has to be freed by the caller. */ extern const char *_nl_normalize_codeset PARAMS ((const char *codeset, size_t name_len)); extern struct loaded_l10nfile * _nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list, const char *dirlist, size_t dirlist_len, int mask, const char *language, const char *territory, const char *codeset, const char *normalized_codeset, const char *modifier, const char *special, const char *sponsor, const char *revision, const char *filename, int do_allocate)); extern const char *_nl_expand_alias PARAMS ((const char *name)); /* normalized_codeset is dynamically allocated and has to be freed by the caller. */ extern int _nl_explode_name PARAMS ((char *name, const char **language, const char **modifier, const char **territory, const char **codeset, const char **normalized_codeset, const char **special, const char **sponsor, const char **revision)); extern char *_nl_find_language PARAMS ((const char *name)); #endif /* loadinfo.h */ kbuild-3686/src/oldsed/intl/gettext.c0000664000175000017500000000354515053010105017550 0ustar locutuslocutus/* Implementation of gettext(3) function. Copyright (C) 1995, 1997, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifdef _LIBC # define __need_NULL # include #else # include /* Just for NULL. */ #endif #include "gettextP.h" #ifdef _LIBC # include #else # include "libgnuintl.h" #endif /* @@ end of prolog @@ */ /* Names for the libintl functions are a problem. They must not clash with existing names and they should follow ANSI C. But this source code is also used in GNU C Library where the names have a __ prefix. So we have to make a difference here. */ #ifdef _LIBC # define GETTEXT __gettext # define DCGETTEXT __dcgettext #else # define GETTEXT gettext__ # define DCGETTEXT dcgettext__ #endif /* Look up MSGID in the current default message catalog for the current LC_MESSAGES locale. If not found, returns MSGID itself (the default text). */ char * GETTEXT (msgid) const char *msgid; { return DCGETTEXT (NULL, msgid, LC_MESSAGES); } #ifdef _LIBC /* Alias for function name in GNU C Library. */ weak_alias (__gettext, gettext); #endif kbuild-3686/src/oldsed/intl/plural.y0000664000175000017500000001774015053010106017414 0ustar locutuslocutus%{ /* Expression parsing for plural form selection. Copyright (C) 2000, 2001 Free Software Foundation, Inc. Written by Ulrich Drepper , 2000. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* The bison generated parser uses alloca. AIX 3 forces us to put this declaration at the beginning of the file. The declaration in bison's skeleton file comes too late. This must come before because may include arbitrary system headers. */ #if defined _AIX && !defined __GNUC__ #pragma alloca #endif #ifdef HAVE_CONFIG_H # include #endif #include #include #include "plural-exp.h" /* The main function generated by the parser is called __gettextparse, but we want it to be called PLURAL_PARSE. */ #ifndef _LIBC # define __gettextparse PLURAL_PARSE #endif #define YYLEX_PARAM &((struct parse_args *) arg)->cp #define YYPARSE_PARAM arg %} %pure_parser %expect 7 %union { unsigned long int num; enum operator op; struct expression *exp; } %{ /* Prototypes for local functions. */ static struct expression *new_exp PARAMS ((int nargs, enum operator op, struct expression * const *args)); static inline struct expression *new_exp_0 PARAMS ((enum operator op)); static inline struct expression *new_exp_1 PARAMS ((enum operator op, struct expression *right)); static struct expression *new_exp_2 PARAMS ((enum operator op, struct expression *left, struct expression *right)); static inline struct expression *new_exp_3 PARAMS ((enum operator op, struct expression *bexp, struct expression *tbranch, struct expression *fbranch)); static int yylex PARAMS ((YYSTYPE *lval, const char **pexp)); static void yyerror PARAMS ((const char *str)); /* Allocation of expressions. */ static struct expression * new_exp (nargs, op, args) int nargs; enum operator op; struct expression * const *args; { int i; struct expression *newp; /* If any of the argument could not be malloc'ed, just return NULL. */ for (i = nargs - 1; i >= 0; i--) if (args[i] == NULL) goto fail; /* Allocate a new expression. */ newp = (struct expression *) malloc (sizeof (*newp)); if (newp != NULL) { newp->nargs = nargs; newp->operation = op; for (i = nargs - 1; i >= 0; i--) newp->val.args[i] = args[i]; return newp; } fail: for (i = nargs - 1; i >= 0; i--) FREE_EXPRESSION (args[i]); return NULL; } static inline struct expression * new_exp_0 (op) enum operator op; { return new_exp (0, op, NULL); } static inline struct expression * new_exp_1 (op, right) enum operator op; struct expression *right; { struct expression *args[1]; args[0] = right; return new_exp (1, op, args); } static struct expression * new_exp_2 (op, left, right) enum operator op; struct expression *left; struct expression *right; { struct expression *args[2]; args[0] = left; args[1] = right; return new_exp (2, op, args); } static inline struct expression * new_exp_3 (op, bexp, tbranch, fbranch) enum operator op; struct expression *bexp; struct expression *tbranch; struct expression *fbranch; { struct expression *args[3]; args[0] = bexp; args[1] = tbranch; args[2] = fbranch; return new_exp (3, op, args); } %} /* This declares that all operators have the same associativity and the precedence order as in C. See [Harbison, Steele: C, A Reference Manual]. There is no unary minus and no bitwise operators. Operators with the same syntactic behaviour have been merged into a single token, to save space in the array generated by bison. */ %right '?' /* ? */ %left '|' /* || */ %left '&' /* && */ %left EQUOP2 /* == != */ %left CMPOP2 /* < > <= >= */ %left ADDOP2 /* + - */ %left MULOP2 /* * / % */ %right '!' /* ! */ %token EQUOP2 CMPOP2 ADDOP2 MULOP2 %token NUMBER %type exp %% start: exp { if ($1 == NULL) YYABORT; ((struct parse_args *) arg)->res = $1; } ; exp: exp '?' exp ':' exp { $$ = new_exp_3 (qmop, $1, $3, $5); } | exp '|' exp { $$ = new_exp_2 (lor, $1, $3); } | exp '&' exp { $$ = new_exp_2 (land, $1, $3); } | exp EQUOP2 exp { $$ = new_exp_2 ($2, $1, $3); } | exp CMPOP2 exp { $$ = new_exp_2 ($2, $1, $3); } | exp ADDOP2 exp { $$ = new_exp_2 ($2, $1, $3); } | exp MULOP2 exp { $$ = new_exp_2 ($2, $1, $3); } | '!' exp { $$ = new_exp_1 (lnot, $2); } | 'n' { $$ = new_exp_0 (var); } | NUMBER { if (($$ = new_exp_0 (num)) != NULL) $$->val.num = $1; } | '(' exp ')' { $$ = $2; } ; %% void internal_function FREE_EXPRESSION (exp) struct expression *exp; { if (exp == NULL) return; /* Handle the recursive case. */ switch (exp->nargs) { case 3: FREE_EXPRESSION (exp->val.args[2]); /* FALLTHROUGH */ case 2: FREE_EXPRESSION (exp->val.args[1]); /* FALLTHROUGH */ case 1: FREE_EXPRESSION (exp->val.args[0]); /* FALLTHROUGH */ default: break; } free (exp); } static int yylex (lval, pexp) YYSTYPE *lval; const char **pexp; { const char *exp = *pexp; int result; while (1) { if (exp[0] == '\0') { *pexp = exp; return YYEOF; } if (exp[0] != ' ' && exp[0] != '\t') break; ++exp; } result = *exp++; switch (result) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { unsigned long int n = result - '0'; while (exp[0] >= '0' && exp[0] <= '9') { n *= 10; n += exp[0] - '0'; ++exp; } lval->num = n; result = NUMBER; } break; case '=': if (exp[0] == '=') { ++exp; lval->op = equal; result = EQUOP2; } else result = YYERRCODE; break; case '!': if (exp[0] == '=') { ++exp; lval->op = not_equal; result = EQUOP2; } break; case '&': case '|': if (exp[0] == result) ++exp; else result = YYERRCODE; break; case '<': if (exp[0] == '=') { ++exp; lval->op = less_or_equal; } else lval->op = less_than; result = CMPOP2; break; case '>': if (exp[0] == '=') { ++exp; lval->op = greater_or_equal; } else lval->op = greater_than; result = CMPOP2; break; case '*': lval->op = mult; result = MULOP2; break; case '/': lval->op = divide; result = MULOP2; break; case '%': lval->op = module; result = MULOP2; break; case '+': lval->op = plus; result = ADDOP2; break; case '-': lval->op = minus; result = ADDOP2; break; case 'n': case '?': case ':': case '(': case ')': /* Nothing, just return the character. */ break; case ';': case '\n': case '\0': /* Be safe and let the user call this function again. */ --exp; result = YYEOF; break; default: result = YYERRCODE; #if YYDEBUG != 0 --exp; #endif break; } *pexp = exp; return result; } static void yyerror (str) const char *str; { /* Do nothing. We don't print error messages here. */ } kbuild-3686/src/oldsed/intl/loadmsgcat.c0000664000175000017500000002751115053010105020201 0ustar locutuslocutus/* Load needed message catalogs. Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Tell glibc's to provide a prototype for mempcpy(). This must come before because may include , and once has been included, it's too late. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #ifdef __GNUC__ # define alloca __builtin_alloca # define HAVE_ALLOCA 1 #else # if defined HAVE_ALLOCA_H || defined _LIBC # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca char *alloca (); # endif # endif # endif #endif #include #include #if defined HAVE_UNISTD_H || defined _LIBC # include #endif #ifdef _LIBC # include # include #endif #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \ || (defined _LIBC && defined _POSIX_MAPPED_FILES) # include # undef HAVE_MMAP # define HAVE_MMAP 1 #else # undef HAVE_MMAP #endif #include "gmo.h" #include "gettextP.h" #include "plural-exp.h" #ifdef _LIBC # include "../locale/localeinfo.h" #endif /* @@ end of prolog @@ */ #ifdef _LIBC /* Rename the non ISO C functions. This is required by the standard because some ISO C functions will require linking with this object file and the name space must not be polluted. */ # define open __open # define close __close # define read __read # define mmap __mmap # define munmap __munmap #endif /* For those losing systems which don't have `alloca' we have to add some additional code emulating it. */ #ifdef HAVE_ALLOCA # define freea(p) /* nothing */ #else # define alloca(n) malloc (n) # define freea(p) free (p) #endif /* For systems that distinguish between text and binary I/O. O_BINARY is usually declared in . */ #if !defined O_BINARY && defined _O_BINARY /* For MSC-compatible compilers. */ # define O_BINARY _O_BINARY # define O_TEXT _O_TEXT #endif #ifdef __BEOS__ /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */ # undef O_BINARY # undef O_TEXT #endif /* On reasonable systems, binary I/O is the default. */ #ifndef O_BINARY # define O_BINARY 0 #endif /* We need a sign, whether a new catalog was loaded, which can be associated with all translations. This is important if the translations are cached by one of GCC's features. */ int _nl_msg_cat_cntr; /* Initialize the codeset dependent parts of an opened message catalog. Return the header entry. */ const char * internal_function _nl_init_domain_conv (domain_file, domain, domainbinding) struct loaded_l10nfile *domain_file; struct loaded_domain *domain; struct binding *domainbinding; { /* Find out about the character set the file is encoded with. This can be found (in textual form) in the entry "". If this entry does not exist or if this does not contain the `charset=' information, we will assume the charset matches the one the current locale and we don't have to perform any conversion. */ char *nullentry; size_t nullentrylen; /* Preinitialize fields, to avoid recursion during _nl_find_msg. */ domain->codeset_cntr = (domainbinding != NULL ? domainbinding->codeset_cntr : 0); #ifdef _LIBC domain->conv = (__gconv_t) -1; #else # if HAVE_ICONV domain->conv = (iconv_t) -1; # endif #endif domain->conv_tab = NULL; /* Get the header entry. */ nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen); if (nullentry != NULL) { #if defined _LIBC || HAVE_ICONV const char *charsetstr; charsetstr = strstr (nullentry, "charset="); if (charsetstr != NULL) { size_t len; char *charset; const char *outcharset; charsetstr += strlen ("charset="); len = strcspn (charsetstr, " \t\n"); charset = (char *) alloca (len + 1); # if defined _LIBC || HAVE_MEMPCPY *((char *) mempcpy (charset, charsetstr, len)) = '\0'; # else memcpy (charset, charsetstr, len); charset[len] = '\0'; # endif /* The output charset should normally be determined by the locale. But sometimes the locale is not used or not correctly set up, so we provide a possibility for the user to override this. Moreover, the value specified through bind_textdomain_codeset overrides both. */ if (domainbinding != NULL && domainbinding->codeset != NULL) outcharset = domainbinding->codeset; else { outcharset = getenv ("OUTPUT_CHARSET"); if (outcharset == NULL || outcharset[0] == '\0') { # ifdef _LIBC outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string; # else # if HAVE_ICONV extern const char *locale_charset PARAMS ((void)); outcharset = locale_charset (); # endif # endif } } # ifdef _LIBC /* We always want to use transliteration. */ outcharset = norm_add_slashes (outcharset, "TRANSLIT"); charset = norm_add_slashes (charset, NULL); if (__gconv_open (outcharset, charset, &domain->conv, GCONV_AVOID_NOCONV) != __GCONV_OK) domain->conv = (__gconv_t) -1; # else # if HAVE_ICONV /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5, we want to use transliteration. */ # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \ || _LIBICONV_VERSION >= 0x0105 len = strlen (outcharset); { char *tmp = (char *) alloca (len + 10 + 1); memcpy (tmp, outcharset, len); memcpy (tmp + len, "//TRANSLIT", 10 + 1); outcharset = tmp; } # endif domain->conv = iconv_open (outcharset, charset); # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \ || _LIBICONV_VERSION >= 0x0105 freea (outcharset); # endif # endif # endif freea (charset); } #endif /* _LIBC || HAVE_ICONV */ } return nullentry; } /* Frees the codeset dependent parts of an opened message catalog. */ void internal_function _nl_free_domain_conv (domain) struct loaded_domain *domain; { if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1) free (domain->conv_tab); #ifdef _LIBC if (domain->conv != (__gconv_t) -1) __gconv_close (domain->conv); #else # if HAVE_ICONV if (domain->conv != (iconv_t) -1) iconv_close (domain->conv); # endif #endif } /* Load the message catalogs specified by FILENAME. If it is no valid message catalog do nothing. */ void internal_function _nl_load_domain (domain_file, domainbinding) struct loaded_l10nfile *domain_file; struct binding *domainbinding; { int fd; size_t size; #ifdef _LIBC struct stat64 st; #else struct stat st; #endif struct mo_file_header *data = (struct mo_file_header *) -1; int use_mmap = 0; struct loaded_domain *domain; const char *nullentry; domain_file->decided = 1; domain_file->data = NULL; /* Note that it would be useless to store domainbinding in domain_file because domainbinding might be == NULL now but != NULL later (after a call to bind_textdomain_codeset). */ /* If the record does not represent a valid locale the FILENAME might be NULL. This can happen when according to the given specification the locale file name is different for XPG and CEN syntax. */ if (domain_file->filename == NULL) return; /* Try to open the addressed file. */ fd = open (domain_file->filename, O_RDONLY | O_BINARY); if (fd == -1) return; /* We must know about the size of the file. */ if ( #ifdef _LIBC __builtin_expect (fstat64 (fd, &st) != 0, 0) #else __builtin_expect (fstat (fd, &st) != 0, 0) #endif || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0) || __builtin_expect (size < sizeof (struct mo_file_header), 0)) { /* Something went wrong. */ close (fd); return; } #ifdef HAVE_MMAP /* Now we are ready to load the file. If mmap() is available we try this first. If not available or it failed we try to load it. */ data = (struct mo_file_header *) mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); if (__builtin_expect (data != (struct mo_file_header *) -1, 1)) { /* mmap() call was successful. */ close (fd); use_mmap = 1; } #endif /* If the data is not yet available (i.e. mmap'ed) we try to load it manually. */ if (data == (struct mo_file_header *) -1) { size_t to_read; char *read_ptr; data = (struct mo_file_header *) malloc (size); if (data == NULL) return; to_read = size; read_ptr = (char *) data; do { long int nb = (long int) read (fd, read_ptr, to_read); if (nb <= 0) { #ifdef EINTR if (nb == -1 && errno == EINTR) continue; #endif close (fd); return; } read_ptr += nb; to_read -= nb; } while (to_read > 0); close (fd); } /* Using the magic number we can test whether it really is a message catalog file. */ if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED, 0)) { /* The magic number is wrong: not a message catalog file. */ #ifdef HAVE_MMAP if (use_mmap) munmap ((caddr_t) data, size); else #endif free (data); return; } domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain)); if (domain == NULL) return; domain_file->data = domain; domain->data = (char *) data; domain->use_mmap = use_mmap; domain->mmap_size = size; domain->must_swap = data->magic != _MAGIC; /* Fill in the information about the available tables. */ switch (W (domain->must_swap, data->revision)) { case 0: domain->nstrings = W (domain->must_swap, data->nstrings); domain->orig_tab = (struct string_desc *) ((char *) data + W (domain->must_swap, data->orig_tab_offset)); domain->trans_tab = (struct string_desc *) ((char *) data + W (domain->must_swap, data->trans_tab_offset)); domain->hash_size = W (domain->must_swap, data->hash_tab_size); domain->hash_tab = (nls_uint32 *) ((char *) data + W (domain->must_swap, data->hash_tab_offset)); break; default: /* This is an invalid revision. */ #ifdef HAVE_MMAP if (use_mmap) munmap ((caddr_t) data, size); else #endif free (data); free (domain); domain_file->data = NULL; return; } /* Now initialize the character set converter from the character set the file is encoded with (found in the header entry) to the domain's specified character set or the locale's character set. */ nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding); /* Also look for a plural specification. */ EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals); } #ifdef _LIBC void internal_function _nl_unload_domain (domain) struct loaded_domain *domain; { if (domain->plural != &__gettext_germanic_plural) __gettext_free_exp (domain->plural); _nl_free_domain_conv (domain); # ifdef _POSIX_MAPPED_FILES if (domain->use_mmap) munmap ((caddr_t) domain->data, domain->mmap_size); else # endif /* _POSIX_MAPPED_FILES */ free ((void *) domain->data); free (domain); } #endif kbuild-3686/src/oldsed/intl/dcgettext.c0000664000175000017500000000343615053010106020057 0ustar locutuslocutus/* Implementation of the dcgettext(3) function. Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "gettextP.h" #ifdef _LIBC # include #else # include "libgnuintl.h" #endif /* @@ end of prolog @@ */ /* Names for the libintl functions are a problem. They must not clash with existing names and they should follow ANSI C. But this source code is also used in GNU C Library where the names have a __ prefix. So we have to make a difference here. */ #ifdef _LIBC # define DCGETTEXT __dcgettext # define DCIGETTEXT __dcigettext #else # define DCGETTEXT dcgettext__ # define DCIGETTEXT dcigettext__ #endif /* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY locale. */ char * DCGETTEXT (domainname, msgid, category) const char *domainname; const char *msgid; int category; { return DCIGETTEXT (domainname, msgid, NULL, 0, 0, category); } #ifdef _LIBC /* Alias for function name in GNU C Library. */ weak_alias (__dcgettext, dcgettext); #endif kbuild-3686/src/oldsed/intl/dcigettext.c0000664000175000017500000007633315053010106020236 0ustar locutuslocutus/* Implementation of the internal dcigettext function. Copyright (C) 1995-1999, 2000-2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Tell glibc's to provide a prototype for mempcpy(). This must come before because may include , and once has been included, it's too late. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif #ifdef HAVE_CONFIG_H # include #endif #include #ifdef __GNUC__ # define alloca __builtin_alloca # define HAVE_ALLOCA 1 #else # if defined HAVE_ALLOCA_H || defined _LIBC # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca char *alloca (); # endif # endif # endif #endif #include #ifndef errno extern int errno; #endif #ifndef __set_errno # define __set_errno(val) errno = (val) #endif #include #include #include #if defined HAVE_UNISTD_H || defined _LIBC # include #endif #include #if defined HAVE_SYS_PARAM_H || defined _LIBC # include #endif #include "gettextP.h" #include "plural-exp.h" #ifdef _LIBC # include #else # include "libgnuintl.h" #endif #include "hash-string.h" /* Thread safetyness. */ #ifdef _LIBC # include #else /* Provide dummy implementation if this is outside glibc. */ # define __libc_lock_define_initialized(CLASS, NAME) # define __libc_lock_lock(NAME) # define __libc_lock_unlock(NAME) # define __libc_rwlock_define_initialized(CLASS, NAME) # define __libc_rwlock_rdlock(NAME) # define __libc_rwlock_unlock(NAME) #endif /* Alignment of types. */ #if defined __GNUC__ && __GNUC__ >= 2 # define alignof(TYPE) __alignof__ (TYPE) #else # define alignof(TYPE) \ ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2) #endif /* The internal variables in the standalone libintl.a must have different names than the internal variables in GNU libc, otherwise programs using libintl.a cannot be linked statically. */ #if !defined _LIBC # define _nl_default_default_domain _nl_default_default_domain__ # define _nl_current_default_domain _nl_current_default_domain__ # define _nl_default_dirname _nl_default_dirname__ # define _nl_domain_bindings _nl_domain_bindings__ #endif /* Some compilers, like SunOS4 cc, don't have offsetof in . */ #ifndef offsetof # define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) #endif /* @@ end of prolog @@ */ #ifdef _LIBC /* Rename the non ANSI C functions. This is required by the standard because some ANSI C functions will require linking with this object file and the name space must not be polluted. */ # define getcwd __getcwd # ifndef stpcpy # define stpcpy __stpcpy # endif # define tfind __tfind #else # if !defined HAVE_GETCWD char *getwd (); # define getcwd(buf, max) getwd (buf) # else char *getcwd (); # endif # ifndef HAVE_STPCPY static char *stpcpy PARAMS ((char *dest, const char *src)); # endif # ifndef HAVE_MEMPCPY static void *mempcpy PARAMS ((void *dest, const void *src, size_t n)); # endif #endif /* Amount to increase buffer size by in each try. */ #define PATH_INCR 32 /* The following is from pathmax.h. */ /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define PATH_MAX but might cause redefinition warnings when sys/param.h is later included (as on MORE/BSD 4.3). */ #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__) # include #endif #ifndef _POSIX_PATH_MAX # define _POSIX_PATH_MAX 255 #endif #if !defined PATH_MAX && defined _PC_PATH_MAX # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX)) #endif /* Don't include sys/param.h if it already has been. */ #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN # include #endif #if !defined PATH_MAX && defined MAXPATHLEN # define PATH_MAX MAXPATHLEN #endif #ifndef PATH_MAX # define PATH_MAX _POSIX_PATH_MAX #endif /* Pathname support. ISSLASH(C) tests whether C is a directory separator character. IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, it may be concatenated to a directory pathname. IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. */ #if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ /* Win32, OS/2, DOS */ # define ISSLASH(C) ((C) == '/' || (C) == '\\') # define HAS_DEVICE(P) \ ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ && (P)[1] == ':') # define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) # define IS_PATH_WITH_DIR(P) \ (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) #else /* Unix */ # define ISSLASH(C) ((C) == '/') # define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0]) # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) #endif /* This is the type used for the search tree where known translations are stored. */ struct known_translation_t { /* Domain in which to search. */ char *domainname; /* The category. */ int category; /* State of the catalog counter at the point the string was found. */ int counter; /* Catalog where the string was found. */ struct loaded_l10nfile *domain; /* And finally the translation. */ const char *translation; size_t translation_length; /* Pointer to the string in question. */ char msgid[ZERO]; }; /* Root of the search tree with known translations. We can use this only if the system provides the `tsearch' function family. */ #if defined HAVE_TSEARCH || defined _LIBC # include static void *root; # ifdef _LIBC # define tsearch __tsearch # endif /* Function to compare two entries in the table of known translations. */ static int transcmp PARAMS ((const void *p1, const void *p2)); static int transcmp (p1, p2) const void *p1; const void *p2; { const struct known_translation_t *s1; const struct known_translation_t *s2; int result; s1 = (const struct known_translation_t *) p1; s2 = (const struct known_translation_t *) p2; result = strcmp (s1->msgid, s2->msgid); if (result == 0) { result = strcmp (s1->domainname, s2->domainname); if (result == 0) /* We compare the category last (though this is the cheapest operation) since it is hopefully always the same (namely LC_MESSAGES). */ result = s1->category - s2->category; } return result; } #endif /* Name of the default domain used for gettext(3) prior any call to textdomain(3). The default value for this is "messages". */ const char _nl_default_default_domain[] = "messages"; /* Value used as the default domain for gettext(3). */ const char *_nl_current_default_domain = _nl_default_default_domain; /* Contains the default location of the message catalogs. */ #if defined __EMX__ extern const char _nl_default_dirname[]; #else const char _nl_default_dirname[] = LOCALEDIR; #endif /* List with bindings of specific domains created by bindtextdomain() calls. */ struct binding *_nl_domain_bindings; /* Prototypes for local functions. */ static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain, unsigned long int n, const char *translation, size_t translation_len)) internal_function; static const char *category_to_name PARAMS ((int category)) internal_function; static const char *guess_category_value PARAMS ((int category, const char *categoryname)) internal_function; /* For those loosing systems which don't have `alloca' we have to add some additional code emulating it. */ #ifdef HAVE_ALLOCA /* Nothing has to be done. */ # define ADD_BLOCK(list, address) /* nothing */ # define FREE_BLOCKS(list) /* nothing */ #else struct block_list { void *address; struct block_list *next; }; # define ADD_BLOCK(list, addr) \ do { \ struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \ /* If we cannot get a free block we cannot add the new element to \ the list. */ \ if (newp != NULL) { \ newp->address = (addr); \ newp->next = (list); \ (list) = newp; \ } \ } while (0) # define FREE_BLOCKS(list) \ do { \ while (list != NULL) { \ struct block_list *old = list; \ list = list->next; \ free (old); \ } \ } while (0) # undef alloca # define alloca(size) (malloc (size)) #endif /* have alloca */ #ifdef _LIBC /* List of blocks allocated for translations. */ typedef struct transmem_list { struct transmem_list *next; char data[ZERO]; } transmem_block_t; static struct transmem_list *transmem_list; #else typedef unsigned char transmem_block_t; #endif /* Names for the libintl functions are a problem. They must not clash with existing names and they should follow ANSI C. But this source code is also used in GNU C Library where the names have a __ prefix. So we have to make a difference here. */ #ifdef _LIBC # define DCIGETTEXT __dcigettext #else # define DCIGETTEXT dcigettext__ #endif /* Lock variable to protect the global data in the gettext implementation. */ #ifdef _LIBC __libc_rwlock_define_initialized (, _nl_state_lock) #endif /* Checking whether the binaries runs SUID must be done and glibc provides easier methods therefore we make a difference here. */ #ifdef _LIBC # define ENABLE_SECURE __libc_enable_secure # define DETERMINE_SECURE #else # ifndef HAVE_GETUID # define getuid() 0 # endif # ifndef HAVE_GETGID # define getgid() 0 # endif # ifndef HAVE_GETEUID # define geteuid() getuid() # endif # ifndef HAVE_GETEGID # define getegid() getgid() # endif static int enable_secure; # define ENABLE_SECURE (enable_secure == 1) # define DETERMINE_SECURE \ if (enable_secure == 0) \ { \ if (getuid () != geteuid () || getgid () != getegid ()) \ enable_secure = 1; \ else \ enable_secure = -1; \ } #endif /* Get the function to evaluate the plural expression. */ #include "eval-plural.h" /* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY locale and, if PLURAL is nonzero, search over string depending on the plural form determined by N. */ char * DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category) const char *domainname; const char *msgid1; const char *msgid2; int plural; unsigned long int n; int category; { #ifndef HAVE_ALLOCA struct block_list *block_list = NULL; #endif struct loaded_l10nfile *domain; struct binding *binding; const char *categoryname; const char *categoryvalue; char *dirname, *xdomainname; char *single_locale; char *retval; size_t retlen; int saved_errno; #if defined HAVE_TSEARCH || defined _LIBC struct known_translation_t *search; struct known_translation_t **foundp = NULL; size_t msgid_len; #endif size_t domainname_len; /* If no real MSGID is given return NULL. */ if (msgid1 == NULL) return NULL; __libc_rwlock_rdlock (_nl_state_lock); /* If DOMAINNAME is NULL, we are interested in the default domain. If CATEGORY is not LC_MESSAGES this might not make much sense but the definition left this undefined. */ if (domainname == NULL) domainname = _nl_current_default_domain; /* OS/2 specific: backward compatibility with older libintl versions */ #ifdef LC_MESSAGES_COMPAT if (category == LC_MESSAGES_COMPAT) category = LC_MESSAGES; #endif #if defined HAVE_TSEARCH || defined _LIBC msgid_len = strlen (msgid1) + 1; /* Try to find the translation among those which we found at some time. */ search = (struct known_translation_t *) alloca (offsetof (struct known_translation_t, msgid) + msgid_len); memcpy (search->msgid, msgid1, msgid_len); search->domainname = (char *) domainname; search->category = category; foundp = (struct known_translation_t **) tfind (search, &root, transcmp); if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr) { /* Now deal with plural. */ if (plural) retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation, (*foundp)->translation_length); else retval = (char *) (*foundp)->translation; __libc_rwlock_unlock (_nl_state_lock); return retval; } #endif /* Preserve the `errno' value. */ saved_errno = errno; /* See whether this is a SUID binary or not. */ DETERMINE_SECURE; /* First find matching binding. */ for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) { int compare = strcmp (domainname, binding->domainname); if (compare == 0) /* We found it! */ break; if (compare < 0) { /* It is not in the list. */ binding = NULL; break; } } if (binding == NULL) dirname = (char *) _nl_default_dirname; else if (IS_ABSOLUTE_PATH (binding->dirname)) dirname = binding->dirname; else { /* We have a relative path. Make it absolute now. */ size_t dirname_len = strlen (binding->dirname) + 1; size_t path_max; char *ret; path_max = (unsigned int) PATH_MAX; path_max += 2; /* The getcwd docs say to do this. */ for (;;) { dirname = (char *) alloca (path_max + dirname_len); ADD_BLOCK (block_list, dirname); __set_errno (0); ret = getcwd (dirname, path_max); if (ret != NULL || errno != ERANGE) break; path_max += path_max / 2; path_max += PATH_INCR; } if (ret == NULL) { /* We cannot get the current working directory. Don't signal an error but simply return the default string. */ FREE_BLOCKS (block_list); __libc_rwlock_unlock (_nl_state_lock); __set_errno (saved_errno); return (plural == 0 ? (char *) msgid1 /* Use the Germanic plural rule. */ : n == 1 ? (char *) msgid1 : (char *) msgid2); } stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname); } /* Now determine the symbolic name of CATEGORY and its value. */ categoryname = category_to_name (category); categoryvalue = guess_category_value (category, categoryname); domainname_len = strlen (domainname); xdomainname = (char *) alloca (strlen (categoryname) + domainname_len + 5); ADD_BLOCK (block_list, xdomainname); stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"), domainname, domainname_len), ".mo"); /* Creating working area. */ single_locale = (char *) alloca (strlen (categoryvalue) + 1); ADD_BLOCK (block_list, single_locale); /* Search for the given string. This is a loop because we perhaps got an ordered list of languages to consider for the translation. */ while (1) { /* Make CATEGORYVALUE point to the next element of the list. */ while (categoryvalue[0] != '\0' && categoryvalue[0] == ':') ++categoryvalue; if (categoryvalue[0] == '\0') { /* The whole contents of CATEGORYVALUE has been searched but no valid entry has been found. We solve this situation by implicitly appending a "C" entry, i.e. no translation will take place. */ single_locale[0] = 'C'; single_locale[1] = '\0'; } else { char *cp = single_locale; while (categoryvalue[0] != '\0' && categoryvalue[0] != ':') *cp++ = *categoryvalue++; *cp = '\0'; /* When this is a SUID binary we must not allow accessing files outside the dedicated directories. */ if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale)) /* Ingore this entry. */ continue; } /* If the current locale value is C (or POSIX) we don't load a domain. Return the MSGID. */ if (strcmp (single_locale, "C") == 0 || strcmp (single_locale, "POSIX") == 0) { FREE_BLOCKS (block_list); __libc_rwlock_unlock (_nl_state_lock); __set_errno (saved_errno); return (plural == 0 ? (char *) msgid1 /* Use the Germanic plural rule. */ : n == 1 ? (char *) msgid1 : (char *) msgid2); } /* Find structure describing the message catalog matching the DOMAINNAME and CATEGORY. */ domain = _nl_find_domain (dirname, single_locale, xdomainname, binding); if (domain != NULL) { retval = _nl_find_msg (domain, binding, msgid1, &retlen); if (retval == NULL) { int cnt; for (cnt = 0; domain->successor[cnt] != NULL; ++cnt) { retval = _nl_find_msg (domain->successor[cnt], binding, msgid1, &retlen); if (retval != NULL) { domain = domain->successor[cnt]; break; } } } if (retval != NULL) { /* Found the translation of MSGID1 in domain DOMAIN: starting at RETVAL, RETLEN bytes. */ FREE_BLOCKS (block_list); __set_errno (saved_errno); #if defined HAVE_TSEARCH || defined _LIBC if (foundp == NULL) { /* Create a new entry and add it to the search tree. */ struct known_translation_t *newp; newp = (struct known_translation_t *) malloc (offsetof (struct known_translation_t, msgid) + msgid_len + domainname_len + 1); if (newp != NULL) { newp->domainname = mempcpy (newp->msgid, msgid1, msgid_len); memcpy (newp->domainname, domainname, domainname_len + 1); newp->category = category; newp->counter = _nl_msg_cat_cntr; newp->domain = domain; newp->translation = retval; newp->translation_length = retlen; /* Insert the entry in the search tree. */ foundp = (struct known_translation_t **) tsearch (newp, &root, transcmp); if (foundp == NULL || __builtin_expect (*foundp != newp, 0)) /* The insert failed. */ free (newp); } } else { /* We can update the existing entry. */ (*foundp)->counter = _nl_msg_cat_cntr; (*foundp)->domain = domain; (*foundp)->translation = retval; (*foundp)->translation_length = retlen; } #endif /* Now deal with plural. */ if (plural) retval = plural_lookup (domain, n, retval, retlen); __libc_rwlock_unlock (_nl_state_lock); return retval; } } } /* NOTREACHED */ } char * internal_function _nl_find_msg (domain_file, domainbinding, msgid, lengthp) struct loaded_l10nfile *domain_file; struct binding *domainbinding; const char *msgid; size_t *lengthp; { struct loaded_domain *domain; size_t act; char *result; size_t resultlen; if (domain_file->decided == 0) _nl_load_domain (domain_file, domainbinding); if (domain_file->data == NULL) return NULL; domain = (struct loaded_domain *) domain_file->data; /* Locate the MSGID and its translation. */ if (domain->hash_size > 2 && domain->hash_tab != NULL) { /* Use the hashing table. */ nls_uint32 len = strlen (msgid); nls_uint32 hash_val = hash_string (msgid); nls_uint32 idx = hash_val % domain->hash_size; nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2)); while (1) { nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]); if (nstr == 0) /* Hash table entry is empty. */ return NULL; /* Compare msgid with the original string at index nstr-1. We compare the lengths with >=, not ==, because plural entries are represented by strings with an embedded NUL. */ if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) >= len && (strcmp (msgid, domain->data + W (domain->must_swap, domain->orig_tab[nstr - 1].offset)) == 0)) { act = nstr - 1; goto found; } if (idx >= domain->hash_size - incr) idx -= domain->hash_size - incr; else idx += incr; } /* NOTREACHED */ } else { /* Try the default method: binary search in the sorted array of messages. */ size_t top, bottom; bottom = 0; top = domain->nstrings; while (bottom < top) { int cmp_val; act = (bottom + top) / 2; cmp_val = strcmp (msgid, (domain->data + W (domain->must_swap, domain->orig_tab[act].offset))); if (cmp_val < 0) top = act; else if (cmp_val > 0) bottom = act + 1; else goto found; } /* No translation was found. */ return NULL; } found: /* The translation was found at index ACT. If we have to convert the string to use a different character set, this is the time. */ result = ((char *) domain->data + W (domain->must_swap, domain->trans_tab[act].offset)); resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1; #if defined _LIBC || HAVE_ICONV if (domain->codeset_cntr != (domainbinding != NULL ? domainbinding->codeset_cntr : 0)) { /* The domain's codeset has changed through bind_textdomain_codeset() since the message catalog was initialized or last accessed. We have to reinitialize the converter. */ _nl_free_domain_conv (domain); _nl_init_domain_conv (domain_file, domain, domainbinding); } if ( # ifdef _LIBC domain->conv != (__gconv_t) -1 # else # if HAVE_ICONV domain->conv != (iconv_t) -1 # endif # endif ) { /* We are supposed to do a conversion. First allocate an appropriate table with the same structure as the table of translations in the file, where we can put the pointers to the converted strings in. There is a slight complication with plural entries. They are represented by consecutive NUL terminated strings. We handle this case by converting RESULTLEN bytes, including NULs. */ if (domain->conv_tab == NULL && ((domain->conv_tab = (char **) calloc (domain->nstrings, sizeof (char *))) == NULL)) /* Mark that we didn't succeed allocating a table. */ domain->conv_tab = (char **) -1; if (__builtin_expect (domain->conv_tab == (char **) -1, 0)) /* Nothing we can do, no more memory. */ goto converted; if (domain->conv_tab[act] == NULL) { /* We haven't used this string so far, so it is not translated yet. Do this now. */ /* We use a bit more efficient memory handling. We allocate always larger blocks which get used over time. This is faster than many small allocations. */ __libc_lock_define_initialized (static, lock) # define INITIAL_BLOCK_SIZE 4080 static unsigned char *freemem; static size_t freemem_size; const unsigned char *inbuf; unsigned char *outbuf; int malloc_count; # ifndef _LIBC transmem_block_t *transmem_list = NULL; # endif __libc_lock_lock (lock); inbuf = (const unsigned char *) result; outbuf = freemem + sizeof (size_t); malloc_count = 0; while (1) { transmem_block_t *newmem; # ifdef _LIBC size_t non_reversible; int res; if (freemem_size < sizeof (size_t)) goto resize_freemem; res = __gconv (domain->conv, &inbuf, inbuf + resultlen, &outbuf, outbuf + freemem_size - sizeof (size_t), &non_reversible); if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT) break; if (res != __GCONV_FULL_OUTPUT) { __libc_lock_unlock (lock); goto converted; } inbuf = result; # else # if HAVE_ICONV const char *inptr = (const char *) inbuf; size_t inleft = resultlen; char *outptr = (char *) outbuf; size_t outleft; if (freemem_size < sizeof (size_t)) goto resize_freemem; outleft = freemem_size - sizeof (size_t); if (iconv (domain->conv, (ICONV_CONST char **) &inptr, &inleft, &outptr, &outleft) != (size_t) (-1)) { outbuf = (unsigned char *) outptr; break; } if (errno != E2BIG) { __libc_lock_unlock (lock); goto converted; } # endif # endif resize_freemem: /* We must allocate a new buffer or resize the old one. */ if (malloc_count > 0) { ++malloc_count; freemem_size = malloc_count * INITIAL_BLOCK_SIZE; newmem = (transmem_block_t *) realloc (transmem_list, freemem_size); # ifdef _LIBC if (newmem != NULL) transmem_list = transmem_list->next; else { struct transmem_list *old = transmem_list; transmem_list = transmem_list->next; free (old); } # endif } else { malloc_count = 1; freemem_size = INITIAL_BLOCK_SIZE; newmem = (transmem_block_t *) malloc (freemem_size); } if (__builtin_expect (newmem == NULL, 0)) { freemem = NULL; freemem_size = 0; __libc_lock_unlock (lock); goto converted; } # ifdef _LIBC /* Add the block to the list of blocks we have to free at some point. */ newmem->next = transmem_list; transmem_list = newmem; freemem = newmem->data; freemem_size -= offsetof (struct transmem_list, data); # else transmem_list = newmem; freemem = newmem; # endif outbuf = freemem + sizeof (size_t); } /* We have now in our buffer a converted string. Put this into the table of conversions. */ *(size_t *) freemem = outbuf - freemem - sizeof (size_t); domain->conv_tab[act] = (char *) freemem; /* Shrink freemem, but keep it aligned. */ freemem_size -= outbuf - freemem; freemem = outbuf; freemem += freemem_size & (alignof (size_t) - 1); freemem_size = freemem_size & ~ (alignof (size_t) - 1); __libc_lock_unlock (lock); } /* Now domain->conv_tab[act] contains the translation of all the plural variants. */ result = domain->conv_tab[act] + sizeof (size_t); resultlen = *(size_t *) domain->conv_tab[act]; } converted: /* The result string is converted. */ #endif /* _LIBC || HAVE_ICONV */ *lengthp = resultlen; return result; } /* Look up a plural variant. */ static char * internal_function plural_lookup (domain, n, translation, translation_len) struct loaded_l10nfile *domain; unsigned long int n; const char *translation; size_t translation_len; { struct loaded_domain *domaindata = (struct loaded_domain *) domain->data; unsigned long int index; const char *p; index = plural_eval (domaindata->plural, n); if (index >= domaindata->nplurals) /* This should never happen. It means the plural expression and the given maximum value do not match. */ index = 0; /* Skip INDEX strings at TRANSLATION. */ p = translation; while (index-- > 0) { #ifdef _LIBC p = __rawmemchr (p, '\0'); #else p = strchr (p, '\0'); #endif /* And skip over the NUL byte. */ p++; if (p >= translation + translation_len) /* This should never happen. It means the plural expression evaluated to a value larger than the number of variants available for MSGID1. */ return (char *) translation; } return (char *) p; } /* Return string representation of locale CATEGORY. */ static const char * internal_function category_to_name (category) int category; { const char *retval; switch (category) { #ifdef LC_COLLATE case LC_COLLATE: retval = "LC_COLLATE"; break; #endif #ifdef LC_CTYPE case LC_CTYPE: retval = "LC_CTYPE"; break; #endif #ifdef LC_MONETARY case LC_MONETARY: retval = "LC_MONETARY"; break; #endif #ifdef LC_NUMERIC case LC_NUMERIC: retval = "LC_NUMERIC"; break; #endif #ifdef LC_TIME case LC_TIME: retval = "LC_TIME"; break; #endif #ifdef LC_MESSAGES case LC_MESSAGES: retval = "LC_MESSAGES"; break; #endif #ifdef LC_RESPONSE case LC_RESPONSE: retval = "LC_RESPONSE"; break; #endif #ifdef LC_ALL case LC_ALL: /* This might not make sense but is perhaps better than any other value. */ retval = "LC_ALL"; break; #endif default: /* If you have a better idea for a default value let me know. */ retval = "LC_XXX"; } return retval; } /* Guess value of current locale from value of the environment variables. */ static const char * internal_function guess_category_value (category, categoryname) int category; const char *categoryname; { const char *language; const char *retval; /* The highest priority value is the `LANGUAGE' environment variable. But we don't use the value if the currently selected locale is the C locale. This is a GNU extension. */ language = getenv ("LANGUAGE"); if (language != NULL && language[0] == '\0') language = NULL; /* We have to proceed with the POSIX methods of looking to `LC_ALL', `LC_xxx', and `LANG'. On some systems this can be done by the `setlocale' function itself. */ #ifdef _LIBC retval = setlocale (category, NULL); #else retval = _nl_locale_name (category, categoryname); #endif /* Ignore LANGUAGE if the locale is set to "C" because 1. "C" locale usually uses the ASCII encoding, and most international messages use non-ASCII characters. These characters get displayed as question marks (if using glibc's iconv()) or as invalid 8-bit characters (because other iconv()s refuse to convert most non-ASCII characters to ASCII). In any case, the output is ugly. 2. The precise output of some programs in the "C" locale is specified by POSIX and should not depend on environment variables like "LANGUAGE". We allow such programs to use gettext(). */ return language != NULL && strcmp (retval, "C") != 0 ? language : retval; } /* @@ begin of epilog @@ */ /* We don't want libintl.a to depend on any other library. So we avoid the non-standard function stpcpy. In GNU C Library this function is available, though. Also allow the symbol HAVE_STPCPY to be defined. */ #if !_LIBC && !HAVE_STPCPY static char * stpcpy (dest, src) char *dest; const char *src; { while ((*dest++ = *src++) != '\0') /* Do nothing. */ ; return dest - 1; } #endif #if !_LIBC && !HAVE_MEMPCPY static void * mempcpy (dest, src, n) void *dest; const void *src; size_t n; { return (void *) ((char *) memcpy (dest, src, n) + n); } #endif #ifdef _LIBC /* If we want to free all resources we have to do some work at program's end. */ static void __attribute__ ((unused)) free_mem (void) { void *old; while (_nl_domain_bindings != NULL) { struct binding *oldp = _nl_domain_bindings; _nl_domain_bindings = _nl_domain_bindings->next; if (oldp->dirname != _nl_default_dirname) /* Yes, this is a pointer comparison. */ free (oldp->dirname); free (oldp->codeset); free (oldp); } if (_nl_current_default_domain != _nl_default_default_domain) /* Yes, again a pointer comparison. */ free ((char *) _nl_current_default_domain); /* Remove the search tree with the known translations. */ __tdestroy (root, free); root = NULL; while (transmem_list != NULL) { old = transmem_list; transmem_list = transmem_list->next; free (old); } } text_set_element (__libc_subfreeres, free_mem); #endif kbuild-3686/src/oldsed/intl/ChangeLog0000664000175000017500000000010715053010105017461 0ustar locutuslocutus2002-01-31 GNU * Version 0.11 released. kbuild-3686/src/oldsed/intl/textdomain.c0000664000175000017500000001060315053010106020232 0ustar locutuslocutus/* Implementation of the textdomain(3) function. Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #ifdef _LIBC # include #else # include "libgnuintl.h" #endif #include "gettextP.h" #ifdef _LIBC /* We have to handle multi-threaded applications. */ # include #else /* Provide dummy implementation if this is outside glibc. */ # define __libc_rwlock_define(CLASS, NAME) # define __libc_rwlock_wrlock(NAME) # define __libc_rwlock_unlock(NAME) #endif /* The internal variables in the standalone libintl.a must have different names than the internal variables in GNU libc, otherwise programs using libintl.a cannot be linked statically. */ #if !defined _LIBC # define _nl_default_default_domain _nl_default_default_domain__ # define _nl_current_default_domain _nl_current_default_domain__ #endif /* @@ end of prolog @@ */ /* Name of the default text domain. */ extern const char _nl_default_default_domain[]; /* Default text domain in which entries for gettext(3) are to be found. */ extern const char *_nl_current_default_domain; /* Names for the libintl functions are a problem. They must not clash with existing names and they should follow ANSI C. But this source code is also used in GNU C Library where the names have a __ prefix. So we have to make a difference here. */ #ifdef _LIBC # define TEXTDOMAIN __textdomain # ifndef strdup # define strdup(str) __strdup (str) # endif #else # define TEXTDOMAIN textdomain__ #endif /* Lock variable to protect the global data in the gettext implementation. */ __libc_rwlock_define (extern, _nl_state_lock) /* Set the current default message catalog to DOMAINNAME. If DOMAINNAME is null, return the current default. If DOMAINNAME is "", reset to the default of "messages". */ char * TEXTDOMAIN (domainname) const char *domainname; { char *new_domain; char *old_domain; /* A NULL pointer requests the current setting. */ if (domainname == NULL) return (char *) _nl_current_default_domain; __libc_rwlock_wrlock (_nl_state_lock); old_domain = (char *) _nl_current_default_domain; /* If domain name is the null string set to default domain "messages". */ if (domainname[0] == '\0' || strcmp (domainname, _nl_default_default_domain) == 0) { _nl_current_default_domain = _nl_default_default_domain; new_domain = (char *) _nl_current_default_domain; } else if (strcmp (domainname, old_domain) == 0) /* This can happen and people will use it to signal that some environment variable changed. */ new_domain = old_domain; else { /* If the following malloc fails `_nl_current_default_domain' will be NULL. This value will be returned and so signals we are out of core. */ #if defined _LIBC || defined HAVE_STRDUP new_domain = strdup (domainname); #else size_t len = strlen (domainname) + 1; new_domain = (char *) malloc (len); if (new_domain != NULL) memcpy (new_domain, domainname, len); #endif if (new_domain != NULL) _nl_current_default_domain = new_domain; } /* We use this possibility to signal a change of the loaded catalogs since this is most likely the case and there is no other easy we to do it. Do it only when the call was successful. */ if (new_domain != NULL) { ++_nl_msg_cat_cntr; if (old_domain != new_domain && old_domain != _nl_default_default_domain) free (old_domain); } __libc_rwlock_unlock (_nl_state_lock); return new_domain; } #ifdef _LIBC /* Alias for function name in GNU C Library. */ weak_alias (__textdomain, textdomain); #endif kbuild-3686/src/oldsed/intl/gmo.h0000664000175000017500000000600115053010106016642 0ustar locutuslocutus/* Description of GNU message catalog format: general file layout. Copyright (C) 1995, 1997, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _GETTEXT_H #define _GETTEXT_H 1 #include /* @@ end of prolog @@ */ /* The magic number of the GNU message catalog format. */ #define _MAGIC 0x950412de #define _MAGIC_SWAPPED 0xde120495 /* Revision number of the currently used .mo (binary) file format. */ #define MO_REVISION_NUMBER 0 /* The following contortions are an attempt to use the C preprocessor to determine an unsigned integral type that is 32 bits wide. An alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but as of version autoconf-2.13, the AC_CHECK_SIZEOF macro doesn't work when cross-compiling. */ #if __STDC__ # define UINT_MAX_32_BITS 4294967295U #else # define UINT_MAX_32_BITS 0xFFFFFFFF #endif /* If UINT_MAX isn't defined, assume it's a 32-bit type. This should be valid for all systems GNU cares about because that doesn't include 16-bit systems, and only modern systems (that certainly have ) have 64+-bit integral types. */ #ifndef UINT_MAX # define UINT_MAX UINT_MAX_32_BITS #endif #if UINT_MAX == UINT_MAX_32_BITS typedef unsigned nls_uint32; #else # if USHRT_MAX == UINT_MAX_32_BITS typedef unsigned short nls_uint32; # else # if ULONG_MAX == UINT_MAX_32_BITS typedef unsigned long nls_uint32; # else /* The following line is intended to throw an error. Using #error is not portable enough. */ "Cannot determine unsigned 32-bit data type." # endif # endif #endif /* Header for binary .mo file format. */ struct mo_file_header { /* The magic number. */ nls_uint32 magic; /* The revision number of the file format. */ nls_uint32 revision; /* The number of strings pairs. */ nls_uint32 nstrings; /* Offset of table with start offsets of original strings. */ nls_uint32 orig_tab_offset; /* Offset of table with start offsets of translation strings. */ nls_uint32 trans_tab_offset; /* Size of hashing table. */ nls_uint32 hash_tab_size; /* Offset of first hashing entry. */ nls_uint32 hash_tab_offset; }; struct string_desc { /* Length of addressed string. */ nls_uint32 length; /* Offset of string in file. */ nls_uint32 offset; }; /* @@ begin of epilog @@ */ #endif /* gettext.h */ kbuild-3686/src/oldsed/intl/finddomain.c0000664000175000017500000001315215053010106020170 0ustar locutuslocutus/* Handle list of needed message catalogs Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. Written by Ulrich Drepper , 1995. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #if defined HAVE_UNISTD_H || defined _LIBC # include #endif #include "gettextP.h" #ifdef _LIBC # include #else # include "libgnuintl.h" #endif /* @@ end of prolog @@ */ /* List of already loaded domains. */ static struct loaded_l10nfile *_nl_loaded_domains; /* Return a data structure describing the message catalog described by the DOMAINNAME and CATEGORY parameters with respect to the currently established bindings. */ struct loaded_l10nfile * internal_function _nl_find_domain (dirname, locale, domainname, domainbinding) const char *dirname; char *locale; const char *domainname; struct binding *domainbinding; { struct loaded_l10nfile *retval; const char *language; const char *modifier; const char *territory; const char *codeset; const char *normalized_codeset; const char *special; const char *sponsor; const char *revision; const char *alias_value; int mask; /* LOCALE can consist of up to four recognized parts for the XPG syntax: language[_territory[.codeset]][@modifier] and six parts for the CEN syntax: language[_territory][+audience][+special][,[sponsor][_revision]] Beside the first part all of them are allowed to be missing. If the full specified locale is not found, the less specific one are looked for. The various parts will be stripped off according to the following order: (1) revision (2) sponsor (3) special (4) codeset (5) normalized codeset (6) territory (7) audience/modifier */ /* If we have already tested for this locale entry there has to be one data set in the list of loaded domains. */ retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, strlen (dirname) + 1, 0, locale, NULL, NULL, NULL, NULL, NULL, NULL, NULL, domainname, 0); if (retval != NULL) { /* We know something about this locale. */ int cnt; if (retval->decided == 0) _nl_load_domain (retval, domainbinding); if (retval->data != NULL) return retval; for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) { if (retval->successor[cnt]->decided == 0) _nl_load_domain (retval->successor[cnt], domainbinding); if (retval->successor[cnt]->data != NULL) break; } return cnt >= 0 ? retval : NULL; /* NOTREACHED */ } /* See whether the locale value is an alias. If yes its value *overwrites* the alias name. No test for the original value is done. */ alias_value = _nl_expand_alias (locale); if (alias_value != NULL) { #if defined _LIBC || defined HAVE_STRDUP locale = strdup (alias_value); if (locale == NULL) return NULL; #else size_t len = strlen (alias_value) + 1; locale = (char *) malloc (len); if (locale == NULL) return NULL; memcpy (locale, alias_value, len); #endif } /* Now we determine the single parts of the locale name. First look for the language. Termination symbols are `_' and `@' if we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ mask = _nl_explode_name (locale, &language, &modifier, &territory, &codeset, &normalized_codeset, &special, &sponsor, &revision); /* Create all possible locale entries which might be interested in generalization. */ retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, strlen (dirname) + 1, mask, language, territory, codeset, normalized_codeset, modifier, special, sponsor, revision, domainname, 1); if (retval == NULL) /* This means we are out of core. */ return NULL; if (retval->decided == 0) _nl_load_domain (retval, domainbinding); if (retval->data == NULL) { int cnt; for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) { if (retval->successor[cnt]->decided == 0) _nl_load_domain (retval->successor[cnt], domainbinding); if (retval->successor[cnt]->data != NULL) break; } } /* The room for an alias was dynamically allocated. Free it now. */ if (alias_value != NULL) free (locale); /* The space for normalized_codeset is dynamically allocated. Free it. */ if (mask & XPG_NORM_CODESET) free ((void *) normalized_codeset); return retval; } #ifdef _LIBC static void __attribute__ ((unused)) free_mem (void) { struct loaded_l10nfile *runp = _nl_loaded_domains; while (runp != NULL) { struct loaded_l10nfile *here = runp; if (runp->data != NULL) _nl_unload_domain ((struct loaded_domain *) runp->data); runp = runp->next; free ((char *) here->filename); free (here); } } text_set_element (__libc_subfreeres, free_mem); #endif kbuild-3686/src/oldsed/intl/l10nflist.c0000664000175000017500000002434515053010105017701 0ustar locutuslocutus/* Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. Contributed by Ulrich Drepper , 1995. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Tell glibc's to provide a prototype for stpcpy(). This must come before because may include , and once has been included, it's too late. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif #ifdef HAVE_CONFIG_H # include #endif #include #if defined _LIBC || defined HAVE_ARGZ_H # include #endif #include #include #include #include "loadinfo.h" /* On some strange systems still no definition of NULL is found. Sigh! */ #ifndef NULL # if defined __STDC__ && __STDC__ # define NULL ((void *) 0) # else # define NULL 0 # endif #endif /* @@ end of prolog @@ */ #ifdef _LIBC /* Rename the non ANSI C functions. This is required by the standard because some ANSI C functions will require linking with this object file and the name space must not be polluted. */ # ifndef stpcpy # define stpcpy(dest, src) __stpcpy(dest, src) # endif #else # ifndef HAVE_STPCPY static char *stpcpy PARAMS ((char *dest, const char *src)); # endif #endif /* Define function which are usually not available. */ #if !defined _LIBC && !defined HAVE___ARGZ_COUNT /* Returns the number of strings in ARGZ. */ static size_t argz_count__ PARAMS ((const char *argz, size_t len)); static size_t argz_count__ (argz, len) const char *argz; size_t len; { size_t count = 0; while (len > 0) { size_t part_len = strlen (argz); argz += part_len + 1; len -= part_len + 1; count++; } return count; } # undef __argz_count # define __argz_count(argz, len) argz_count__ (argz, len) #endif /* !_LIBC && !HAVE___ARGZ_COUNT */ #if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY /* Make '\0' separated arg vector ARGZ printable by converting all the '\0's except the last into the character SEP. */ static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep)); static void argz_stringify__ (argz, len, sep) char *argz; size_t len; int sep; { while (len > 0) { size_t part_len = strlen (argz); argz += part_len; len -= part_len + 1; if (len > 0) *argz++ = sep; } } # undef __argz_stringify # define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep) #endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */ #if !defined _LIBC && !defined HAVE___ARGZ_NEXT static char *argz_next__ PARAMS ((char *argz, size_t argz_len, const char *entry)); static char * argz_next__ (argz, argz_len, entry) char *argz; size_t argz_len; const char *entry; { if (entry) { if (entry < argz + argz_len) entry = strchr (entry, '\0') + 1; return entry >= argz + argz_len ? NULL : (char *) entry; } else if (argz_len > 0) return argz; else return 0; } # undef __argz_next # define __argz_next(argz, len, entry) argz_next__ (argz, len, entry) #endif /* !_LIBC && !HAVE___ARGZ_NEXT */ /* Return number of bits set in X. */ static int pop PARAMS ((int x)); static inline int pop (x) int x; { /* We assume that no more than 16 bits are used. */ x = ((x & ~0x5555) >> 1) + (x & 0x5555); x = ((x & ~0x3333) >> 2) + (x & 0x3333); x = ((x >> 4) + x) & 0x0f0f; x = ((x >> 8) + x) & 0xff; return x; } struct loaded_l10nfile * _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language, territory, codeset, normalized_codeset, modifier, special, sponsor, revision, filename, do_allocate) struct loaded_l10nfile **l10nfile_list; const char *dirlist; size_t dirlist_len; int mask; const char *language; const char *territory; const char *codeset; const char *normalized_codeset; const char *modifier; const char *special; const char *sponsor; const char *revision; const char *filename; int do_allocate; { char *abs_filename; struct loaded_l10nfile *last = NULL; struct loaded_l10nfile *retval; char *cp; size_t entries; int cnt; /* Allocate room for the full file name. */ abs_filename = (char *) malloc (dirlist_len + strlen (language) + ((mask & TERRITORY) != 0 ? strlen (territory) + 1 : 0) + ((mask & XPG_CODESET) != 0 ? strlen (codeset) + 1 : 0) + ((mask & XPG_NORM_CODESET) != 0 ? strlen (normalized_codeset) + 1 : 0) + (((mask & XPG_MODIFIER) != 0 || (mask & CEN_AUDIENCE) != 0) ? strlen (modifier) + 1 : 0) + ((mask & CEN_SPECIAL) != 0 ? strlen (special) + 1 : 0) + (((mask & CEN_SPONSOR) != 0 || (mask & CEN_REVISION) != 0) ? (1 + ((mask & CEN_SPONSOR) != 0 ? strlen (sponsor) + 1 : 0) + ((mask & CEN_REVISION) != 0 ? strlen (revision) + 1 : 0)) : 0) + 1 + strlen (filename) + 1); if (abs_filename == NULL) return NULL; retval = NULL; last = NULL; /* Construct file name. */ memcpy (abs_filename, dirlist, dirlist_len); __argz_stringify (abs_filename, dirlist_len, PATH_SEPARATOR); cp = abs_filename + (dirlist_len - 1); *cp++ = '/'; cp = stpcpy (cp, language); if ((mask & TERRITORY) != 0) { *cp++ = '_'; cp = stpcpy (cp, territory); } if ((mask & XPG_CODESET) != 0) { *cp++ = '.'; cp = stpcpy (cp, codeset); } if ((mask & XPG_NORM_CODESET) != 0) { *cp++ = '.'; cp = stpcpy (cp, normalized_codeset); } if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0) { /* This component can be part of both syntaces but has different leading characters. For CEN we use `+', else `@'. */ *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@'; cp = stpcpy (cp, modifier); } if ((mask & CEN_SPECIAL) != 0) { *cp++ = '+'; cp = stpcpy (cp, special); } if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0) { *cp++ = ','; if ((mask & CEN_SPONSOR) != 0) cp = stpcpy (cp, sponsor); if ((mask & CEN_REVISION) != 0) { *cp++ = '_'; cp = stpcpy (cp, revision); } } *cp++ = '/'; stpcpy (cp, filename); /* Look in list of already loaded domains whether it is already available. */ last = NULL; for (retval = *l10nfile_list; retval != NULL; retval = retval->next) if (retval->filename != NULL) { int compare = strcmp (retval->filename, abs_filename); if (compare == 0) /* We found it! */ break; if (compare < 0) { /* It's not in the list. */ retval = NULL; break; } last = retval; } if (retval != NULL || do_allocate == 0) { free (abs_filename); return retval; } retval = (struct loaded_l10nfile *) malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len) * (1 << pop (mask)) * sizeof (struct loaded_l10nfile *))); if (retval == NULL) return NULL; retval->filename = abs_filename; retval->decided = (__argz_count (dirlist, dirlist_len) != 1 || ((mask & XPG_CODESET) != 0 && (mask & XPG_NORM_CODESET) != 0)); retval->data = NULL; if (last == NULL) { retval->next = *l10nfile_list; *l10nfile_list = retval; } else { retval->next = last->next; last->next = retval; } entries = 0; /* If the DIRLIST is a real list the RETVAL entry corresponds not to a real file. So we have to use the DIRLIST separation mechanism of the inner loop. */ cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask; for (; cnt >= 0; --cnt) if ((cnt & ~mask) == 0 && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0) && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0)) { /* Iterate over all elements of the DIRLIST. */ char *dir = NULL; while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir)) != NULL) retval->successor[entries++] = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt, language, territory, codeset, normalized_codeset, modifier, special, sponsor, revision, filename, 1); } retval->successor[entries] = NULL; return retval; } /* Normalize codeset name. There is no standard for the codeset names. Normalization allows the user to use any of the common names. The return value is dynamically allocated and has to be freed by the caller. */ const char * _nl_normalize_codeset (codeset, name_len) const char *codeset; size_t name_len; { int len = 0; int only_digit = 1; char *retval; char *wp; size_t cnt; for (cnt = 0; cnt < name_len; ++cnt) if (isalnum ((unsigned char) codeset[cnt])) { ++len; if (isalpha ((unsigned char) codeset[cnt])) only_digit = 0; } retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1); if (retval != NULL) { if (only_digit) wp = stpcpy (retval, "iso"); else wp = retval; for (cnt = 0; cnt < name_len; ++cnt) if (isalpha ((unsigned char) codeset[cnt])) *wp++ = tolower ((unsigned char) codeset[cnt]); else if (isdigit ((unsigned char) codeset[cnt])) *wp++ = codeset[cnt]; *wp = '\0'; } return (const char *) retval; } /* @@ begin of epilog @@ */ /* We don't want libintl.a to depend on any other library. So we avoid the non-standard function stpcpy. In GNU C Library this function is available, though. Also allow the symbol HAVE_STPCPY to be defined. */ #if !_LIBC && !HAVE_STPCPY static char * stpcpy (dest, src) char *dest; const char *src; { while ((*dest++ = *src++) != '\0') /* Do nothing. */ ; return dest - 1; } #endif kbuild-3686/src/oldsed/intl/Makefile.in0000664000175000017500000002516015053010106017763 0ustar locutuslocutus# Makefile for directory with message catalog handling in GNU NLS Utilities. # Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU Library General Public License as published # by the Free Software Foundation; either version 2, 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. PACKAGE = @PACKAGE@ VERSION = @VERSION@ SHELL = /bin/sh srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = .. VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ transform = @program_transform_name@ libdir = @libdir@ includedir = @includedir@ datadir = @datadir@ localedir = $(datadir)/locale gettextsrcdir = $(datadir)/gettext/intl aliaspath = $(localedir) subdir = intl INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ MKINSTALLDIRS = @MKINSTALLDIRS@ mkinstalldirs = $(SHELL) `case "$(MKINSTALLDIRS)" in /*) echo "$(MKINSTALLDIRS)" ;; *) echo "$(top_builddir)/$(MKINSTALLDIRS)" ;; esac` l = @INTL_LIBTOOL_SUFFIX_PREFIX@ AR = ar CC = @CC@ LIBTOOL = @LIBTOOL@ RANLIB = @RANLIB@ YACC = @INTLBISON@ -y -d YFLAGS = --name-prefix=__gettext DEFS = -DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \ -DLIBDIR=\"$(libdir)\" -DIN_LIBINTL @DEFS@ CPPFLAGS = @CPPFLAGS@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) HEADERS = $(COMHDRS) libgnuintl.h loadinfo.h COMHDRS = gmo.h gettextP.h hash-string.h plural-exp.h eval-plural.h os2compat.h SOURCES = $(COMSRCS) intl-compat.c COMSRCS = bindtextdom.c dcgettext.c dgettext.c gettext.c \ finddomain.c loadmsgcat.c localealias.c textdomain.c l10nflist.c \ explodename.c dcigettext.c dcngettext.c dngettext.c ngettext.c plural.y \ plural-exp.c localcharset.c localename.c osdep.c os2compat.c OBJECTS = @INTLOBJS@ bindtextdom.$lo dcgettext.$lo dgettext.$lo gettext.$lo \ finddomain.$lo loadmsgcat.$lo localealias.$lo textdomain.$lo l10nflist.$lo \ explodename.$lo dcigettext.$lo dcngettext.$lo dngettext.$lo ngettext.$lo \ plural.$lo plural-exp.$lo localcharset.$lo localename.$lo osdep.$lo GETTOBJS = intl-compat.$lo DISTFILES.common = Makefile.in \ config.charset locale.alias ref-add.sin ref-del.sin $(HEADERS) $(SOURCES) DISTFILES.generated = plural.c DISTFILES.normal = VERSION DISTFILES.gettext = COPYING.LIB-2.0 COPYING.LIB-2.1 libintl.glibc DISTFILES.obsolete = xopen-msg.sed linux-msg.sed po2tbl.sed.in cat-compat.c \ COPYING.LIB-2 gettext.h libgettext.h plural-eval.c # Libtool's library version information for libintl. # Before making a gettext release, the gettext maintainer must change this # according to the libtool documentation, section "Library interface versions". # Maintainers of other packages that include the intl directory must *not* # change these values. LTV_CURRENT=2 LTV_REVISION=0 LTV_AGE=0 .SUFFIXES: .SUFFIXES: .c .y .o .lo .sin .sed .c.o: $(COMPILE) $< .c.lo: $(LIBTOOL) --mode=compile $(COMPILE) $< .y.c: $(YACC) $(YFLAGS) --output $@ $< rm -f $*.h .sin.sed: sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $< > t-$@ mv t-$@ $@ INCLUDES = -I.. -I. -I$(top_srcdir)/intl all: all-@USE_INCLUDED_LIBINTL@ all-yes: libintl.$la libintl.h charset.alias ref-add.sed ref-del.sed all-no: all-no-@BUILD_INCLUDED_LIBINTL@ all-no-yes: libgnuintl.$la all-no-no: libintl.a libgnuintl.a: $(OBJECTS) rm -f $@ $(AR) cru $@ $(OBJECTS) $(RANLIB) $@ libintl.la libgnuintl.la: $(OBJECTS) $(LIBTOOL) --mode=link \ $(CC) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ \ $(OBJECTS) @LTLIBICONV@ -lc \ -version-info $(LTV_CURRENT):$(LTV_REVISION):$(LTV_AGE) \ -rpath $(libdir) \ -no-undefined libintl.h: libgnuintl.h cp $(srcdir)/libgnuintl.h libintl.h charset.alias: config.charset $(SHELL) $(srcdir)/config.charset '@host@' > t-$@ mv t-$@ $@ check: all # This installation goal is only used in GNU gettext. Packages which # only use the library should use install instead. # We must not install the libintl.h/libintl.a files if we are on a # system which has the GNU gettext() function in its C library or in a # separate library. # If you want to use the one which comes with this version of the # package, you have to use `configure --with-included-gettext'. install: install-exec install-data install-exec: all if test "$(PACKAGE)" = "gettext" \ && test '@INTLOBJS@' = '$(GETTOBJS)'; then \ $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \ $(INSTALL_DATA) libintl.h $(DESTDIR)$(includedir)/libintl.h; \ $(LIBTOOL) --mode=install \ $(INSTALL_DATA) libintl.$la $(DESTDIR)$(libdir)/libintl.$la; \ else \ : ; \ fi if test '@USE_INCLUDED_LIBINTL@' = yes; then \ test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \ temp=$(DESTDIR)$(libdir)/t-charset.alias; \ dest=$(DESTDIR)$(libdir)/charset.alias; \ if test -f $(DESTDIR)$(libdir)/charset.alias; then \ orig=$(DESTDIR)$(libdir)/charset.alias; \ sed -f ref-add.sed $$orig > $$temp; \ $(INSTALL_DATA) $$temp $$dest; \ rm -f $$temp; \ else \ if test @GLIBC21@ = no; then \ orig=charset.alias; \ sed -f ref-add.sed $$orig > $$temp; \ $(INSTALL_DATA) $$temp $$dest; \ rm -f $$temp; \ fi; \ fi; \ $(mkinstalldirs) $(DESTDIR)$(localedir); \ test -f $(DESTDIR)$(localedir)/locale.alias \ && orig=$(DESTDIR)$(localedir)/locale.alias \ || orig=$(srcdir)/locale.alias; \ temp=$(DESTDIR)$(localedir)/t-locale.alias; \ dest=$(DESTDIR)$(localedir)/locale.alias; \ sed -f ref-add.sed $$orig > $$temp; \ $(INSTALL_DATA) $$temp $$dest; \ rm -f $$temp; \ else \ : ; \ fi install-data: all if test "$(PACKAGE)" = "gettext"; then \ $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ $(INSTALL_DATA) VERSION $(DESTDIR)$(gettextsrcdir)/VERSION; \ $(INSTALL_DATA) ChangeLog.inst $(DESTDIR)$(gettextsrcdir)/ChangeLog; \ dists="COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common)"; \ for file in $$dists; do \ $(INSTALL_DATA) $(srcdir)/$$file \ $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ chmod a+x $(DESTDIR)$(gettextsrcdir)/config.charset; \ dists="$(DISTFILES.generated)"; \ for file in $$dists; do \ if test -f $$file; then dir=.; else dir=$(srcdir); fi; \ $(INSTALL_DATA) $$dir/$$file \ $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ dists="$(DISTFILES.obsolete)"; \ for file in $$dists; do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi install-strip: install installdirs: if test "$(PACKAGE)" = "gettext" \ && test '@INTLOBJS@' = '$(GETTOBJS)'; then \ $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \ else \ : ; \ fi if test '@USE_INCLUDED_LIBINTL@' = yes; then \ test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \ $(mkinstalldirs) $(DESTDIR)$(localedir); \ else \ : ; \ fi if test "$(PACKAGE)" = "gettext"; then \ $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ else \ : ; \ fi # Define this as empty until I found a useful application. installcheck: uninstall: if test "$(PACKAGE)" = "gettext" \ && test '@INTLOBJS@' = '$(GETTOBJS)'; then \ rm -f $(DESTDIR)$(includedir)/libintl.h; \ $(LIBTOOL) --mode=uninstall \ rm -f $(DESTDIR)$(libdir)/libintl.$la; \ else \ : ; \ fi if test '@USE_INCLUDED_LIBINTL@' = yes; then \ if test -f $(DESTDIR)$(libdir)/charset.alias; then \ temp=$(DESTDIR)$(libdir)/t-charset.alias; \ dest=$(DESTDIR)$(libdir)/charset.alias; \ sed -f ref-del.sed $$dest > $$temp; \ if grep '^# Packages using this file: $$' $$temp > /dev/null; then \ rm -f $$dest; \ else \ $(INSTALL_DATA) $$temp $$dest; \ fi; \ rm -f $$temp; \ fi; \ if test -f $(DESTDIR)$(localedir)/locale.alias; then \ temp=$(DESTDIR)$(localedir)/t-locale.alias; \ dest=$(DESTDIR)$(localedir)/locale.alias; \ sed -f ref-del.sed $$dest > $$temp; \ if grep '^# Packages using this file: $$' $$temp > /dev/null; then \ rm -f $$dest; \ else \ $(INSTALL_DATA) $$temp $$dest; \ fi; \ rm -f $$temp; \ fi; \ else \ : ; \ fi if test "$(PACKAGE)" = "gettext"; then \ for file in VERSION ChangeLog COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common) $(DISTFILES.generated); do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi info dvi: $(OBJECTS): ../config.h libgnuintl.h bindtextdom.$lo dcgettext.$lo dcigettext.$lo dcngettext.$lo dgettext.$lo dngettext.$lo finddomain.$lo gettext.$lo intl-compat.$lo loadmsgcat.$lo localealias.$lo ngettext.$lo textdomain.$lo: gettextP.h gmo.h loadinfo.h dcigettext.$lo: hash-string.h explodename.$lo l10nflist.$lo: loadinfo.h dcigettext.$lo loadmsgcat.$lo plural.$lo plural-exp.$lo: plural-exp.h dcigettext.$lo: eval-plural.h tags: TAGS TAGS: $(HEADERS) $(SOURCES) here=`pwd`; cd $(srcdir) && etags -o $$here/TAGS $(HEADERS) $(SOURCES) id: ID ID: $(HEADERS) $(SOURCES) here=`pwd`; cd $(srcdir) && mkid -f$$here/ID $(HEADERS) $(SOURCES) mostlyclean: rm -f *.a *.la *.o *.lo core core.* rm -f libintl.h charset.alias ref-add.sed ref-del.sed rm -f -r .libs _libs clean: mostlyclean distclean: clean rm -f Makefile ID TAGS if test "$(PACKAGE)" = gettext; then \ rm -f ChangeLog.inst $(DISTFILES.normal); \ else \ : ; \ fi maintainer-clean: distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." # GNU gettext needs not contain the file `VERSION' but contains some # other files which should not be distributed in other packages. distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) dist distdir: Makefile if test "$(PACKAGE)" = gettext; then \ additional="$(DISTFILES.gettext)"; \ else \ additional="$(DISTFILES.normal)"; \ fi; \ $(MAKE) $(DISTFILES.common) $(DISTFILES.generated) $$additional; \ for file in ChangeLog $(DISTFILES.common) $(DISTFILES.generated) $$additional; do \ if test -f $$file; then dir=.; else dir=$(srcdir); fi; \ cp -p $$dir/$$file $(distdir); \ done Makefile: Makefile.in ../config.status cd .. \ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status # Tell versions [3.59,3.63) of GNU make not to export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: kbuild-3686/src/oldsed/intl/osdep.c0000664000175000017500000000164715053010106017200 0ustar locutuslocutus/* OS dependent parts of libintl. Copyright (C) 2001-2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #if defined __EMX__ # include "os2compat.c" #else /* Avoid AIX compiler warning. */ typedef int dummy; #endif kbuild-3686/src/oldsed/intl/plural-exp.c0000664000175000017500000000772015053010105020154 0ustar locutuslocutus/* Expression parsing for plural form selection. Copyright (C) 2000, 2001 Free Software Foundation, Inc. Written by Ulrich Drepper , 2000. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "plural-exp.h" #if (defined __GNUC__ && !defined __APPLE_CC__) \ || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) /* These structs are the constant expression for the germanic plural form determination. It represents the expression "n != 1". */ static const struct expression plvar = { .nargs = 0, .operation = var, }; static const struct expression plone = { .nargs = 0, .operation = num, .val = { .num = 1 } }; struct expression GERMANIC_PLURAL = { .nargs = 2, .operation = not_equal, .val = { .args = { [0] = (struct expression *) &plvar, [1] = (struct expression *) &plone } } }; # define INIT_GERMANIC_PLURAL() #else /* For compilers without support for ISO C 99 struct/union initializers: Initialization at run-time. */ static struct expression plvar; static struct expression plone; struct expression GERMANIC_PLURAL; static void init_germanic_plural () { if (plone.val.num == 0) { plvar.nargs = 0; plvar.operation = var; plone.nargs = 0; plone.operation = num; plone.val.num = 1; GERMANIC_PLURAL.nargs = 2; GERMANIC_PLURAL.operation = not_equal; GERMANIC_PLURAL.val.args[0] = &plvar; GERMANIC_PLURAL.val.args[1] = &plone; } } # define INIT_GERMANIC_PLURAL() init_germanic_plural () #endif void internal_function EXTRACT_PLURAL_EXPRESSION (nullentry, pluralp, npluralsp) const char *nullentry; struct expression **pluralp; unsigned long int *npluralsp; { if (nullentry != NULL) { const char *plural; const char *nplurals; plural = strstr (nullentry, "plural="); nplurals = strstr (nullentry, "nplurals="); if (plural == NULL || nplurals == NULL) goto no_plural; else { char *endp; unsigned long int n; struct parse_args args; /* First get the number. */ nplurals += 9; while (*nplurals != '\0' && isspace ((unsigned char) *nplurals)) ++nplurals; if (!(*nplurals >= '0' && *nplurals <= '9')) goto no_plural; #if defined HAVE_STRTOUL || defined _LIBC n = strtoul (nplurals, &endp, 10); #else for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++) n = n * 10 + (*endp - '0'); #endif if (nplurals == endp) goto no_plural; *npluralsp = n; /* Due to the restrictions bison imposes onto the interface of the scanner function we have to put the input string and the result passed up from the parser into the same structure which address is passed down to the parser. */ plural += 7; args.cp = plural; if (PLURAL_PARSE (&args) != 0) goto no_plural; *pluralp = args.res; } } else { /* By default we are using the Germanic form: singular form only for `one', the plural form otherwise. Yes, this is also what English is using since English is a Germanic language. */ no_plural: INIT_GERMANIC_PLURAL (); *pluralp = &GERMANIC_PLURAL; *npluralsp = 2; } } kbuild-3686/src/oldsed/intl/libgnuintl.h0000664000175000017500000001124215053010106020232 0ustar locutuslocutus/* Message catalogs for internationalization. Copyright (C) 1995-1997, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _LIBINTL_H #define _LIBINTL_H 1 #include /* The LC_MESSAGES locale category is the category used by the functions gettext() and dgettext(). It is specified in POSIX, but not in ANSI C. On systems that don't define it, use an arbitrary value instead. On Solaris, defines __LOCALE_H then includes (i.e. this file!) and then only defines LC_MESSAGES. To avoid a redefinition warning, don't define LC_MESSAGES in this case. */ #if !defined LC_MESSAGES && !defined __LOCALE_H # define LC_MESSAGES 1729 #endif /* We define an additional symbol to signal that we use the GNU implementation of gettext. */ #define __USE_GNU_GETTEXT 1 /* Resolve a platform specific conflict on DJGPP. GNU gettext takes precedence over _conio_gettext. */ #ifdef __DJGPP__ # undef gettext # define gettext gettext #endif /* Use _INTL_PARAMS, not PARAMS, in order to avoid clashes with identifiers used by programs. Similarly, test __PROTOTYPES, not PROTOTYPES. */ #ifndef _INTL_PARAMS # if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES # define _INTL_PARAMS(args) args # else # define _INTL_PARAMS(args) () # endif #endif #ifdef __cplusplus extern "C" { #endif /* Look up MSGID in the current default message catalog for the current LC_MESSAGES locale. If not found, returns MSGID itself (the default text). */ extern char *gettext _INTL_PARAMS ((const char *__msgid)); /* Look up MSGID in the DOMAINNAME message catalog for the current LC_MESSAGES locale. */ extern char *dgettext _INTL_PARAMS ((const char *__domainname, const char *__msgid)); /* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY locale. */ extern char *dcgettext _INTL_PARAMS ((const char *__domainname, const char *__msgid, int __category)); /* Similar to `gettext' but select the plural form corresponding to the number N. */ extern char *ngettext _INTL_PARAMS ((const char *__msgid1, const char *__msgid2, unsigned long int __n)); /* Similar to `dgettext' but select the plural form corresponding to the number N. */ extern char *dngettext _INTL_PARAMS ((const char *__domainname, const char *__msgid1, const char *__msgid2, unsigned long int __n)); /* Similar to `dcgettext' but select the plural form corresponding to the number N. */ extern char *dcngettext _INTL_PARAMS ((const char *__domainname, const char *__msgid1, const char *__msgid2, unsigned long int __n, int __category)); /* Set the current default message catalog to DOMAINNAME. If DOMAINNAME is null, return the current default. If DOMAINNAME is "", reset to the default of "messages". */ extern char *textdomain _INTL_PARAMS ((const char *__domainname)); /* Specify that the DOMAINNAME message catalog will be found in DIRNAME rather than in the system locale data base. */ extern char *bindtextdomain _INTL_PARAMS ((const char *__domainname, const char *__dirname)); /* Specify the character encoding in which the messages from the DOMAINNAME message catalog will be returned. */ extern char *bind_textdomain_codeset _INTL_PARAMS ((const char *__domainname, const char *__codeset)); /* Optimized version of the functions above. */ #if defined __OPTIMIZED /* These are macros, but could also be inline functions. */ # define gettext(msgid) \ dgettext (NULL, msgid) # define dgettext(domainname, msgid) \ dcgettext (domainname, msgid, LC_MESSAGES) # define ngettext(msgid1, msgid2, n) \ dngettext (NULL, msgid1, msgid2, n) # define dngettext(domainname, msgid1, msgid2, n) \ dcngettext (domainname, msgid1, msgid2, n, LC_MESSAGES) #endif /* Optimizing. */ #ifdef __cplusplus } #endif #endif /* libintl.h */ kbuild-3686/src/oldsed/intl/plural-exp.h0000664000175000017500000001013615053010106020155 0ustar locutuslocutus/* Expression parsing and evaluation for plural form selection. Copyright (C) 2000, 2001 Free Software Foundation, Inc. Written by Ulrich Drepper , 2000. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _PLURAL_EXP_H #define _PLURAL_EXP_H #ifndef PARAMS # if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES # define PARAMS(args) args # else # define PARAMS(args) () # endif #endif #ifndef internal_function # define internal_function #endif /* This is the representation of the expressions to determine the plural form. */ struct expression { int nargs; /* Number of arguments. */ enum operator { /* Without arguments: */ var, /* The variable "n". */ num, /* Decimal number. */ /* Unary operators: */ lnot, /* Logical NOT. */ /* Binary operators: */ mult, /* Multiplication. */ divide, /* Division. */ module, /* Modulo operation. */ plus, /* Addition. */ minus, /* Subtraction. */ less_than, /* Comparison. */ greater_than, /* Comparison. */ less_or_equal, /* Comparison. */ greater_or_equal, /* Comparison. */ equal, /* Comparison for equality. */ not_equal, /* Comparison for inequality. */ land, /* Logical AND. */ lor, /* Logical OR. */ /* Ternary operators: */ qmop /* Question mark operator. */ } operation; union { unsigned long int num; /* Number value for `num'. */ struct expression *args[3]; /* Up to three arguments. */ } val; }; /* This is the data structure to pass information to the parser and get the result in a thread-safe way. */ struct parse_args { const char *cp; struct expression *res; }; /* Names for the libintl functions are a problem. This source code is used 1. in the GNU C Library library, 2. in the GNU libintl library, 3. in the GNU gettext tools. The function names in each situation must be different, to allow for binary incompatible changes in 'struct expression'. Furthermore, 1. in the GNU C Library library, the names have a __ prefix, 2.+3. in the GNU libintl library and in the GNU gettext tools, the names must follow ANSI C and not start with __. So we have to distinguish the three cases. */ #ifdef _LIBC # define FREE_EXPRESSION __gettext_free_exp # define PLURAL_PARSE __gettextparse # define GERMANIC_PLURAL __gettext_germanic_plural # define EXTRACT_PLURAL_EXPRESSION __gettext_extract_plural #elif defined (IN_LIBINTL) # define FREE_EXPRESSION gettext_free_exp__ # define PLURAL_PARSE gettextparse__ # define GERMANIC_PLURAL gettext_germanic_plural__ # define EXTRACT_PLURAL_EXPRESSION gettext_extract_plural__ #else # define FREE_EXPRESSION free_plural_expression # define PLURAL_PARSE parse_plural_expression # define GERMANIC_PLURAL germanic_plural # define EXTRACT_PLURAL_EXPRESSION extract_plural_expression #endif extern void FREE_EXPRESSION PARAMS ((struct expression *exp)) internal_function; extern int PLURAL_PARSE PARAMS ((void *arg)); extern struct expression GERMANIC_PLURAL; extern void EXTRACT_PLURAL_EXPRESSION PARAMS ((const char *nullentry, struct expression **pluralp, unsigned long int *npluralsp)) internal_function; #if !defined (_LIBC) && !defined (IN_LIBINTL) extern unsigned long int plural_eval PARAMS ((struct expression *pexp, unsigned long int n)); #endif #endif /* _PLURAL_EXP_H */ kbuild-3686/src/oldsed/intl/hash-string.h0000664000175000017500000000360015053010106020311 0ustar locutuslocutus/* Description of GNU message catalog format: string hashing function. Copyright (C) 1995, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* @@ end of prolog @@ */ #ifndef PARAMS # if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES # define PARAMS(Args) Args # else # define PARAMS(Args) () # endif #endif /* We assume to have `unsigned long int' value with at least 32 bits. */ #define HASHWORDBITS 32 /* Defines the so called `hashpjw' function by P.J. Weinberger [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, 1986, 1987 Bell Telephone Laboratories, Inc.] */ static unsigned long int hash_string PARAMS ((const char *__str_param)); static inline unsigned long int hash_string (str_param) const char *str_param; { unsigned long int hval, g; const char *str = str_param; /* Compute the hash value for the given string. */ hval = 0; while (*str != '\0') { hval <<= 4; hval += (unsigned long int) *str++; g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); if (g != 0) { hval ^= g >> (HASHWORDBITS - 8); hval ^= g; } } return hval; } kbuild-3686/src/oldsed/intl/bindtextdom.c0000664000175000017500000002316715053010106020410 0ustar locutuslocutus/* Implementation of the bindtextdomain(3) function Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #ifdef _LIBC # include #else # include "libgnuintl.h" #endif #include "gettextP.h" #ifdef _LIBC /* We have to handle multi-threaded applications. */ # include #else /* Provide dummy implementation if this is outside glibc. */ # define __libc_rwlock_define(CLASS, NAME) # define __libc_rwlock_wrlock(NAME) # define __libc_rwlock_unlock(NAME) #endif /* The internal variables in the standalone libintl.a must have different names than the internal variables in GNU libc, otherwise programs using libintl.a cannot be linked statically. */ #if !defined _LIBC # define _nl_default_dirname _nl_default_dirname__ # define _nl_domain_bindings _nl_domain_bindings__ #endif /* Some compilers, like SunOS4 cc, don't have offsetof in . */ #ifndef offsetof # define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) #endif /* @@ end of prolog @@ */ /* Contains the default location of the message catalogs. */ extern const char _nl_default_dirname[]; /* List with bindings of specific domains. */ extern struct binding *_nl_domain_bindings; /* Lock variable to protect the global data in the gettext implementation. */ __libc_rwlock_define (extern, _nl_state_lock) /* Names for the libintl functions are a problem. They must not clash with existing names and they should follow ANSI C. But this source code is also used in GNU C Library where the names have a __ prefix. So we have to make a difference here. */ #ifdef _LIBC # define BINDTEXTDOMAIN __bindtextdomain # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset # ifndef strdup # define strdup(str) __strdup (str) # endif #else # define BINDTEXTDOMAIN bindtextdomain__ # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__ #endif /* Prototypes for local functions. */ static void set_binding_values PARAMS ((const char *domainname, const char **dirnamep, const char **codesetp)); /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP to be used for the DOMAINNAME message catalog. If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not modified, only the current value is returned. If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither modified nor returned. */ static void set_binding_values (domainname, dirnamep, codesetp) const char *domainname; const char **dirnamep; const char **codesetp; { struct binding *binding; int modified; /* Some sanity checks. */ if (domainname == NULL || domainname[0] == '\0') { if (dirnamep) *dirnamep = NULL; if (codesetp) *codesetp = NULL; return; } __libc_rwlock_wrlock (_nl_state_lock); modified = 0; for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) { int compare = strcmp (domainname, binding->domainname); if (compare == 0) /* We found it! */ break; if (compare < 0) { /* It is not in the list. */ binding = NULL; break; } } if (binding != NULL) { if (dirnamep) { const char *dirname = *dirnamep; if (dirname == NULL) /* The current binding has be to returned. */ *dirnamep = binding->dirname; else { /* The domain is already bound. If the new value and the old one are equal we simply do nothing. Otherwise replace the old binding. */ char *result = binding->dirname; if (strcmp (dirname, result) != 0) { if (strcmp (dirname, _nl_default_dirname) == 0) result = (char *) _nl_default_dirname; else { #if defined _LIBC || defined HAVE_STRDUP result = strdup (dirname); #else size_t len = strlen (dirname) + 1; result = (char *) malloc (len); if (__builtin_expect (result != NULL, 1)) memcpy (result, dirname, len); #endif } if (__builtin_expect (result != NULL, 1)) { if (binding->dirname != _nl_default_dirname) free (binding->dirname); binding->dirname = result; modified = 1; } } *dirnamep = result; } } if (codesetp) { const char *codeset = *codesetp; if (codeset == NULL) /* The current binding has be to returned. */ *codesetp = binding->codeset; else { /* The domain is already bound. If the new value and the old one are equal we simply do nothing. Otherwise replace the old binding. */ char *result = binding->codeset; if (result == NULL || strcmp (codeset, result) != 0) { #if defined _LIBC || defined HAVE_STRDUP result = strdup (codeset); #else size_t len = strlen (codeset) + 1; result = (char *) malloc (len); if (__builtin_expect (result != NULL, 1)) memcpy (result, codeset, len); #endif if (__builtin_expect (result != NULL, 1)) { if (binding->codeset != NULL) free (binding->codeset); binding->codeset = result; binding->codeset_cntr++; modified = 1; } } *codesetp = result; } } } else if ((dirnamep == NULL || *dirnamep == NULL) && (codesetp == NULL || *codesetp == NULL)) { /* Simply return the default values. */ if (dirnamep) *dirnamep = _nl_default_dirname; if (codesetp) *codesetp = NULL; } else { /* We have to create a new binding. */ size_t len = strlen (domainname) + 1; struct binding *new_binding = (struct binding *) malloc (offsetof (struct binding, domainname) + len); if (__builtin_expect (new_binding == NULL, 0)) goto failed; memcpy (new_binding->domainname, domainname, len); if (dirnamep) { const char *dirname = *dirnamep; if (dirname == NULL) /* The default value. */ dirname = _nl_default_dirname; else { if (strcmp (dirname, _nl_default_dirname) == 0) dirname = _nl_default_dirname; else { char *result; #if defined _LIBC || defined HAVE_STRDUP result = strdup (dirname); if (__builtin_expect (result == NULL, 0)) goto failed_dirname; #else size_t len = strlen (dirname) + 1; result = (char *) malloc (len); if (__builtin_expect (result == NULL, 0)) goto failed_dirname; memcpy (result, dirname, len); #endif dirname = result; } } *dirnamep = dirname; new_binding->dirname = (char *) dirname; } else /* The default value. */ new_binding->dirname = (char *) _nl_default_dirname; new_binding->codeset_cntr = 0; if (codesetp) { const char *codeset = *codesetp; if (codeset != NULL) { char *result; #if defined _LIBC || defined HAVE_STRDUP result = strdup (codeset); if (__builtin_expect (result == NULL, 0)) goto failed_codeset; #else size_t len = strlen (codeset) + 1; result = (char *) malloc (len); if (__builtin_expect (result == NULL, 0)) goto failed_codeset; memcpy (result, codeset, len); #endif codeset = result; new_binding->codeset_cntr++; } *codesetp = codeset; new_binding->codeset = (char *) codeset; } else new_binding->codeset = NULL; /* Now enqueue it. */ if (_nl_domain_bindings == NULL || strcmp (domainname, _nl_domain_bindings->domainname) < 0) { new_binding->next = _nl_domain_bindings; _nl_domain_bindings = new_binding; } else { binding = _nl_domain_bindings; while (binding->next != NULL && strcmp (domainname, binding->next->domainname) > 0) binding = binding->next; new_binding->next = binding->next; binding->next = new_binding; } modified = 1; /* Here we deal with memory allocation failures. */ if (0) { failed_codeset: if (new_binding->dirname != _nl_default_dirname) free (new_binding->dirname); failed_dirname: free (new_binding); failed: if (dirnamep) *dirnamep = NULL; if (codesetp) *codesetp = NULL; } } /* If we modified any binding, we flush the caches. */ if (modified) ++_nl_msg_cat_cntr; __libc_rwlock_unlock (_nl_state_lock); } /* Specify that the DOMAINNAME message catalog will be found in DIRNAME rather than in the system locale data base. */ char * BINDTEXTDOMAIN (domainname, dirname) const char *domainname; const char *dirname; { set_binding_values (domainname, &dirname, NULL); return (char *) dirname; } /* Specify the character encoding in which the messages from the DOMAINNAME message catalog will be returned. */ char * BIND_TEXTDOMAIN_CODESET (domainname, codeset) const char *domainname; const char *codeset; { set_binding_values (domainname, NULL, &codeset); return (char *) codeset; } #ifdef _LIBC /* Aliases for function names in GNU C Library. */ weak_alias (__bindtextdomain, bindtextdomain); weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset); #endif kbuild-3686/src/oldsed/intl/os2compat.c0000664000175000017500000000657315053010106020000 0ustar locutuslocutus/* OS/2 compatibility functions. Copyright (C) 2001-2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #define OS2_AWARE #ifdef HAVE_CONFIG_H #include #endif #include #include /* A version of getenv() that works from DLLs */ extern unsigned long DosScanEnv (const unsigned char *pszName, unsigned char **ppszValue); char * _nl_getenv (const char *name) { unsigned char *value; if (DosScanEnv (name, &value)) return NULL; else return value; } char _nl_default_dirname[] = /* a 260+1 bytes large buffer */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0" #define LOCALEDIR_MAX 260 char *_os2_libdir = NULL; char *_os2_localealiaspath = NULL; char *_os2_localedir = NULL; static __attribute__((constructor)) void os2_initialize () { char *root = getenv ("UNIXROOT"); char *gnulocaledir = getenv ("GNULOCALEDIR"); _os2_libdir = gnulocaledir; if (!_os2_libdir) { if (root) { size_t sl = strlen (root); _os2_libdir = (char *) malloc (sl + strlen (LIBDIR) + 1); memcpy (_os2_libdir, root, sl); memcpy (_os2_libdir + sl, LIBDIR, strlen (LIBDIR) + 1); } else _os2_libdir = LIBDIR; } _os2_localealiaspath = gnulocaledir; if (!_os2_localealiaspath) { if (root) { size_t sl = strlen (root); _os2_localealiaspath = (char *) malloc (sl + strlen (LOCALE_ALIAS_PATH) + 1); memcpy (_os2_localealiaspath, root, sl); memcpy (_os2_localealiaspath + sl, LOCALE_ALIAS_PATH, strlen (LOCALE_ALIAS_PATH) + 1); } else _os2_localealiaspath = LOCALE_ALIAS_PATH; } _os2_localedir = gnulocaledir; if (!_os2_localedir) { if (root) { size_t sl = strlen (root); _os2_localedir = (char *) malloc (sl + strlen (LOCALEDIR) + 1); memcpy (_os2_localedir, root, sl); memcpy (_os2_localedir + sl, LOCALEDIR, strlen (LOCALEDIR) + 1); } else _os2_localedir = LOCALEDIR; } { extern const char _nl_default_dirname__[]; if (strlen (_os2_localedir) <= LOCALEDIR_MAX) strcpy (_nl_default_dirname__, _os2_localedir); } } kbuild-3686/src/oldsed/intl/dcngettext.c0000664000175000017500000000355115053010106020233 0ustar locutuslocutus/* Implementation of the dcngettext(3) function. Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "gettextP.h" #ifdef _LIBC # include #else # include "libgnuintl.h" #endif /* @@ end of prolog @@ */ /* Names for the libintl functions are a problem. They must not clash with existing names and they should follow ANSI C. But this source code is also used in GNU C Library where the names have a __ prefix. So we have to make a difference here. */ #ifdef _LIBC # define DCNGETTEXT __dcngettext # define DCIGETTEXT __dcigettext #else # define DCNGETTEXT dcngettext__ # define DCIGETTEXT dcigettext__ #endif /* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY locale. */ char * DCNGETTEXT (domainname, msgid1, msgid2, n, category) const char *domainname; const char *msgid1; const char *msgid2; unsigned long int n; int category; { return DCIGETTEXT (domainname, msgid1, msgid2, 1, n, category); } #ifdef _LIBC /* Alias for function name in GNU C Library. */ weak_alias (__dcngettext, dcngettext); #endif kbuild-3686/src/oldsed/intl/dgettext.c0000664000175000017500000000340215053010106017705 0ustar locutuslocutus/* Implementation of the dgettext(3) function. Copyright (C) 1995-1997, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "gettextP.h" #ifdef _LIBC # include #else # include "libgnuintl.h" #endif /* @@ end of prolog @@ */ /* Names for the libintl functions are a problem. They must not clash with existing names and they should follow ANSI C. But this source code is also used in GNU C Library where the names have a __ prefix. So we have to make a difference here. */ #ifdef _LIBC # define DGETTEXT __dgettext # define DCGETTEXT __dcgettext #else # define DGETTEXT dgettext__ # define DCGETTEXT dcgettext__ #endif /* Look up MSGID in the DOMAINNAME message catalog of the current LC_MESSAGES locale. */ char * DGETTEXT (domainname, msgid) const char *domainname; const char *msgid; { return DCGETTEXT (domainname, msgid, LC_MESSAGES); } #ifdef _LIBC /* Alias for function name in GNU C Library. */ weak_alias (__dgettext, dgettext); #endif kbuild-3686/src/oldsed/intl/ref-del.sin0000664000175000017500000000203015053010105017735 0ustar locutuslocutus# Remove this package from a list of references stored in a text file. # # Copyright (C) 2000 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU Library General Public License as published # by the Free Software Foundation; either version 2, 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # # Written by Bruno Haible . # /^# Packages using this file: / { s/# Packages using this file:// s/ @PACKAGE@ / / s/^/# Packages using this file:/ } kbuild-3686/src/oldsed/intl/localealias.c0000664000175000017500000002330715053010105020333 0ustar locutuslocutus/* Handle aliases for locale names. Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Tell glibc's to provide a prototype for mempcpy(). This must come before because may include , and once has been included, it's too late. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif #ifdef HAVE_CONFIG_H # include #endif #include #include #if defined _LIBC || defined HAVE___FSETLOCKING # include #endif #include #ifdef __GNUC__ # define alloca __builtin_alloca # define HAVE_ALLOCA 1 #else # if defined HAVE_ALLOCA_H || defined _LIBC # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca char *alloca (); # endif # endif # endif #endif #include #include #include "gettextP.h" /* @@ end of prolog @@ */ #ifdef _LIBC /* Rename the non ANSI C functions. This is required by the standard because some ANSI C functions will require linking with this object file and the name space must not be polluted. */ # define strcasecmp __strcasecmp # ifndef mempcpy # define mempcpy __mempcpy # endif # define HAVE_MEMPCPY 1 # define HAVE___FSETLOCKING 1 /* We need locking here since we can be called from different places. */ # include __libc_lock_define_initialized (static, lock); #endif #ifndef internal_function # define internal_function #endif /* Some optimizations for glibc. */ #ifdef _LIBC # define FEOF(fp) feof_unlocked (fp) # define FGETS(buf, n, fp) fgets_unlocked (buf, n, fp) #else # define FEOF(fp) feof (fp) # define FGETS(buf, n, fp) fgets (buf, n, fp) #endif /* For those losing systems which don't have `alloca' we have to add some additional code emulating it. */ #ifdef HAVE_ALLOCA # define freea(p) /* nothing */ #else # define alloca(n) malloc (n) # define freea(p) free (p) #endif #if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED # undef fgets # define fgets(buf, len, s) fgets_unlocked (buf, len, s) #endif #if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED # undef feof # define feof(s) feof_unlocked (s) #endif struct alias_map { const char *alias; const char *value; }; static char *string_space; static size_t string_space_act; static size_t string_space_max; static struct alias_map *map; static size_t nmap; static size_t maxmap; /* Prototypes for local functions. */ static size_t read_alias_file PARAMS ((const char *fname, int fname_len)) internal_function; static int extend_alias_table PARAMS ((void)); static int alias_compare PARAMS ((const struct alias_map *map1, const struct alias_map *map2)); const char * _nl_expand_alias (name) const char *name; { static const char *locale_alias_path; struct alias_map *retval; const char *result = NULL; size_t added; #ifdef _LIBC __libc_lock_lock (lock); #endif if (locale_alias_path == NULL) locale_alias_path = LOCALE_ALIAS_PATH; do { struct alias_map item; item.alias = name; if (nmap > 0) retval = (struct alias_map *) bsearch (&item, map, nmap, sizeof (struct alias_map), (int (*) PARAMS ((const void *, const void *)) ) alias_compare); else retval = NULL; /* We really found an alias. Return the value. */ if (retval != NULL) { result = retval->value; break; } /* Perhaps we can find another alias file. */ added = 0; while (added == 0 && locale_alias_path[0] != '\0') { const char *start; while (locale_alias_path[0] == PATH_SEPARATOR) ++locale_alias_path; start = locale_alias_path; while (locale_alias_path[0] != '\0' && locale_alias_path[0] != PATH_SEPARATOR) ++locale_alias_path; if (start < locale_alias_path) added = read_alias_file (start, locale_alias_path - start); } } while (added != 0); #ifdef _LIBC __libc_lock_unlock (lock); #endif return result; } static size_t internal_function read_alias_file (fname, fname_len) const char *fname; int fname_len; { FILE *fp; char *full_fname; size_t added; static const char aliasfile[] = "/locale.alias"; full_fname = (char *) alloca (fname_len + sizeof aliasfile); #ifdef HAVE_MEMPCPY mempcpy (mempcpy (full_fname, fname, fname_len), aliasfile, sizeof aliasfile); #else memcpy (full_fname, fname, fname_len); memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile); #endif fp = fopen (full_fname, "r"); freea (full_fname); if (fp == NULL) return 0; #ifdef HAVE___FSETLOCKING /* No threads present. */ __fsetlocking (fp, FSETLOCKING_BYCALLER); #endif added = 0; while (!FEOF (fp)) { /* It is a reasonable approach to use a fix buffer here because a) we are only interested in the first two fields b) these fields must be usable as file names and so must not be that long */ char buf[BUFSIZ]; char *alias; char *value; char *cp; if (FGETS (buf, sizeof buf, fp) == NULL) /* EOF reached. */ break; /* Possibly not the whole line fits into the buffer. Ignore the rest of the line. */ if (strchr (buf, '\n') == NULL) { char altbuf[BUFSIZ]; do if (FGETS (altbuf, sizeof altbuf, fp) == NULL) /* Make sure the inner loop will be left. The outer loop will exit at the `feof' test. */ break; while (strchr (altbuf, '\n') == NULL); } cp = buf; /* Ignore leading white space. */ while (isspace ((unsigned char) cp[0])) ++cp; /* A leading '#' signals a comment line. */ if (cp[0] != '\0' && cp[0] != '#') { alias = cp++; while (cp[0] != '\0' && !isspace ((unsigned char) cp[0])) ++cp; /* Terminate alias name. */ if (cp[0] != '\0') *cp++ = '\0'; /* Now look for the beginning of the value. */ while (isspace ((unsigned char) cp[0])) ++cp; if (cp[0] != '\0') { size_t alias_len; size_t value_len; value = cp++; while (cp[0] != '\0' && !isspace ((unsigned char) cp[0])) ++cp; /* Terminate value. */ if (cp[0] == '\n') { /* This has to be done to make the following test for the end of line possible. We are looking for the terminating '\n' which do not overwrite here. */ *cp++ = '\0'; *cp = '\n'; } else if (cp[0] != '\0') *cp++ = '\0'; if (nmap >= maxmap) if (__builtin_expect (extend_alias_table (), 0)) return added; alias_len = strlen (alias) + 1; value_len = strlen (value) + 1; if (string_space_act + alias_len + value_len > string_space_max) { /* Increase size of memory pool. */ size_t new_size = (string_space_max + (alias_len + value_len > 1024 ? alias_len + value_len : 1024)); char *new_pool = (char *) realloc (string_space, new_size); if (new_pool == NULL) return added; if (__builtin_expect (string_space != new_pool, 0)) { size_t i; for (i = 0; i < nmap; i++) { map[i].alias += new_pool - string_space; map[i].value += new_pool - string_space; } } string_space = new_pool; string_space_max = new_size; } map[nmap].alias = memcpy (&string_space[string_space_act], alias, alias_len); string_space_act += alias_len; map[nmap].value = memcpy (&string_space[string_space_act], value, value_len); string_space_act += value_len; ++nmap; ++added; } } } /* Should we test for ferror()? I think we have to silently ignore errors. --drepper */ fclose (fp); if (added > 0) qsort (map, nmap, sizeof (struct alias_map), (int (*) PARAMS ((const void *, const void *))) alias_compare); return added; } static int extend_alias_table () { size_t new_size; struct alias_map *new_map; new_size = maxmap == 0 ? 100 : 2 * maxmap; new_map = (struct alias_map *) realloc (map, (new_size * sizeof (struct alias_map))); if (new_map == NULL) /* Simply don't extend: we don't have any more core. */ return -1; map = new_map; maxmap = new_size; return 0; } #ifdef _LIBC static void __attribute__ ((unused)) free_mem (void) { if (string_space != NULL) free (string_space); if (map != NULL) free (map); } text_set_element (__libc_subfreeres, free_mem); #endif static int alias_compare (map1, map2) const struct alias_map *map1; const struct alias_map *map2; { #if defined _LIBC || defined HAVE_STRCASECMP return strcasecmp (map1->alias, map2->alias); #else const unsigned char *p1 = (const unsigned char *) map1->alias; const unsigned char *p2 = (const unsigned char *) map2->alias; unsigned char c1, c2; if (p1 == p2) return 0; do { /* I know this seems to be odd but the tolower() function in some systems libc cannot handle nonalpha characters. */ c1 = isupper (*p1) ? tolower (*p1) : *p1; c2 = isupper (*p2) ? tolower (*p2) : *p2; if (c1 == '\0') break; ++p1; ++p2; } while (c1 == c2); return c1 - c2; #endif } kbuild-3686/src/oldsed/intl/gettextP.h0000664000175000017500000001425215053010105017672 0ustar locutuslocutus/* Header describing internals of libintl library. Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. Written by Ulrich Drepper , 1995. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _GETTEXTP_H #define _GETTEXTP_H #include /* Get size_t. */ #ifdef _LIBC # include "../iconv/gconv_int.h" #else # if HAVE_ICONV # include # endif #endif #include "loadinfo.h" #include "gmo.h" /* Get nls_uint32. */ /* @@ end of prolog @@ */ #ifndef PARAMS # if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES # define PARAMS(args) args # else # define PARAMS(args) () # endif #endif #ifndef internal_function # define internal_function #endif /* Tell the compiler when a conditional or integer expression is almost always true or almost always false. */ #ifndef HAVE_BUILTIN_EXPECT # define __builtin_expect(expr, val) (expr) #endif #ifndef W # define W(flag, data) ((flag) ? SWAP (data) : (data)) #endif #ifdef _LIBC # include # define SWAP(i) bswap_32 (i) #else static inline nls_uint32 SWAP (i) nls_uint32 i; { return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24); } #endif /* The representation of an opened message catalog. */ struct loaded_domain { const char *data; int use_mmap; size_t mmap_size; int must_swap; nls_uint32 nstrings; struct string_desc *orig_tab; struct string_desc *trans_tab; nls_uint32 hash_size; nls_uint32 *hash_tab; int codeset_cntr; #ifdef _LIBC __gconv_t conv; #else # if HAVE_ICONV iconv_t conv; # endif #endif char **conv_tab; struct expression *plural; unsigned long int nplurals; }; /* We want to allocate a string at the end of the struct. But ISO C doesn't allow zero sized arrays. */ #ifdef __GNUC__ # define ZERO 0 #else # define ZERO 1 #endif /* A set of settings bound to a message domain. Used to store settings from bindtextdomain() and bind_textdomain_codeset(). */ struct binding { struct binding *next; char *dirname; int codeset_cntr; /* Incremented each time codeset changes. */ char *codeset; char domainname[ZERO]; }; /* A counter which is incremented each time some previous translations become invalid. This variable is part of the external ABI of the GNU libintl. */ extern int _nl_msg_cat_cntr; #ifndef _LIBC const char *_nl_locale_name PARAMS ((int category, const char *categoryname)); #endif struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname, char *__locale, const char *__domainname, struct binding *__domainbinding)) internal_function; void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain, struct binding *__domainbinding)) internal_function; void _nl_unload_domain PARAMS ((struct loaded_domain *__domain)) internal_function; const char *_nl_init_domain_conv PARAMS ((struct loaded_l10nfile *__domain_file, struct loaded_domain *__domain, struct binding *__domainbinding)) internal_function; void _nl_free_domain_conv PARAMS ((struct loaded_domain *__domain)) internal_function; char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file, struct binding *domainbinding, const char *msgid, size_t *lengthp)) internal_function; #ifdef _LIBC extern char *__gettext PARAMS ((const char *__msgid)); extern char *__dgettext PARAMS ((const char *__domainname, const char *__msgid)); extern char *__dcgettext PARAMS ((const char *__domainname, const char *__msgid, int __category)); extern char *__ngettext PARAMS ((const char *__msgid1, const char *__msgid2, unsigned long int __n)); extern char *__dngettext PARAMS ((const char *__domainname, const char *__msgid1, const char *__msgid2, unsigned long int n)); extern char *__dcngettext PARAMS ((const char *__domainname, const char *__msgid1, const char *__msgid2, unsigned long int __n, int __category)); extern char *__dcigettext PARAMS ((const char *__domainname, const char *__msgid1, const char *__msgid2, int __plural, unsigned long int __n, int __category)); extern char *__textdomain PARAMS ((const char *__domainname)); extern char *__bindtextdomain PARAMS ((const char *__domainname, const char *__dirname)); extern char *__bind_textdomain_codeset PARAMS ((const char *__domainname, const char *__codeset)); #else extern char *gettext__ PARAMS ((const char *__msgid)); extern char *dgettext__ PARAMS ((const char *__domainname, const char *__msgid)); extern char *dcgettext__ PARAMS ((const char *__domainname, const char *__msgid, int __category)); extern char *ngettext__ PARAMS ((const char *__msgid1, const char *__msgid2, unsigned long int __n)); extern char *dngettext__ PARAMS ((const char *__domainname, const char *__msgid1, const char *__msgid2, unsigned long int __n)); extern char *dcngettext__ PARAMS ((const char *__domainname, const char *__msgid1, const char *__msgid2, unsigned long int __n, int __category)); extern char *dcigettext__ PARAMS ((const char *__domainname, const char *__msgid1, const char *__msgid2, int __plural, unsigned long int __n, int __category)); extern char *textdomain__ PARAMS ((const char *__domainname)); extern char *bindtextdomain__ PARAMS ((const char *__domainname, const char *__dirname)); extern char *bind_textdomain_codeset__ PARAMS ((const char *__domainname, const char *__codeset)); #endif /* @@ begin of epilog @@ */ #endif /* gettextP.h */ kbuild-3686/src/oldsed/intl/config.charset0000775000175000017500000003220015053010105020531 0ustar locutuslocutus#! /bin/sh # Output a system dependent table of character encoding aliases. # # Copyright (C) 2000-2002 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU Library General Public License as published # by the Free Software Foundation; either version 2, 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # # The table consists of lines of the form # ALIAS CANONICAL # # ALIAS is the (system dependent) result of "nl_langinfo (CODESET)". # ALIAS is compared in a case sensitive way. # # CANONICAL is the GNU canonical name for this character encoding. # It must be an encoding supported by libiconv. Support by GNU libc is # also desirable. CANONICAL is case insensitive. Usually an upper case # MIME charset name is preferred. # The current list of GNU canonical charset names is as follows. # # name used by which systems a MIME name? # ASCII, ANSI_X3.4-1968 glibc solaris freebsd # ISO-8859-1 glibc aix hpux irix osf solaris freebsd yes # ISO-8859-2 glibc aix hpux irix osf solaris freebsd yes # ISO-8859-3 glibc yes # ISO-8859-4 osf solaris freebsd yes # ISO-8859-5 glibc aix hpux irix osf solaris freebsd yes # ISO-8859-6 glibc aix hpux solaris yes # ISO-8859-7 glibc aix hpux irix osf solaris yes # ISO-8859-8 glibc aix hpux osf solaris yes # ISO-8859-9 glibc aix hpux irix osf solaris yes # ISO-8859-13 glibc # ISO-8859-15 glibc aix osf solaris freebsd # KOI8-R glibc solaris freebsd yes # KOI8-U glibc freebsd yes # CP437 dos # CP775 dos # CP850 aix osf dos # CP852 dos # CP855 dos # CP856 aix # CP857 dos # CP861 dos # CP862 dos # CP864 dos # CP865 dos # CP866 freebsd dos # CP869 dos # CP874 win32 dos # CP922 aix # CP932 aix win32 dos # CP943 aix # CP949 osf win32 dos # CP950 win32 dos # CP1046 aix # CP1124 aix # CP1129 aix # CP1250 win32 # CP1251 glibc win32 # CP1252 aix win32 # CP1253 win32 # CP1254 win32 # CP1255 win32 # CP1256 win32 # CP1257 win32 # GB2312 glibc aix hpux irix solaris freebsd yes # EUC-JP glibc aix hpux irix osf solaris freebsd yes # EUC-KR glibc aix hpux irix osf solaris freebsd yes # EUC-TW glibc aix hpux irix osf solaris # BIG5 glibc aix hpux osf solaris freebsd yes # BIG5-HKSCS glibc # GBK aix osf win32 dos # GB18030 glibc # SHIFT_JIS hpux osf solaris freebsd yes # JOHAB glibc win32 # TIS-620 glibc aix hpux osf solaris # VISCII glibc yes # HP-ROMAN8 hpux # HP-ARABIC8 hpux # HP-GREEK8 hpux # HP-HEBREW8 hpux # HP-TURKISH8 hpux # HP-KANA8 hpux # DEC-KANJI osf # DEC-HANYU osf # UTF-8 glibc aix hpux osf solaris yes # # Note: Names which are not marked as being a MIME name should not be used in # Internet protocols for information interchange (mail, news, etc.). # # Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications # must understand both names and treat them as equivalent. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM host="$1" os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'` echo "# This file contains a table of character encoding aliases," echo "# suitable for operating system '${os}'." echo "# It was automatically generated from config.charset." # List of references, updated during installation: echo "# Packages using this file: " case "$os" in linux* | *-gnu*) # With glibc-2.1 or newer, we don't need any canonicalization, # because glibc has iconv and both glibc and libiconv support all # GNU canonical names directly. Therefore, the Makefile does not # need to install the alias file at all. # The following applies only to glibc-2.0.x and older libcs. echo "ISO_646.IRV:1983 ASCII" ;; aix*) echo "ISO8859-1 ISO-8859-1" echo "ISO8859-2 ISO-8859-2" echo "ISO8859-5 ISO-8859-5" echo "ISO8859-6 ISO-8859-6" echo "ISO8859-7 ISO-8859-7" echo "ISO8859-8 ISO-8859-8" echo "ISO8859-9 ISO-8859-9" echo "ISO8859-15 ISO-8859-15" echo "IBM-850 CP850" echo "IBM-856 CP856" echo "IBM-921 ISO-8859-13" echo "IBM-922 CP922" echo "IBM-932 CP932" echo "IBM-943 CP943" echo "IBM-1046 CP1046" echo "IBM-1124 CP1124" echo "IBM-1129 CP1129" echo "IBM-1252 CP1252" echo "IBM-eucCN GB2312" echo "IBM-eucJP EUC-JP" echo "IBM-eucKR EUC-KR" echo "IBM-eucTW EUC-TW" echo "big5 BIG5" echo "GBK GBK" echo "TIS-620 TIS-620" echo "UTF-8 UTF-8" ;; hpux*) echo "iso88591 ISO-8859-1" echo "iso88592 ISO-8859-2" echo "iso88595 ISO-8859-5" echo "iso88596 ISO-8859-6" echo "iso88597 ISO-8859-7" echo "iso88598 ISO-8859-8" echo "iso88599 ISO-8859-9" echo "iso885915 ISO-8859-15" echo "roman8 HP-ROMAN8" echo "arabic8 HP-ARABIC8" echo "greek8 HP-GREEK8" echo "hebrew8 HP-HEBREW8" echo "turkish8 HP-TURKISH8" echo "kana8 HP-KANA8" echo "tis620 TIS-620" echo "big5 BIG5" echo "eucJP EUC-JP" echo "eucKR EUC-KR" echo "eucTW EUC-TW" echo "hp15CN GB2312" #echo "ccdc ?" # what is this? echo "SJIS SHIFT_JIS" echo "utf8 UTF-8" ;; irix*) echo "ISO8859-1 ISO-8859-1" echo "ISO8859-2 ISO-8859-2" echo "ISO8859-5 ISO-8859-5" echo "ISO8859-7 ISO-8859-7" echo "ISO8859-9 ISO-8859-9" echo "eucCN GB2312" echo "eucJP EUC-JP" echo "eucKR EUC-KR" echo "eucTW EUC-TW" ;; osf*) echo "ISO8859-1 ISO-8859-1" echo "ISO8859-2 ISO-8859-2" echo "ISO8859-4 ISO-8859-4" echo "ISO8859-5 ISO-8859-5" echo "ISO8859-7 ISO-8859-7" echo "ISO8859-8 ISO-8859-8" echo "ISO8859-9 ISO-8859-9" echo "ISO8859-15 ISO-8859-15" echo "cp850 CP850" echo "big5 BIG5" echo "dechanyu DEC-HANYU" echo "dechanzi GB2312" echo "deckanji DEC-KANJI" echo "deckorean EUC-KR" echo "eucJP EUC-JP" echo "eucKR EUC-KR" echo "eucTW EUC-TW" echo "GBK GBK" echo "KSC5601 CP949" echo "sdeckanji EUC-JP" echo "SJIS SHIFT_JIS" echo "TACTIS TIS-620" echo "UTF-8 UTF-8" ;; solaris*) echo "646 ASCII" echo "ISO8859-1 ISO-8859-1" echo "ISO8859-2 ISO-8859-2" echo "ISO8859-4 ISO-8859-4" echo "ISO8859-5 ISO-8859-5" echo "ISO8859-6 ISO-8859-6" echo "ISO8859-7 ISO-8859-7" echo "ISO8859-8 ISO-8859-8" echo "ISO8859-9 ISO-8859-9" echo "ISO8859-15 ISO-8859-15" echo "koi8-r KOI8-R" echo "BIG5 BIG5" echo "gb2312 GB2312" echo "cns11643 EUC-TW" echo "5601 EUC-KR" echo "eucJP EUC-JP" echo "PCK SHIFT_JIS" echo "TIS620.2533 TIS-620" #echo "sun_eu_greek ?" # what is this? echo "UTF-8 UTF-8" ;; freebsd* | os2*) # FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore # localcharset.c falls back to using the full locale name # from the environment variables. # Likewise for OS/2. OS/2 has XFree86 just like FreeBSD. Just # reuse FreeBSD's locale data for OS/2. echo "C ASCII" echo "US-ASCII ASCII" for l in la_LN lt_LN; do echo "$l.ASCII ASCII" done for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \ fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \ lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do echo "$l.ISO_8859-1 ISO-8859-1" echo "$l.DIS_8859-15 ISO-8859-15" done for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do echo "$l.ISO_8859-2 ISO-8859-2" done for l in la_LN lt_LT; do echo "$l.ISO_8859-4 ISO-8859-4" done for l in ru_RU ru_SU; do echo "$l.KOI8-R KOI8-R" echo "$l.ISO_8859-5 ISO-8859-5" echo "$l.CP866 CP866" done echo "uk_UA.KOI8-U KOI8-U" echo "zh_TW.BIG5 BIG5" echo "zh_TW.Big5 BIG5" echo "zh_CN.EUC GB2312" echo "ja_JP.EUC EUC-JP" echo "ja_JP.SJIS SHIFT_JIS" echo "ja_JP.Shift_JIS SHIFT_JIS" echo "ko_KR.EUC EUC-KR" ;; beos*) # BeOS has a single locale, and it has UTF-8 encoding. echo "* UTF-8" ;; msdosdjgpp*) # DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore # localcharset.c falls back to using the full locale name # from the environment variables. echo "#" echo "# The encodings given here may not all be correct." echo "# If you find that the encoding given for your language and" echo "# country is not the one your DOS machine actually uses, just" echo "# correct it in this file, and send a mail to" echo "# Juan Manuel Guerrero " echo "# and Bruno Haible ." echo "#" echo "C ASCII" # ISO-8859-1 languages echo "ca CP850" echo "ca_ES CP850" echo "da CP865" # not CP850 ?? echo "da_DK CP865" # not CP850 ?? echo "de CP850" echo "de_AT CP850" echo "de_CH CP850" echo "de_DE CP850" echo "en CP850" echo "en_AU CP850" # not CP437 ?? echo "en_CA CP850" echo "en_GB CP850" echo "en_NZ CP437" echo "en_US CP437" echo "en_ZA CP850" # not CP437 ?? echo "es CP850" echo "es_AR CP850" echo "es_BO CP850" echo "es_CL CP850" echo "es_CO CP850" echo "es_CR CP850" echo "es_CU CP850" echo "es_DO CP850" echo "es_EC CP850" echo "es_ES CP850" echo "es_GT CP850" echo "es_HN CP850" echo "es_MX CP850" echo "es_NI CP850" echo "es_PA CP850" echo "es_PY CP850" echo "es_PE CP850" echo "es_SV CP850" echo "es_UY CP850" echo "es_VE CP850" echo "et CP850" echo "et_EE CP850" echo "eu CP850" echo "eu_ES CP850" echo "fi CP850" echo "fi_FI CP850" echo "fr CP850" echo "fr_BE CP850" echo "fr_CA CP850" echo "fr_CH CP850" echo "fr_FR CP850" echo "ga CP850" echo "ga_IE CP850" echo "gd CP850" echo "gd_GB CP850" echo "gl CP850" echo "gl_ES CP850" echo "id CP850" # not CP437 ?? echo "id_ID CP850" # not CP437 ?? echo "is CP861" # not CP850 ?? echo "is_IS CP861" # not CP850 ?? echo "it CP850" echo "it_CH CP850" echo "it_IT CP850" echo "lt CP775" echo "lt_LT CP775" echo "lv CP775" echo "lv_LV CP775" echo "nb CP865" # not CP850 ?? echo "nb_NO CP865" # not CP850 ?? echo "nl CP850" echo "nl_BE CP850" echo "nl_NL CP850" echo "nn CP865" # not CP850 ?? echo "nn_NO CP865" # not CP850 ?? echo "no CP865" # not CP850 ?? echo "no_NO CP865" # not CP850 ?? echo "pt CP850" echo "pt_BR CP850" echo "pt_PT CP850" echo "sv CP850" echo "sv_SE CP850" # ISO-8859-2 languages echo "cs CP852" echo "cs_CZ CP852" echo "hr CP852" echo "hr_HR CP852" echo "hu CP852" echo "hu_HU CP852" echo "pl CP852" echo "pl_PL CP852" echo "ro CP852" echo "ro_RO CP852" echo "sk CP852" echo "sk_SK CP852" echo "sl CP852" echo "sl_SI CP852" echo "sq CP852" echo "sq_AL CP852" echo "sr CP852" # CP852 or CP866 or CP855 ?? echo "sr_YU CP852" # CP852 or CP866 or CP855 ?? # ISO-8859-3 languages echo "mt CP850" echo "mt_MT CP850" # ISO-8859-5 languages echo "be CP866" echo "be_BE CP866" echo "bg CP866" # not CP855 ?? echo "bg_BG CP866" # not CP855 ?? echo "mk CP866" # not CP855 ?? echo "mk_MK CP866" # not CP855 ?? echo "ru KOI8-R" # not CP866 ?? echo "ru_RU KOI8-R" # not CP866 ?? # ISO-8859-6 languages echo "ar CP864" echo "ar_AE CP864" echo "ar_DZ CP864" echo "ar_EG CP864" echo "ar_IQ CP864" echo "ar_IR CP864" echo "ar_JO CP864" echo "ar_KW CP864" echo "ar_MA CP864" echo "ar_OM CP864" echo "ar_QA CP864" echo "ar_SA CP864" echo "ar_SY CP864" # ISO-8859-7 languages echo "el CP869" echo "el_GR CP869" # ISO-8859-8 languages echo "he CP862" echo "he_IL CP862" # ISO-8859-9 languages echo "tr CP857" echo "tr_TR CP857" # Japanese echo "ja CP932" echo "ja_JP CP932" # Chinese echo "zh_CN GBK" echo "zh_TW CP950" # not CP938 ?? # Korean echo "kr CP949" # not CP934 ?? echo "kr_KR CP949" # not CP934 ?? # Thai echo "th CP874" echo "th_TH CP874" # Other echo "eo CP850" echo "eo_EO CP850" ;; esac kbuild-3686/src/oldsed/intl/explodename.c0000664000175000017500000001105415053010105020357 0ustar locutuslocutus/* Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. Contributed by Ulrich Drepper , 1995. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "loadinfo.h" /* On some strange systems still no definition of NULL is found. Sigh! */ #ifndef NULL # if defined __STDC__ && __STDC__ # define NULL ((void *) 0) # else # define NULL 0 # endif #endif /* @@ end of prolog @@ */ char * _nl_find_language (name) const char *name; { while (name[0] != '\0' && name[0] != '_' && name[0] != '@' && name[0] != '+' && name[0] != ',') ++name; return (char *) name; } int _nl_explode_name (name, language, modifier, territory, codeset, normalized_codeset, special, sponsor, revision) char *name; const char **language; const char **modifier; const char **territory; const char **codeset; const char **normalized_codeset; const char **special; const char **sponsor; const char **revision; { enum { undecided, xpg, cen } syntax; char *cp; int mask; *modifier = NULL; *territory = NULL; *codeset = NULL; *normalized_codeset = NULL; *special = NULL; *sponsor = NULL; *revision = NULL; /* Now we determine the single parts of the locale name. First look for the language. Termination symbols are `_' and `@' if we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ mask = 0; syntax = undecided; *language = cp = name; cp = _nl_find_language (*language); if (*language == cp) /* This does not make sense: language has to be specified. Use this entry as it is without exploding. Perhaps it is an alias. */ cp = strchr (*language, '\0'); else if (cp[0] == '_') { /* Next is the territory. */ cp[0] = '\0'; *territory = ++cp; while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@' && cp[0] != '+' && cp[0] != ',' && cp[0] != '_') ++cp; mask |= TERRITORY; if (cp[0] == '.') { /* Next is the codeset. */ syntax = xpg; cp[0] = '\0'; *codeset = ++cp; while (cp[0] != '\0' && cp[0] != '@') ++cp; mask |= XPG_CODESET; if (*codeset != cp && (*codeset)[0] != '\0') { *normalized_codeset = _nl_normalize_codeset (*codeset, cp - *codeset); if (strcmp (*codeset, *normalized_codeset) == 0) free ((char *) *normalized_codeset); else mask |= XPG_NORM_CODESET; } } } if (cp[0] == '@' || (syntax != xpg && cp[0] == '+')) { /* Next is the modifier. */ syntax = cp[0] == '@' ? xpg : cen; cp[0] = '\0'; *modifier = ++cp; while (syntax == cen && cp[0] != '\0' && cp[0] != '+' && cp[0] != ',' && cp[0] != '_') ++cp; mask |= XPG_MODIFIER | CEN_AUDIENCE; } if (syntax != xpg && (cp[0] == '+' || cp[0] == ',' || cp[0] == '_')) { syntax = cen; if (cp[0] == '+') { /* Next is special application (CEN syntax). */ cp[0] = '\0'; *special = ++cp; while (cp[0] != '\0' && cp[0] != ',' && cp[0] != '_') ++cp; mask |= CEN_SPECIAL; } if (cp[0] == ',') { /* Next is sponsor (CEN syntax). */ cp[0] = '\0'; *sponsor = ++cp; while (cp[0] != '\0' && cp[0] != '_') ++cp; mask |= CEN_SPONSOR; } if (cp[0] == '_') { /* Next is revision (CEN syntax). */ cp[0] = '\0'; *revision = ++cp; mask |= CEN_REVISION; } } /* For CEN syntax values it might be important to have the separator character in the file name, not for XPG syntax. */ if (syntax == xpg) { if (*territory != NULL && (*territory)[0] == '\0') mask &= ~TERRITORY; if (*codeset != NULL && (*codeset)[0] == '\0') mask &= ~XPG_CODESET; if (*modifier != NULL && (*modifier)[0] == '\0') mask &= ~XPG_MODIFIER; } return mask; } kbuild-3686/src/oldsed/intl/ngettext.c0000664000175000017500000000372315053010106017725 0ustar locutuslocutus/* Implementation of ngettext(3) function. Copyright (C) 1995, 1997, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifdef _LIBC # define __need_NULL # include #else # include /* Just for NULL. */ #endif #include "gettextP.h" #ifdef _LIBC # include #else # include "libgnuintl.h" #endif #include /* @@ end of prolog @@ */ /* Names for the libintl functions are a problem. They must not clash with existing names and they should follow ANSI C. But this source code is also used in GNU C Library where the names have a __ prefix. So we have to make a difference here. */ #ifdef _LIBC # define NGETTEXT __ngettext # define DCNGETTEXT __dcngettext #else # define NGETTEXT ngettext__ # define DCNGETTEXT dcngettext__ #endif /* Look up MSGID in the current default message catalog for the current LC_MESSAGES locale. If not found, returns MSGID itself (the default text). */ char * NGETTEXT (msgid1, msgid2, n) const char *msgid1; const char *msgid2; unsigned long int n; { return DCNGETTEXT (NULL, msgid1, msgid2, n, LC_MESSAGES); } #ifdef _LIBC /* Alias for function name in GNU C Library. */ weak_alias (__ngettext, ngettext); #endif kbuild-3686/src/oldsed/intl/locale.alias0000664000175000017500000000514515053010105020170 0ustar locutuslocutus# Locale name alias data base. # Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU Library General Public License as published # by the Free Software Foundation; either version 2, 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # The format of this file is the same as for the corresponding file of # the X Window System, which normally can be found in # /usr/lib/X11/locale/locale.alias # A single line contains two fields: an alias and a substitution value. # All entries are case independent. # Note: This file is far from being complete. If you have a value for # your own site which you think might be useful for others too, share # it with the rest of us. Send it using the `glibcbug' script to # bugs@gnu.org. # Packages using this file: bokmal no_NO.ISO-8859-1 bokmål no_NO.ISO-8859-1 catalan ca_ES.ISO-8859-1 croatian hr_HR.ISO-8859-2 czech cs_CZ.ISO-8859-2 danish da_DK.ISO-8859-1 dansk da_DK.ISO-8859-1 deutsch de_DE.ISO-8859-1 dutch nl_NL.ISO-8859-1 eesti et_EE.ISO-8859-1 estonian et_EE.ISO-8859-1 finnish fi_FI.ISO-8859-1 français fr_FR.ISO-8859-1 french fr_FR.ISO-8859-1 galego gl_ES.ISO-8859-1 galician gl_ES.ISO-8859-1 german de_DE.ISO-8859-1 greek el_GR.ISO-8859-7 hebrew he_IL.ISO-8859-8 hrvatski hr_HR.ISO-8859-2 hungarian hu_HU.ISO-8859-2 icelandic is_IS.ISO-8859-1 italian it_IT.ISO-8859-1 japanese ja_JP.eucJP japanese.euc ja_JP.eucJP ja_JP ja_JP.eucJP ja_JP.ujis ja_JP.eucJP japanese.sjis ja_JP.SJIS korean ko_KR.eucKR korean.euc ko_KR.eucKR ko_KR ko_KR.eucKR lithuanian lt_LT.ISO-8859-13 nb_NO no_NO.ISO-8859-1 nb_NO.ISO-8859-1 no_NO.ISO-8859-1 norwegian no_NO.ISO-8859-1 nynorsk nn_NO.ISO-8859-1 polish pl_PL.ISO-8859-2 portuguese pt_PT.ISO-8859-1 romanian ro_RO.ISO-8859-2 russian ru_RU.ISO-8859-5 slovak sk_SK.ISO-8859-2 slovene sl_SI.ISO-8859-2 slovenian sl_SI.ISO-8859-2 spanish es_ES.ISO-8859-1 swedish sv_SE.ISO-8859-1 thai th_TH.TIS-620 turkish tr_TR.ISO-8859-9 kbuild-3686/src/oldsed/intl/dngettext.c0000664000175000017500000000361115053010105020064 0ustar locutuslocutus/* Implementation of the dngettext(3) function. Copyright (C) 1995-1997, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "gettextP.h" #ifdef _LIBC # include #else # include "libgnuintl.h" #endif /* @@ end of prolog @@ */ /* Names for the libintl functions are a problem. They must not clash with existing names and they should follow ANSI C. But this source code is also used in GNU C Library where the names have a __ prefix. So we have to make a difference here. */ #ifdef _LIBC # define DNGETTEXT __dngettext # define DCNGETTEXT __dcngettext #else # define DNGETTEXT dngettext__ # define DCNGETTEXT dcngettext__ #endif /* Look up MSGID in the DOMAINNAME message catalog of the current LC_MESSAGES locale and skip message according to the plural form. */ char * DNGETTEXT (domainname, msgid1, msgid2, n) const char *domainname; const char *msgid1; const char *msgid2; unsigned long int n; { return DCNGETTEXT (domainname, msgid1, msgid2, n, LC_MESSAGES); } #ifdef _LIBC /* Alias for function name in GNU C Library. */ weak_alias (__dngettext, dngettext); #endif kbuild-3686/src/oldsed/intl/intl-compat.c0000664000175000017500000001123515053010105020306 0ustar locutuslocutus/* intl-compat.c - Stub functions to call gettext functions from GNU gettext Library. Copyright (C) 1995, 2000, 2001 Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "libgnuintl.h" #include "gettextP.h" /* @@ end of prolog @@ */ /* This file redirects the gettext functions (without prefix or suffix) to those defined in the included GNU gettext library (with "__" suffix). It is compiled into libintl when the included GNU gettext library is configured --with-included-gettext. This redirection works also in the case that the system C library or the system libintl library contain gettext/textdomain/... functions. If it didn't, we would need to add preprocessor level redirections to libgnuintl.h of the following form: # define gettext gettext__ # define dgettext dgettext__ # define dcgettext dcgettext__ # define ngettext ngettext__ # define dngettext dngettext__ # define dcngettext dcngettext__ # define textdomain textdomain__ # define bindtextdomain bindtextdomain__ # define bind_textdomain_codeset bind_textdomain_codeset__ How does this redirection work? There are two cases. A. When libintl.a is linked into an executable, it works because functions defined in the executable always override functions in the shared libraries. B. When libintl.so is used, it works because 1. those systems defining gettext/textdomain/... in the C library (namely, Solaris 2.4 and newer, and GNU libc 2.0 and newer) are ELF systems and define these symbols as weak, thus explicitly letting other shared libraries override it. 2. those systems defining gettext/textdomain/... in a standalone libintl.so library (namely, Solaris 2.3 and newer) have this shared library in /usr/lib, and the linker will search /usr/lib *after* the directory where the GNU gettext library is installed. A third case, namely when libintl.a is linked into a shared library whose name is not libintl.so, is not supported. In this case, on Solaris, when -lintl precedes the linker option for the shared library containing GNU gettext, the system's gettext would indeed override the GNU gettext. Anyone doing this kind of stuff must be clever enough to 1. compile libintl.a with -fPIC, 2. remove -lintl from his linker command line. */ #undef gettext #undef dgettext #undef dcgettext #undef ngettext #undef dngettext #undef dcngettext #undef textdomain #undef bindtextdomain #undef bind_textdomain_codeset char * gettext (msgid) const char *msgid; { return gettext__ (msgid); } char * dgettext (domainname, msgid) const char *domainname; const char *msgid; { return dgettext__ (domainname, msgid); } char * dcgettext (domainname, msgid, category) const char *domainname; const char *msgid; int category; { return dcgettext__ (domainname, msgid, category); } char * ngettext (msgid1, msgid2, n) const char *msgid1; const char *msgid2; unsigned long int n; { return ngettext__ (msgid1, msgid2, n); } char * dngettext (domainname, msgid1, msgid2, n) const char *domainname; const char *msgid1; const char *msgid2; unsigned long int n; { return dngettext__ (domainname, msgid1, msgid2, n); } char * dcngettext (domainname, msgid1, msgid2, n, category) const char *domainname; const char *msgid1; const char *msgid2; unsigned long int n; int category; { return dcngettext__ (domainname, msgid1, msgid2, n, category); } char * textdomain (domainname) const char *domainname; { return textdomain__ (domainname); } char * bindtextdomain (domainname, dirname) const char *domainname; const char *dirname; { return bindtextdomain__ (domainname, dirname); } char * bind_textdomain_codeset (domainname, codeset) const char *domainname; const char *codeset; { return bind_textdomain_codeset__ (domainname, codeset); } kbuild-3686/src/oldsed/intl/eval-plural.h0000664000175000017500000000527215053010105020314 0ustar locutuslocutus/* Plural expression evaluation. Copyright (C) 2000, 2001 Free Software Foundation, Inc. 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, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef STATIC #define STATIC static #endif /* Evaluate the plural expression and return an index value. */ STATIC unsigned long int plural_eval PARAMS ((struct expression *pexp, unsigned long int n)) internal_function; STATIC unsigned long int internal_function plural_eval (pexp, n) struct expression *pexp; unsigned long int n; { switch (pexp->nargs) { case 0: switch (pexp->operation) { case var: return n; case num: return pexp->val.num; default: break; } /* NOTREACHED */ break; case 1: { /* pexp->operation must be lnot. */ unsigned long int arg = plural_eval (pexp->val.args[0], n); return ! arg; } case 2: { unsigned long int leftarg = plural_eval (pexp->val.args[0], n); if (pexp->operation == lor) return leftarg || plural_eval (pexp->val.args[1], n); else if (pexp->operation == land) return leftarg && plural_eval (pexp->val.args[1], n); else { unsigned long int rightarg = plural_eval (pexp->val.args[1], n); switch (pexp->operation) { case mult: return leftarg * rightarg; case divide: return leftarg / rightarg; case module: return leftarg % rightarg; case plus: return leftarg + rightarg; case minus: return leftarg - rightarg; case less_than: return leftarg < rightarg; case greater_than: return leftarg > rightarg; case less_or_equal: return leftarg <= rightarg; case greater_or_equal: return leftarg >= rightarg; case equal: return leftarg == rightarg; case not_equal: return leftarg != rightarg; default: break; } } /* NOTREACHED */ break; } case 3: { /* pexp->operation must be qmop. */ unsigned long int boolarg = plural_eval (pexp->val.args[0], n); return plural_eval (pexp->val.args[boolarg ? 1 : 2], n); } } /* NOTREACHED */ return 0; } kbuild-3686/src/oldsed/configure.ac0000664000175000017500000001112515053010105017231 0ustar locutuslocutusdnl Process this file with -*- autoconf -*- to produce a configure script. AC_INIT(sed, 4.1.5, bonzini@gnu.org, sed) AC_CONFIG_AUX_DIR(config) AC_CONFIG_SRCDIR([sed/sed.c]) AM_CONFIG_HEADER(config.h:config_h.in) AC_PREREQ(2.59) AM_INIT_AUTOMAKE SED_FEATURE_VERSION=4.1 AC_DEFINE_UNQUOTED(SED_FEATURE_VERSION, "$SED_FEATURE_VERSION", [Define to the version of GNU sed whose features are supported by this sed.]) AC_SUBST(SED_FEATURE_VERSION) AC_PROG_CC AC_PROG_RANLIB AC_GNU_SOURCE AC_AIX AC_MINIX AC_ISC_POSIX AC_SYS_LARGEFILE AC_SYS_LONG_FILE_NAMES AC_CACHE_CHECK([whether -lcP is needed], [sed_cv_libcp_needed], [ AC_TRY_RUN([ #include #include int main() { FILE *fp; int result; errno = 0; fp = fopen ("conftest.c", "r"); if (!fp) return 0; /* error, assume not needed */ result = fflush (fp) == EOF && errno == 0; fclose (fp); return result; }], [sed_cv_libcp_needed=no], [sed_cv_libcp_needed=yes], [sed_cv_libcp_needed="assuming no"]) ]) if test "$sed_cv_libcp_needed" = yes; then LIBS="-lcP $LIBS" fi AC_HEADER_DIRENT AC_CHECK_HEADERS(io.h limits.h locale.h stdarg.h alloca.h stddef.h errno.h \ wchar.h wctype.h sys/file.h mcheck.h, [], [], [AC_INCLUDES_DEFAULT]) AC_C_CONST AC_TYPE_SIZE_T AC_CHECK_TYPE(ssize_t, int) AC_HEADER_STDBOOL if test "$ac_cv_type__Bool" = no; then HAVE__BOOL=0 else HAVE__BOOL=1 fi AC_SUBST(HAVE__BOOL) if test "$ac_cv_header_stdbool_h" = no; then AC_CONFIG_FILES(lib/stdbool.h:lib/stdbool_.h) fi AC_FUNC_ALLOCA AC_FUNC_VPRINTF AM_FUNC_GETLINE AC_FUNC_OBSTACK AC_FUNC_MBRTOWC AC_TYPE_MBSTATE_T gl_FUNC_STRVERSCMP AC_REPLACE_FUNCS(memchr memcmp memmove strerror mkstemp) AC_CHECK_FUNCS(isatty bcopy bzero isascii memcpy memset strchr strtoul popen \ pathconf isblank fchown fchmod setlocale wcrtomb wcscoll btowc) AC_ARG_ENABLE(i18n, [ --disable-i18n disable internationalization (default=yes)], , enable_i18n=yes) if test "x$enable_i18n" = xno; then ac_cv_func_wcscoll=false fi AC_ARG_WITH(included-regex, [ --with-included-regex use included regex matcher (default=yes)], , with_included_regex=yes) if test "x$with_included_regex" = xno; then AC_CHECK_HEADERS(regex.h) AC_CHECK_LIB(regex, re_search) AC_CHECK_FUNC(re_search) if test $ac_cv_header_regex_h = no || test $ac_cv_func_re_search = no; then AC_MSG_WARN([GNU regex not found, falling back to the included version]) with_included_regex=yes fi fi AC_ARG_ENABLE(regex-tests, [ --enable-regex-tests enable regex matcher regression tests (default=yes)], [if test "x$with_included_regex" = xno; then enable_regex_tests=no fi], enable_regex_tests=$with_included_regex) AM_CONDITIONAL(TEST_REGEX, test "x$enable_regex_tests" != xno) if test "x$with_included_regex" != xno; then AC_CONFIG_LINKS(lib/regex.h:lib/regex_.h) AC_LIBOBJ(regex) fi if test "x$enable_regex_tests" = xyes; then AC_DEFINE_UNQUOTED(_REGEX_RE_COMP, 1, [Include BSD functions in regex, used by the testsuite]) fi AC_ARG_ENABLE(html, [ --enable-html build HTML manual (default=no)], , enable_html=no) AM_CONDITIONAL(BUILD_HTML, test "x$enable_html" != xno) : ${TEXI2HTML=texi2html -monolithic} AC_SUBST(TEXI2HTML) AC_MSG_CHECKING(how to build HTML documentation) if eval $am_missing_run makeinfo --help 2>&1 | grep .-html > /dev/null; then AC_MSG_RESULT(with makeinfo) enable_html=makeinfo else if $TEXI2HTML --help 2>&1 | grep monolithic > /dev/null; then AC_MSG_RESULT(with texi2html) enable_html=texi2html else AC_MSG_RESULT(not built) if test "x$enable_html" != xno; then AC_MSG_ERROR(cannot build HTML documentation, install makeinfo 4.0 or texi2html) fi enable_html=no fi fi AM_CONDITIONAL(MAKEINFO_HTML, test "x$enable_html" = xmakeinfo) AM_CONDITIONAL(TEXI2HTML_HTML, test "x$enable_html" = xtexi2html) AC_DEFUN([AM_MKINSTALLDIRS], [MKINSTALLDIRS="$mkdir_p" AC_SUBST(MKINSTALLDIRS)]) AM_GNU_GETTEXT_VERSION(0.14) AM_GNU_GETTEXT(no-libtool, need-ngettext, ../intl) dnl bird: made the 'expr/a\' stuff work on BSD. a\ only works when scripting there. AC_CONFIG_COMMANDS([gettext-fix], [ echo '/^mkinstalldirs *=/a\' > tmp.sed echo "install_sh=$install_sh" >> tmp.sed echo 's/^mkinstalldirs *=.*/mkinstalldirs=$(MKINSTALLDIRS)/' >> tmp.sed sed -f tmp.sed intl/Makefile > intl/Makefile.tmp mv intl/Makefile.tmp intl/Makefile sed -f tmp.sed po/Makefile > po/Makefile.tmp mv po/Makefile.tmp po/Makefile rm -f tmp.sed], [ install_sh="$install_sh"]) AC_CONFIG_FILES([bootstrap.sh], chmod +x bootstrap.sh) AC_CONFIG_FILES([Makefile doc/Makefile \ lib/Makefile sed/Makefile testsuite/Makefile \ po/Makefile.in intl/Makefile]) AC_OUTPUT kbuild-3686/src/oldsed/config.h.win0000664000175000017500000002743215053010104017164 0ustar locutuslocutus/* config.h.win Maintaind by hand. */ /* config_h.in. Generated from configure.ac by autoheader. */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if translation of program messages to the user's native language is requested. */ /* #undef ENABLE_NLS */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ /*#define HAVE_ALLOCA_H 1*/ /* Define to 1 if you have the header file. */ /*#define HAVE_ARGZ_H 1*/ /* Define to 1 if you have the `bcopy' function. */ /*#define HAVE_BCOPY 1*/ /* Define to 1 if you have the `btowc' function. */ /*#define HAVE_BTOWC 1 - bird don't drag in msvcp71.dll */ /* Define to 1 if you have the `bzero' function. */ /*#define HAVE_BZERO 1*/ /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* #undef HAVE_DCGETTEXT */ /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* unused */ /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ /* #undef HAVE_DOPRNT */ /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H 1 /* Define to 1 if you have the `fchmod' function. */ /*#define HAVE_FCHMOD 1*/ /* Define to 1 if you have the `fchown' function. */ /*#define HAVE_FCHOWN 1*/ /* Define to 1 if you have the `feof_unlocked' function. */ /*#define HAVE_FEOF_UNLOCKED 1*/ /* Define to 1 if you have the `fgets_unlocked' function. */ /*#define HAVE_FGETS_UNLOCKED 1*/ /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getc_unlocked' function. */ /*#define HAVE_GETC_UNLOCKED 1*/ /* Define to 1 if you have the `getegid' function. */ /*#define HAVE_GETEGID 1*/ /* Define to 1 if you have the `geteuid' function. */ /*#define HAVE_GETEUID 1*/ /* Define to 1 if you have the `getgid' function. */ /*#define HAVE_GETGID 1*/ /* Define to 1 if you have the `getpagesize' function. */ #define HAVE_GETPAGESIZE 1 /* unused */ /* Define if the GNU gettext() function is already present or preinstalled. */ /* #undef HAVE_GETTEXT */ /* Define to 1 if you have the `getuid' function. */ #define HAVE_GETUID 1 /* unused (intl) */ /* Define if you have the iconv() function. */ #define HAVE_ICONV 1 /* unused (intl?) */ /* Define to 1 if you have the header file. */ /*#define HAVE_INTTYPES_H 1*/ /* Define to 1 if you have the header file. */ /* #undef HAVE_IO_H */ /* Define to 1 if you have the `isascii' function. */ /*#define HAVE_ISASCII 1*/ /* don't think we've got this... */ /* Define to 1 if you have the `isatty' function. */ #define HAVE_ISATTY 1 /* Define to 1 if you have the `isblank' function. */ /*#define HAVE_ISBLANK 1*/ /* don't think we've got this... */ /* Define if you have and nl_langinfo(CODESET). */ /*#define HAVE_LANGINFO_CODESET 1*/ /* Define if your file defines LC_MESSAGES. */ #define HAVE_LC_MESSAGES 1 /* ??? */ /* Define to 1 if you have the `regex' library (-lregex). */ /* #undef HAVE_LIBREGEX */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you support file names longer than 14 characters. */ #define HAVE_LONG_FILE_NAMES 1 /* Define to 1 if you have the header file. */ #define HAVE_MALLOC_H 1 /* Define to 1 if mbrtowc and mbstate_t are properly declared. */ /*#define HAVE_MBRTOWC 1 - bird don't drag in msvcp71.dll */ /* Define to 1 if declares mbstate_t. */ #define HAVE_MBSTATE_T 1 /* Define to 1 if you have the header file. */ /*#define HAVE_MCHECK_H 1*/ /* Define to 1 if you have the `memchr' function. */ #define HAVE_MEMCHR 1 /* Define to 1 if you have the `memcmp' function. */ #define HAVE_MEMCMP 1 /* Define to 1 if you have the `memcpy' function. */ #define HAVE_MEMCPY 1 /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mempcpy' function. */ /*#define HAVE_MEMPCPY 1*/ /* Define to 1 if you have the `memset' function. */ #define HAVE_MEMSET 1 /* Define to 1 if you have the `mkstemp' function. */ /*#define HAVE_MKSTEMP 1*/ /* Define to 1 if you have a working `mmap' system call. */ /*#define HAVE_MMAP 1*/ /* Define to 1 if you have the `munmap' function. */ /*#define HAVE_MUNMAP 1*/ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ /*#define HAVE_NL_TYPES_H 1*/ /* Define to 1 if libc includes obstacks. */ /*#define HAVE_OBSTACK 1*/ /* Define to 1 if you have the `pathconf' function. */ #define HAVE_PATHCONF 1 /* ?? */ /* Define to 1 if you have the `popen' function. */ /*#define HAVE_POPEN 1*/ /** @todo popen */ /* Define to 1 if you have the `putenv' function. */ #define HAVE_PUTENV 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_REGEX_H */ /* Define to 1 if you have the `setenv' function. */ /*#define HAVE_SETENV 1*/ /* Define to 1 if you have the `setlocale' function. */ #define HAVE_SETLOCALE 1 /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if stdbool.h conforms to C99. */ /*#define HAVE_STDBOOL_H 1*/ /* Define to 1 if you have the header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `stpcpy' function. */ /*#define HAVE_STPCPY 1*/ /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 #define strcasecmp(__a,__b) stricmp((__a),(__b)) /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ /*#define HAVE_STRINGS_H 1*/ /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strtoul' function. */ #define HAVE_STRTOUL 1 /* Define to 1 if you have the `strverscmp' function. */ /*#define HAVE_STRVERSCMP 1*/ /* 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. */ /*#define HAVE_SYS_FILE_H 1*/ /* 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. */ /*#define HAVE_SYS_PARAM_H 1*/ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the `tsearch' function. */ #define HAVE_TSEARCH 1 /* ??? */ /* Define to 1 if you have the header file. */ /*#define HAVE_UNISTD_H 1*/ /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_WCHAR_H 1 /* Define to 1 if you have the `wcrtomb' function. */ /*#define HAVE_WCRTOMB 1 - bird don't drag in msvcp71.dll */ /* Define to 1 if you have the `wcscoll' function. */ /*#define HAVE_WCSCOLL 1 - bird don't drag in msvcp71.dll */ /* Define to 1 if you have the header file. */ #define HAVE_WCTYPE_H 1 /* Define to 1 if the system has the type `_Bool'. */ /*#define HAVE__BOOL 1*/ /* Define to 1 if you have the `__argz_count' function. */ /*#define HAVE___ARGZ_COUNT 1*/ /* Define to 1 if you have the `__argz_next' function. */ /*#define HAVE___ARGZ_NEXT 1*/ /* Define to 1 if you have the `__argz_stringify' function. */ /*#define HAVE___ARGZ_STRINGIFY 1*/ /* Define as const if the declaration of iconv() needs const. */ /*#define ICONV_CONST */ /* Name of package */ #define PACKAGE "sed" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bonzini@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "sed" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "sed 4.1.5" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "sed" /* Define to the version of this package. */ #define PACKAGE_VERSION "4.1.5" /* Define to the version of GNU sed whose features are supported by this sed. */ #define SED_FEATURE_VERSION "4.1" /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ #define VERSION "4.1.5" /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* # undef _ALL_SOURCE */ #endif /* Number of bits in a file offset, on hosts where this is settable. */ #define _FILE_OFFSET_BITS 64 /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Include BSD functions in regex, used by the testsuite */ #define _REGEX_RE_COMP 1 /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to a type if does not define. */ /* #undef mbstate_t */ /* Define to `long' if does not define. */ /* #undef off_t */ /* Define to `unsigned' if does not define. */ /* #undef size_t */ /* Define to `int' if does not define. */ #define ssize_t intptr_t /* does 14.0 have this? */ /* Additional defines and includes to make it work with the microsoft compiler */ #ifndef __config_h_included_already #define __config_h_included_already #define HAVE_FCNTL_H 1 /* no idea why this isn't in config.h.in... */ #define VOID void #define inline _inline #include /* isatty ++ */ #include #define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) #define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) #define S_ISLNK(m) 0 #include /* memory.h != string.h it seem even if the code assumes so. */ /* stdbool.h replacement */ typedef char bool; #define false 0 #define true 1 #include /* mbsinit isn't defined until 2005 / v8.0. */ #if _MSC_VER < 1400 int _inline mbsinit(const mbstate_t *_p) { return (_p) == (const mbstate_t *)0 || *(_p) == 0; } #endif #if _MSC_VER >= 1400 /* crtdefs.h contains a typedef int errcode which collides with regcomp.c, try avoid it. */ #define errcode _errcode #endif /* mkstemp, getline */ #include "get_codepage.h" #endif kbuild-3686/src/oldsed/ABOUT-NLS0000664000175000017500000005132315053010105016176 0ustar locutuslocutusNotes on the Free Translation Project ************************************* Free software is going international! The Free Translation Project is a way to get maintainers of free software, translators, and users all together, so that will gradually become able to speak many languages. A few packages already provide translations for their messages. If you found this `ABOUT-NLS' file inside a distribution, you may assume that the distributed package does use GNU `gettext' internally, itself available at your nearest GNU archive site. But you do _not_ need to install GNU `gettext' prior to configuring, installing or using this package with messages translated. Installers will find here some useful hints. These notes also explain how users should proceed for getting the programs to use the available translations. They tell how people wanting to contribute and work at translations should contact the appropriate team. When reporting bugs in the `intl/' directory or bugs which may be related to internationalization, you should tell about the version of `gettext' which is used. The information can be found in the `intl/VERSION' file, in internationalized packages. Quick configuration advice ========================== If you want to exploit the full power of internationalization, you should configure it using ./configure --with-included-gettext to force usage of internationalizing routines provided within this package, despite the existence of internationalizing capabilities in the operating system where this package is being installed. So far, only the `gettext' implementation in the GNU C library version 2 provides as many features (such as locale alias, message inheritance, automatic charset conversion or plural form handling) as the implementation here. It is also not possible to offer this additional functionality on top of a `catgets' implementation. Future versions of GNU `gettext' will very likely convey even more functionality. So it might be a good idea to change to GNU `gettext' as soon as possible. So you need _not_ provide this option if you are using GNU libc 2 or you have installed a recent copy of the GNU gettext package with the included `libintl'. INSTALL Matters =============== Some packages are "localizable" when properly installed; the programs they contain can be made to speak your own native language. Most such packages use GNU `gettext'. Other packages have their own ways to internationalization, predating GNU `gettext'. By default, this package will be installed to allow translation of messages. It will automatically detect whether the system already provides the GNU `gettext' functions. If not, the GNU `gettext' own library will be used. This library is wholly contained within this package, usually in the `intl/' subdirectory, so prior installation of the GNU `gettext' package is _not_ required. Installers may use special options at configuration time for changing the default behaviour. The commands: ./configure --with-included-gettext ./configure --disable-nls will respectively bypass any pre-existing `gettext' to use the internationalizing routines provided within this package, or else, _totally_ disable translation of messages. When you already have GNU `gettext' installed on your system and run configure without an option for your new package, `configure' will probably detect the previously built and installed `libintl.a' file and will decide to use this. This might be not what is desirable. You should use the more recent version of the GNU `gettext' library. I.e. if the file `intl/VERSION' shows that the library which comes with this package is more recent, you should use ./configure --with-included-gettext to prevent auto-detection. The configuration process will not test for the `catgets' function and therefore it will not be used. The reason is that even an emulation of `gettext' on top of `catgets' could not provide all the extensions of the GNU `gettext' library. Internationalized packages have usually many `po/LL.po' files, where LL gives an ISO 639 two-letter code identifying the language. Unless translations have been forbidden at `configure' time by using the `--disable-nls' switch, all available translations are installed together with the package. However, the environment variable `LINGUAS' may be set, prior to configuration, to limit the installed set. `LINGUAS' should then contain a space separated list of two-letter codes, stating which languages are allowed. Using This Package ================== As a user, if your language has been installed for this package, you only have to set the `LANG' environment variable to the appropriate `LL_CC' combination. Here `LL' is an ISO 639 two-letter language code, and `CC' is an ISO 3166 two-letter country code. For example, let's suppose that you speak German and live in Germany. At the shell prompt, merely execute `setenv LANG de_DE' (in `csh'), `export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). This can be done from your `.login' or `.profile' file, once and for all. You might think that the country code specification is redundant. But in fact, some languages have dialects in different countries. For example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The country code serves to distinguish the dialects. The locale naming convention of `LL_CC', with `LL' denoting the language and `CC' denoting the country, is the one use on systems based on GNU libc. On other systems, some variations of this scheme are used, such as `LL' or `LL_CC.ENCODING'. You can get the list of locales supported by your system for your country by running the command `locale -a | grep '^LL''. Not all programs have translations for all languages. By default, an English message is shown in place of a nonexistent translation. If you understand other languages, you can set up a priority list of languages. This is done through a different environment variable, called `LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' for the purpose of message handling, but you still need to have `LANG' set to the primary language; this is required by other parts of the system libraries. For example, some Swedish users who would rather read translations in German than English for when Swedish is not available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. In the `LANGUAGE' environment variable, but not in the `LANG' environment variable, `LL_CC' combinations can be abbreviated as `LL' to denote the language's main dialect. For example, `de' is equivalent to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' (Portuguese as spoken in Portugal) in this context. Translating Teams ================= For the Free Translation Project to be a success, we need interested people who like their own language and write it well, and who are also able to synergize with other translators speaking the same language. Each translation team has its own mailing list. The up-to-date list of teams can be found at the Free Translation Project's homepage, `http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams" area. If you'd like to volunteer to _work_ at translating messages, you should become a member of the translating team for your own language. The subscribing address is _not_ the same as the list itself, it has `-request' appended. For example, speakers of Swedish can send a message to `sv-request@li.org', having this message body: subscribe Keep in mind that team members are expected to participate _actively_ in translations, or at solving translational difficulties, rather than merely lurking around. If your team does not exist yet and you want to start one, or if you are unsure about what to do or how to get started, please write to `translation@iro.umontreal.ca' to reach the coordinator for all translator teams. The English team is special. It works at improving and uniformizing the terminology in use. Proven linguistic skill are praised more than programming skill, here. Available Packages ================== Languages are not equally supported in all packages. The following matrix shows the current state of internationalization, as of January 2002. The matrix shows, in regard of each package, for which languages PO files have been submitted to translation coordination, with a translation percentage of at least 50%. Ready PO files bg ca cs da de el en eo es et fi fr +-------------------------------------+ a2ps | [] [] [] [] | bash | [] [] [] [] | bfd | [] [] | binutils | [] [] | bison | [] [] [] | clisp | [] [] [] [] | cpio | [] [] [] [] | diffutils | [] [] [] [] [] [] | enscript | [] [] | error | [] [] | fetchmail | () [] [] [] () | fileutils | [] [] [] [] [] | findutils | [] [] [] [] [] | flex | [] [] [] | gas | [] | gawk | [] [] | gcal | [] [] | gcc | [] [] | gettext | [] [] [] [] [] | gnupg | [] [] [] [] [] [] | gprof | [] [] | grep | [] [] [] [] [] [] | hello | [] [] [] [] [] [] [] [] | id-utils | [] [] [] | indent | [] [] [] [] | jpilot | () [] [] [] | jwhois | [] [] | kbd | [] | ld | [] [] | libc | [] [] [] [] [] [] [] | lilypond | [] [] | lynx | [] [] [] [] | m4 | [] [] [] [] [] | make | [] [] [] [] | mysecretdiary | [] [] | nano | [] () [] [] [] [] | nano_1_0 | [] () [] [] [] [] | opcodes | [] [] [] | parted | [] [] [] [] | ptx | [] [] [] [] [] | python | | recode | [] [] [] [] [] [] | sed | [] [] [] [] [] [] [] [] | sh-utils | [] [] [] [] [] [] [] [] | sharutils | [] [] [] [] [] [] | sketch | () [] () | soundtracker | [] [] [] | sp | | tar | [] [] [] [] [] [] | texinfo | [] [] [] [] [] | textutils | [] [] [] [] | util-linux | [] [] [] [] | wdiff | [] [] [] [] [] | wget | [] [] [] [] [] [] [] [] | +-------------------------------------+ bg ca cs da de el en eo es et fi fr 0 8 12 31 36 9 1 9 37 15 1 49 gl he hr hu id it ja ko lv nb nl nn +-------------------------------------+ a2ps | () () [] | bash | | bfd | [] | binutils | [] | bison | [] | clisp | [] | cpio | [] [] [] | diffutils | [] [] | enscript | [] | error | [] | fetchmail | | fileutils | [] [] | findutils | [] [] [] [] [] [] | flex | [] | gas | | gawk | [] | gcal | | gcc | [] | gettext | [] | gnupg | [] [] [] | gprof | | grep | [] [] | hello | [] [] [] [] [] [] [] [] [] | id-utils | [] | indent | [] [] [] | jpilot | () () | jwhois | | kbd | | ld | | libc | [] [] [] [] | lilypond | [] [] | lynx | [] [] | m4 | [] [] [] [] | make | [] [] [] [] | mysecretdiary | | nano | [] [] [] () () [] | nano_1_0 | [] [] [] () () [] | opcodes | | parted | [] [] [] | ptx | [] [] [] [] | python | | recode | [] [] [] | sed | [] [] [] [] [] [] [] | sh-utils | [] [] [] [] [] | sharutils | [] [] [] | sketch | () | soundtracker | [] | sp | | tar | [] [] [] | texinfo | [] [] [] | textutils | [] [] | util-linux | () [] | wdiff | | wget | [] [] [] [] [] | +-------------------------------------+ gl he hr hu id it ja ko lv nb nl nn 20 6 1 3 6 11 22 9 1 6 17 4 no pl pt pt_BR ru sk sl sv tr uk zh +-------------------------------------+ a2ps | () () () [] [] [] () | 8 bash | | 4 bfd | [] [] | 5 binutils | [] | 4 bison | [] [] [] | 7 clisp | | 5 cpio | [] [] [] [] | 11 diffutils | [] [] [] | 11 enscript | [] [] [] | 6 error | [] [] | 5 fetchmail | () () | 3 fileutils | [] [] [] [] | 11 findutils | [] [] [] [] [] [] | 17 flex | [] [] | 6 gas | [] | 2 gawk | [] [] | 5 gcal | [] | 3 gcc | [] | 4 gettext | [] [] [] [] | 10 gnupg | [] [] [] | 12 gprof | [] [] | 4 grep | [] [] [] [] [] | 13 hello | [] [] [] [] [] [] [] | 24 id-utils | [] [] | 6 indent | [] [] [] [] | 11 jpilot | () () | 3 jwhois | () () | 2 kbd | [] [] | 3 ld | [] [] | 4 libc | [] [] [] [] [] [] | 17 lilypond | [] | 5 lynx | [] [] [] | 9 m4 | [] [] [] | 12 make | [] [] [] [] | 12 mysecretdiary | [] | 3 nano | () [] [] [] | 12 nano_1_0 | () [] [] [] | 12 opcodes | [] [] | 5 parted | [] [] [] | 10 ptx | [] [] [] [] [] [] | 15 python | | 0 recode | [] [] [] [] | 13 sed | [] [] [] [] [] [] | 21 sh-utils | [] [] [] [] [] [] [] [] [] | 22 sharutils | [] [] | 11 sketch | () | 1 soundtracker | | 4 sp | | 0 tar | [] [] [] [] [] [] [] | 16 texinfo | [] [] | 10 textutils | [] [] | 8 util-linux | [] [] [] | 8 wdiff | [] [] [] [] | 9 wget | [] [] [] [] [] [] | 19 +-------------------------------------+ 35 teams no pl pt pt_BR ru sk sl sv tr uk zh 54 domains 5 12 2 11 25 10 11 39 29 4 1 463 Some counters in the preceding matrix are higher than the number of visible blocks let us expect. This is because a few extra PO files are used for implementing regional variants of languages, or language dialects. For a PO file in the matrix above to be effective, the package to which it applies should also have been internationalized and distributed as such by its maintainer. There might be an observable lag between the mere existence a PO file and its wide availability in a distribution. If January 2002 seems to be old, you may fetch a more recent copy of this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date matrix with full percentage details can be found at `http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'. Using `gettext' in new packages =============================== If you are writing a freely available program and want to internationalize it you are welcome to use GNU `gettext' in your package. Of course you have to respect the GNU Library General Public License which covers the use of the GNU `gettext' library. This means in particular that even non-free programs can use `libintl' as a shared library, whereas only free software can use `libintl' as a static library or use modified versions of `libintl'. Once the sources are changed appropriately and the setup can handle to use of `gettext' the only thing missing are the translations. The Free Translation Project is also available for packages which are not developed inside the GNU project. Therefore the information given above applies also for every other Free Software Project. Contact `translation@iro.umontreal.ca' to make the `.pot' files available to the translation teams. kbuild-3686/src/oldsed/THANKS0000664000175000017500000000340215053010105015655 0ustar locutuslocutusAkim Demaille Alan Modra Arnold Robbins Andreas Schwab Andrew Herbert Bruno Haible Chip Salzenberg Chris Weber David Eckelkamp David J. MacKenzie David Schmidt Dietrich Kappe Doug McIlroy Eero Hakkinen Eli Zaretskii Eric Pement Erick Branderhorst Francois Pinard Gaumond Pierre Greg Ubben Isamu Hasegawa J.T. Conklin Jakub Jelinek Jason Molenda Jim Meyering Laurent Vogel Karl Berry Karl Heuer Kaveh R. Ghazi Kevin Buettner Maciej W. Rozycki Mark Kettenis Michael De La Rue Michel de Ruiter Paul Eggert Robert A Bruce Ronnie Glasscock Simon Taylor Stepan Kasal Stephen Davis Steve Ingram Tapani Tarvainen Timothy J Luoma Tom R.Hageman Ulrich Drepper Vladimir Volovich Wichert Akkerman And the GNU translation teams. kbuild-3686/src/oldsed/config/0000775000175000017500000000000015053010105016210 5ustar locutuslocutuskbuild-3686/src/oldsed/config/lib-link.m40000664000175000017500000005276315053010105020170 0ustar locutuslocutus# lib-link.m4 serial 1 (gettext-0.11) dnl Copyright (C) 2001-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. dnl From Bruno Haible. dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and dnl augments the CPPFLAGS variable. AC_DEFUN([AC_LIB_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) define([Name],[translit([$1],[./-], [___])]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ AC_LIB_LINKFLAGS_BODY([$1], [$2]) ac_cv_lib[]Name[]_libs="$LIB[]NAME" ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" ac_cv_lib[]Name[]_cppflags="$INC[]NAME" ]) LIB[]NAME="$ac_cv_lib[]Name[]_libs" LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" INC[]NAME="$ac_cv_lib[]Name[]_cppflags" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the dnl results of this search when this library appears as a dependency. HAVE_LIB[]NAME=yes undefine([Name]) undefine([NAME]) ]) dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode) dnl searches for libname and the libraries corresponding to explicit and dnl implicit dependencies, together with the specified include files and dnl the ability to compile and link the specified testcode. If found, it dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) define([Name],[translit([$1],[./-], [___])]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME dnl accordingly. AC_LIB_LINKFLAGS_BODY([$1], [$2]) dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, dnl because if the user has installed lib[]Name and not disabled its use dnl via --without-lib[]Name-prefix, he wants to use it. ac_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ ac_save_LIBS="$LIBS" LIBS="$LIBS $LIB[]NAME" AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no]) LIBS="$ac_save_LIBS" ]) if test "$ac_cv_lib[]Name" = yes; then HAVE_LIB[]NAME=yes AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.]) AC_MSG_CHECKING([how to link with lib[]$1]) AC_MSG_RESULT([$LIB[]NAME]) else HAVE_LIB[]NAME=no dnl If $LIB[]NAME didn't lead to a usable library, we don't need dnl $INC[]NAME either. CPPFLAGS="$ac_save_CPPFLAGS" LIB[]NAME= LTLIB[]NAME= fi AC_SUBST([HAVE_LIB]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) undefine([Name]) undefine([NAME]) ]) dnl Determine the platform dependent parameters needed to use rpath: dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator, dnl hardcode_direct, hardcode_minus_L, dnl sys_lib_search_path_spec, sys_lib_dlsearch_path_spec. AC_DEFUN([AC_LIB_RPATH], [ AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done ]) wl="$acl_cv_wl" libext="$acl_cv_libext" shlibext="$acl_cv_shlibext" hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" hardcode_direct="$acl_cv_hardcode_direct" hardcode_minus_L="$acl_cv_hardcode_minus_L" sys_lib_search_path_spec="$acl_cv_sys_lib_search_path_spec" sys_lib_dlsearch_path_spec="$acl_cv_sys_lib_dlsearch_path_spec" ]) dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. AC_DEFUN([AC_LIB_LINKFLAGS_BODY], [ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_ARG_WITH([lib$1-prefix], [ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib --without-lib$1-prefix don't search for lib$1 in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/lib" fi fi ]) dnl Search the library and its dependencies in $additional_libdir and dnl $LDFLAGS. Using breadth-first-seach. LIB[]NAME= LTLIB[]NAME= INC[]NAME= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='$1 $2' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" dnl See if it was already located by an earlier AC_LIB_LINKFLAGS dnl or AC_LIB_HAVE_LINKFLAGS call. uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" else dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined dnl that this library doesn't exist. So just drop it. : fi else dnl Search the library lib$name in $additional_libdir and $LDFLAGS dnl and the already constructed $LIBNAME/$LTLIBNAME. found_dir= found_la= found_so= found_a= if test $use_additional = yes; then if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then found_dir="$additional_libdir" found_so="$additional_libdir/lib$name.$shlibext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi else if test -f "$additional_libdir/lib$name.$libext"; then found_dir="$additional_libdir" found_a="$additional_libdir/lib$name.$libext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then found_dir="$dir" found_so="$dir/lib$name.$shlibext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi else if test -f "$dir/lib$name.$libext"; then found_dir="$dir" found_a="$dir/lib$name.$libext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then dnl Found the library. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then dnl Linking with a shared library. We attempt to hardcode its dnl directory into the executable's runpath, unless it's the dnl standard /usr/lib. if test "X$found_dir" = "X/usr/lib"; then dnl No hardcoding is needed. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl Use an explicit option to hardcode DIR into the resulting dnl binary. dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi dnl The hardcoding into $LIBNAME is system dependent. if test "$hardcode_direct" = yes; then dnl Using DIR/libNAME.so during linking hardcodes DIR into the dnl resulting binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then dnl Use an explicit option to hardcode DIR into the resulting dnl binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else dnl Rely on "-L$found_dir". dnl But don't add it if it's already contained in the LDFLAGS dnl or the already constructed $LIBNAME haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" fi if test "$hardcode_minus_L" != no; then dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH dnl here, because this doesn't fit in flags passed to the dnl compiler. So give up. No hardcoding. This affects only dnl very old systems. dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then dnl Linking with a static library. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" else dnl We shouldn't come here, but anyway it's good to have a dnl fallback. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" fi fi dnl Assume the include files are nearby. additional_includedir= case "$found_dir" in */lib | */lib/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then dnl Potentially add $additional_includedir to $INCNAME. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's /usr/local/include and we are using GCC on Linux, dnl 3. if it's already present in $CPPFLAGS or the already dnl constructed $INCNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INC[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $INCNAME. INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" fi fi fi fi fi dnl Look for dependencies. if test -n "$found_la"; then dnl Read the .la file. It defines the variables dnl dlname, library_names, old_library, dependency_libs, current, dnl age, revision, installed, dlopen, dlpreopen, libdir. save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" dnl We use only dependency_libs. for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's /usr/local/lib and we are using GCC on Linux, dnl 3. if it's already present in $LDFLAGS or the already dnl constructed $LIBNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/lib"; then haveit= if test "X$additional_libdir" = "X/usr/local/lib"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LIBNAME. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LTLIBNAME. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" fi fi fi fi ;; -l*) dnl Handle this in the next round. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) dnl Handle this in the next round. Throw away the .la's dnl directory; it is already contained in a preceding -L dnl option. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) dnl Most likely an immediate library name. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" ;; esac done fi else dnl Didn't find the library; assume it is in the system directories dnl known to the linker and runtime loader. (All the system dnl directories known to the linker should also be known to the dnl runtime loader, otherwise the system is severely misconfigured.) LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user must dnl pass all path elements in one option. We can arrange that for a dnl single library, but not when more than one $LIBNAMEs are used. alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" done dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl. acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" else dnl The -rpath options are cumulative. for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then dnl When using libtool, the option that works for both libraries and dnl executables is -R. The -R options are cumulative. for found_dir in $ltrpathdirs; do LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" done fi ]) dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, dnl unless already present in VAR. dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes dnl contains two or three consecutive elements that belong together. AC_DEFUN([AC_LIB_APPENDTOVAR], [ for element in [$2]; do haveit= for x in $[$1]; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then [$1]="${[$1]}${[$1]:+ }$element" fi done ]) kbuild-3686/src/oldsed/config/help2man0000775000175000017500000003057015053010105017651 0ustar locutuslocutus#!/usr/bin/env perl # Generate a short man page from --help and --version output. # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software # Foundation, Inc. # 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, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Written by Brendan O'Dea # Available from ftp://ftp.gnu.org/gnu/help2man/ use 5.005; use strict; use Getopt::Long; use Text::Tabs qw(expand); use POSIX qw(strftime setlocale LC_TIME); my $this_program = 'help2man'; my $this_version = '1.28'; my $version_info = < EOT my $help_info = <. EOT my $section = 1; my $manual = ''; my $source = ''; my $help_option = '--help'; my $version_option = '--version'; my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info); my %opt_def = ( 'n|name=s' => \$opt_name, 's|section=s' => \$section, 'm|manual=s' => \$manual, 'S|source=s' => \$source, 'i|include=s' => sub { push @opt_include, [ pop, 1 ] }, 'I|opt-include=s' => sub { push @opt_include, [ pop, 0 ] }, 'o|output=s' => \$opt_output, 'p|info-page=s' => \$opt_info, 'N|no-info' => \$opt_no_info, 'h|help-option=s' => \$help_option, 'v|version-option=s' => \$version_option, ); # Parse options. Getopt::Long::config('bundling'); GetOptions (%opt_def, help => sub { print $help_info; exit }, version => sub { print $version_info; exit }, ) or die $help_info; die $help_info unless @ARGV == 1; my %include = (); my %append = (); my @include = (); # retain order given in include file # Process include file (if given). Format is: # # [section name] # verbatim text # # or # # /pattern/ # verbatim text # while (@opt_include) { my ($inc, $required) = @{shift @opt_include}; next unless -f $inc or $required; die "$this_program: can't open `$inc' ($!)\n" unless open INC, $inc; my $key; my $hash = \%include; while () { # [section] if (/^\[([^]]+)\]/) { $key = uc $1; $key =~ s/^\s+//; $key =~ s/\s+$//; $hash = \%include; push @include, $key unless $include{$key}; next; } # /pattern/ if (m!^/(.*)/([ims]*)!) { my $pat = $2 ? "(?$2)$1" : $1; # Check pattern. eval { $key = qr($pat) }; if ($@) { $@ =~ s/ at .*? line \d.*//; die "$inc:$.:$@"; } $hash = \%append; next; } # Check for options before the first section--anything else is # silently ignored, allowing the first for comments and # revision info. unless ($key) { # handle options if (/^-/) { local @ARGV = split; GetOptions %opt_def; } next; } $hash->{$key} ||= ''; $hash->{$key} .= $_; } close INC; die "$this_program: no valid information found in `$inc'\n" unless $key; } # Compress trailing blank lines. for my $hash (\(%include, %append)) { for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ } } # Turn off localisation of executable's ouput. @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; # Turn off localisation of date (for strftime). setlocale LC_TIME, 'C'; # Grab help and version info from executable. my ($help_text, $version_text) = map { join '', map { s/ +$//; expand $_ } `$ARGV[0] $_ 2>/dev/null` or die "$this_program: can't get `$_' info from $ARGV[0]\n" } $help_option, $version_option; my $date = strftime "%B %Y", localtime; (my $program = $ARGV[0]) =~ s!.*/!!; my $package = $program; my $version; if ($opt_output) { unlink $opt_output or die "$this_program: can't unlink $opt_output ($!)\n" if -e $opt_output; open STDOUT, ">$opt_output" or die "$this_program: can't create $opt_output ($!)\n"; } # The first line of the --version information is assumed to be in one # of the following formats: # # # # {GNU,Free} # ({GNU,Free} ) # - {GNU,Free} # # and seperated from any copyright/author details by a blank line. ($_, $version_text) = split /\n+/, $version_text, 2; if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/) { $program = $1; $package = $2; $version = $3; } elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/) { $program = $2; $package = $1 ? "$1$2" : $2; $version = $3; } else { $version = $_; } $program =~ s!.*/!!; # No info for `info' itself. $opt_no_info = 1 if $program eq 'info'; # --name overrides --include contents. $include{NAME} = "$program \\- $opt_name\n" if $opt_name; # Default (useless) NAME paragraph. $include{NAME} ||= "$program \\- manual page for $program $version\n"; # Man pages traditionally have the page title in caps. my $PROGRAM = uc $program; # Set default page head/footers $source ||= "$program $version"; unless ($manual) { for ($section) { if (/^(1[Mm]|8)/) { $manual = 'System Administration Utilities' } elsif (/^6/) { $manual = 'Games' } else { $manual = 'User Commands' } } } # Extract usage clause(s) [if any] for SYNOPSIS. if ($help_text =~ s/^Usage:( +(\S+))(.*)((?:\n(?: {6}\1| *or: +\S).*)*)//m) { my @syn = $2 . $3; if ($_ = $4) { s/^\n//; for (split /\n/) { s/^ *(or: +)?//; push @syn, $_ } } my $synopsis = ''; for (@syn) { $synopsis .= ".br\n" if $synopsis; s!^\S*/!!; s/^(\S+) *//; $synopsis .= ".B $1\n"; s/\s+$//; s/(([][]|\.\.+)+)/\\fR$1\\fI/g; s/^/\\fI/ unless s/^\\fR//; $_ .= '\fR'; s/(\\fI)( *)/$2$1/g; s/\\fI\\fR//g; s/^\\fR//; s/\\fI$//; s/^\./\\&./; $synopsis .= "$_\n"; } $include{SYNOPSIS} ||= $synopsis; } # Process text, initial section is DESCRIPTION. my $sect = 'DESCRIPTION'; $_ = "$help_text\n\n$version_text"; # Normalise paragraph breaks. s/^\n+//; s/\n*$/\n/; s/\n\n+/\n\n/g; # Temporarily exchange leading dots, apostrophes and backslashes for # tokens. s/^\./\x80/mg; s/^'/\x81/mg; s/\\/\x82/g; # Start a new paragraph (if required) for these. s/([^\n])\n(Report +bugs|Email +bug +reports +to|Written +by)/$1\n\n$2/g; sub convert_option; while (length) { # Convert some standard paragraph names. if (s/^(Options|Examples): *\n//) { $sect = uc $1; next; } # Copyright section if (/^Copyright +[(\xa9]/) { $sect = 'COPYRIGHT'; $include{$sect} ||= ''; $include{$sect} .= ".PP\n" if $include{$sect}; my $copy; ($copy, $_) = split /\n\n/, $_, 2; for ($copy) { # Add back newline s/\n*$/\n/; # Convert iso9959-1 copyright symbol or (c) to nroff # character. s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg; # Insert line breaks before additional copyright messages # and the disclaimer. s/(.)\n(Copyright |This +is +free +software)/$1\n.br\n$2/g; # Join hyphenated lines. s/([A-Za-z])-\n */$1/g; } $include{$sect} .= $copy; $_ ||= ''; next; } # Catch bug report text. if (/^(Report +bugs|Email +bug +reports +to) /) { $sect = 'REPORTING BUGS'; } # Author section. elsif (/^Written +by/) { $sect = 'AUTHOR'; } # Examples, indicated by an indented leading $, % or > are # rendered in a constant width font. if (/^( +)([\$\%>] )\S/) { my $indent = $1; my $prefix = $2; my $break = '.IP'; $include{$sect} ||= ''; while (s/^$indent\Q$prefix\E(\S.*)\n*//) { $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n"; $break = '.br'; } next; } my $matched = ''; $include{$sect} ||= ''; # Sub-sections have a trailing colon and the second line indented. if (s/^(\S.*:) *\n / /) { $matched .= $& if %append; $include{$sect} .= qq(.SS "$1"\n); } my $indent = 0; my $content = ''; # Option with description. if (s/^( {1,10}([+-]\S.*?))(?:( +(?!-))|\n( {20,}))(\S.*)\n//) { $matched .= $& if %append; $indent = length ($4 || "$1$3"); $content = ".TP\n\x83$2\n\x83$5\n"; unless ($4) { # Indent may be different on second line. $indent = length $& if /^ {20,}/; } } # Option without description. elsif (s/^ {1,10}([+-]\S.*)\n//) { $matched .= $& if %append; $content = ".HP\n\x83$1\n"; $indent = 80; # not continued } # Indented paragraph with tag. elsif (s/^( +(\S.*?) +)(\S.*)\n//) { $matched .= $& if %append; $indent = length $1; $content = ".TP\n\x83$2\n\x83$3\n"; } # Indented paragraph. elsif (s/^( +)(\S.*)\n//) { $matched .= $& if %append; $indent = length $1; $content = ".IP\n\x83$2\n"; } # Left justified paragraph. else { s/(.*)\n//; $matched .= $& if %append; $content = ".PP\n" if $include{$sect}; $content .= "$1\n"; } # Append continuations. while (s/^ {$indent}(\S.*)\n//) { $matched .= $& if %append; $content .= "\x83$1\n" } # Move to next paragraph. s/^\n+//; for ($content) { # Leading dot and apostrophe protection. s/\x83\./\x80/g; s/\x83'/\x81/g; s/\x83//g; # Convert options. s/(^| )(-[][\w=-]+)/$1 . convert_option $2/mge; } # Check if matched paragraph contains /pat/. if (%append) { for my $pat (keys %append) { if ($matched =~ $pat) { $content .= ".PP\n" unless $append{$pat} =~ /^\./; $content .= $append{$pat}; } } } $include{$sect} .= $content; } # Refer to the real documentation. unless ($opt_no_info) { my $info_page = $opt_info || $program; $sect = 'SEE ALSO'; $include{$sect} ||= ''; $include{$sect} .= ".PP\n" if $include{$sect}; $include{$sect} .= < \let\ptexhat=^ \let\ptexi=\i \let\ptexindent=\indent \let\ptexnoindent=\noindent \let\ptexinsert=\insert \let\ptexlbrace=\{ \let\ptexless=< \let\ptexplus=+ \let\ptexrbrace=\} \let\ptexslash=\/ \let\ptexstar=\* \let\ptext=\t % If this character appears in an error message or help string, it % starts a new line in the output. \newlinechar = `^^J % Use TeX 3.0's \inputlineno to get the line number, for better error % messages, but if we're using an old version of TeX, don't do anything. % \ifx\inputlineno\thisisundefined \let\linenumber = \empty % Pre-3.0. \else \def\linenumber{l.\the\inputlineno:\space} \fi % Set up fixed words for English if not already set. \ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi \ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi \ifx\putwordfile\undefined \gdef\putwordfile{file}\fi \ifx\putwordin\undefined \gdef\putwordin{in}\fi \ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi \ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi \ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi \ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi \ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi \ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi \ifx\putwordof\undefined \gdef\putwordof{of}\fi \ifx\putwordon\undefined \gdef\putwordon{on}\fi \ifx\putwordpage\undefined \gdef\putwordpage{page}\fi \ifx\putwordsection\undefined \gdef\putwordsection{section}\fi \ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi \ifx\putwordsee\undefined \gdef\putwordsee{see}\fi \ifx\putwordSee\undefined \gdef\putwordSee{See}\fi \ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi \ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi % \ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi \ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi \ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi \ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi \ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi \ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi \ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi \ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi \ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi \ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi \ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi \ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi % \ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi \ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi \ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi \ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi \ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi % In some macros, we cannot use the `\? notation---the left quote is % in some cases the escape char. \chardef\colonChar = `\: \chardef\commaChar = `\, \chardef\dotChar = `\. \chardef\exclamChar= `\! \chardef\questChar = `\? \chardef\semiChar = `\; \chardef\underChar = `\_ \chardef\spaceChar = `\ % \chardef\spacecat = 10 \def\spaceisspace{\catcode\spaceChar=\spacecat} % Ignore a token. % \def\gobble#1{} % The following is used inside several \edef's. \def\makecsname#1{\expandafter\noexpand\csname#1\endcsname} % Hyphenation fixes. \hyphenation{ Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script ap-pen-dix bit-map bit-maps data-base data-bases eshell fall-ing half-way long-est man-u-script man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces spell-ing spell-ings stand-alone strong-est time-stamp time-stamps which-ever white-space wide-spread wrap-around } % Margin to add to right of even pages, to left of odd pages. \newdimen\bindingoffset \newdimen\normaloffset \newdimen\pagewidth \newdimen\pageheight % For a final copy, take out the rectangles % that mark overfull boxes (in case you have decided % that the text looks ok even though it passes the margin). % \def\finalout{\overfullrule=0pt} % @| inserts a changebar to the left of the current line. It should % surround any changed text. This approach does *not* work if the % change spans more than two lines of output. To handle that, we would % have adopt a much more difficult approach (putting marks into the main % vertical list for the beginning and end of each change). % \def\|{% % \vadjust can only be used in horizontal mode. \leavevmode % % Append this vertical mode material after the current line in the output. \vadjust{% % We want to insert a rule with the height and depth of the current % leading; that is exactly what \strutbox is supposed to record. \vskip-\baselineskip % % \vadjust-items are inserted at the left edge of the type. So % the \llap here moves out into the left-hand margin. \llap{% % % For a thicker or thinner bar, change the `1pt'. \vrule height\baselineskip width1pt % % This is the space between the bar and the text. \hskip 12pt }% }% } % Sometimes it is convenient to have everything in the transcript file % and nothing on the terminal. We don't just call \tracingall here, % since that produces some useless output on the terminal. We also make % some effort to order the tracing commands to reduce output in the log % file; cf. trace.sty in LaTeX. % \def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% \def\loggingall{% \tracingstats2 \tracingpages1 \tracinglostchars2 % 2 gives us more in etex \tracingparagraphs1 \tracingoutput1 \tracingmacros2 \tracingrestores1 \showboxbreadth\maxdimen \showboxdepth\maxdimen \ifx\eTeXversion\undefined\else % etex gives us more logging \tracingscantokens1 \tracingifs1 \tracinggroups1 \tracingnesting2 \tracingassigns1 \fi \tracingcommands3 % 3 gives us more in etex \errorcontextlines16 }% % add check for \lastpenalty to plain's definitions. If the last thing % we did was a \nobreak, we don't want to insert more space. % \def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount \removelastskip\penalty-50\smallskip\fi\fi} \def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount \removelastskip\penalty-100\medskip\fi\fi} \def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount \removelastskip\penalty-200\bigskip\fi\fi} % For @cropmarks command. % Do @cropmarks to get crop marks. % \newif\ifcropmarks \let\cropmarks = \cropmarkstrue % % Dimensions to add cropmarks at corners. % Added by P. A. MacKay, 12 Nov. 1986 % \newdimen\outerhsize \newdimen\outervsize % set by the paper size routines \newdimen\cornerlong \cornerlong=1pc \newdimen\cornerthick \cornerthick=.3pt \newdimen\topandbottommargin \topandbottommargin=.75in % Main output routine. \chardef\PAGE = 255 \output = {\onepageout{\pagecontents\PAGE}} \newbox\headlinebox \newbox\footlinebox % \onepageout takes a vbox as an argument. Note that \pagecontents % does insertions, but you have to call it yourself. \def\onepageout#1{% \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi % \ifodd\pageno \advance\hoffset by \bindingoffset \else \advance\hoffset by -\bindingoffset\fi % % Do this outside of the \shipout so @code etc. will be expanded in % the headline as they should be, not taken literally (outputting ''code). \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% % {% % Have to do this stuff outside the \shipout because we want it to % take effect in \write's, yet the group defined by the \vbox ends % before the \shipout runs. % \escapechar = `\\ % use backslash in output files. \indexdummies % don't expand commands in the output. \normalturnoffactive % \ in index entries must not stay \, e.g., if % the page break happens to be in the middle of an example. \shipout\vbox{% % Do this early so pdf references go to the beginning of the page. \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi % \ifcropmarks \vbox to \outervsize\bgroup \hsize = \outerhsize \vskip-\topandbottommargin \vtop to0pt{% \line{\ewtop\hfil\ewtop}% \nointerlineskip \line{% \vbox{\moveleft\cornerthick\nstop}% \hfill \vbox{\moveright\cornerthick\nstop}% }% \vss}% \vskip\topandbottommargin \line\bgroup \hfil % center the page within the outer (page) hsize. \ifodd\pageno\hskip\bindingoffset\fi \vbox\bgroup \fi % \unvbox\headlinebox \pagebody{#1}% \ifdim\ht\footlinebox > 0pt % Only leave this space if the footline is nonempty. % (We lessened \vsize for it in \oddfootingxxx.) % The \baselineskip=24pt in plain's \makefootline has no effect. \vskip 2\baselineskip \unvbox\footlinebox \fi % \ifcropmarks \egroup % end of \vbox\bgroup \hfil\egroup % end of (centering) \line\bgroup \vskip\topandbottommargin plus1fill minus1fill \boxmaxdepth = \cornerthick \vbox to0pt{\vss \line{% \vbox{\moveleft\cornerthick\nsbot}% \hfill \vbox{\moveright\cornerthick\nsbot}% }% \nointerlineskip \line{\ewbot\hfil\ewbot}% }% \egroup % \vbox from first cropmarks clause \fi }% end of \shipout\vbox }% end of group with \normalturnoffactive \advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi } \newinsert\margin \dimen\margin=\maxdimen \def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} {\catcode`\@ =11 \gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi % marginal hacks, juha@viisa.uucp (Juha Takala) \ifvoid\margin\else % marginal info is present \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi \dimen@=\dp#1 \unvbox#1 \ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi \ifr@ggedbottom \kern-\dimen@ \vfil \fi} } % Here are the rules for the cropmarks. Note that they are % offset so that the space between them is truly \outerhsize or \outervsize % (P. A. MacKay, 12 November, 1986) % \def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} \def\nstop{\vbox {\hrule height\cornerthick depth\cornerlong width\cornerthick}} \def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} \def\nsbot{\vbox {\hrule height\cornerlong depth\cornerthick width\cornerthick}} % Parse an argument, then pass it to #1. The argument is the rest of % the input line (except we remove a trailing comment). #1 should be a % macro which expects an ordinary undelimited TeX argument. % \def\parsearg{\parseargusing{}} \def\parseargusing#1#2{% \def\next{#2}% \begingroup \obeylines \spaceisspace #1% \parseargline\empty% Insert the \empty token, see \finishparsearg below. } {\obeylines % \gdef\parseargline#1^^M{% \endgroup % End of the group started in \parsearg. \argremovecomment #1\comment\ArgTerm% }% } % First remove any @comment, then any @c comment. \def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} \def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} % Each occurence of `\^^M' or `\^^M' is replaced by a single space. % % \argremovec might leave us with trailing space, e.g., % @end itemize @c foo % This space token undergoes the same procedure and is eventually removed % by \finishparsearg. % \def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M} \def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M} \def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% \def\temp{#3}% \ifx\temp\empty % We cannot use \next here, as it holds the macro to run; % thus we reuse \temp. \let\temp\finishparsearg \else \let\temp\argcheckspaces \fi % Put the space token in: \temp#1 #3\ArgTerm } % If a _delimited_ argument is enclosed in braces, they get stripped; so % to get _exactly_ the rest of the line, we had to prevent such situation. % We prepended an \empty token at the very beginning and we expand it now, % just before passing the control to \next. % (Similarily, we have to think about #3 of \argcheckspacesY above: it is % either the null string, or it ends with \^^M---thus there is no danger % that a pair of braces would be stripped. % % But first, we have to remove the trailing space token. % \def\finishparsearg#1 \ArgTerm{\expandafter\next\expandafter{#1}} % \parseargdef\foo{...} % is roughly equivalent to % \def\foo{\parsearg\Xfoo} % \def\Xfoo#1{...} % % Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my % favourite TeX trick. --kasal, 16nov03 \def\parseargdef#1{% \expandafter \doparseargdef \csname\string#1\endcsname #1% } \def\doparseargdef#1#2{% \def#2{\parsearg#1}% \def#1##1% } % Several utility definitions with active space: { \obeyspaces \gdef\obeyedspace{ } % Make each space character in the input produce a normal interword % space in the output. Don't allow a line break at this space, as this % is used only in environments like @example, where each line of input % should produce a line of output anyway. % \gdef\sepspaces{\obeyspaces\let =\tie} % If an index command is used in an @example environment, any spaces % therein should become regular spaces in the raw index file, not the % expansion of \tie (\leavevmode \penalty \@M \ ). \gdef\unsepspaces{\let =\space} } \def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} % Define the framework for environments in texinfo.tex. It's used like this: % % \envdef\foo{...} % \def\Efoo{...} % % It's the responsibility of \envdef to insert \begingroup before the % actual body; @end closes the group after calling \Efoo. \envdef also % defines \thisenv, so the current environment is known; @end checks % whether the environment name matches. The \checkenv macro can also be % used to check whether the current environment is the one expected. % % Non-false conditionals (@iftex, @ifset) don't fit into this, so they % are not treated as enviroments; they don't open a group. (The % implementation of @end takes care not to call \endgroup in this % special case.) % At runtime, environments start with this: \def\startenvironment#1{\begingroup\def\thisenv{#1}} % initialize \let\thisenv\empty % ... but they get defined via ``\envdef\foo{...}'': \long\def\envdef#1#2{\def#1{\startenvironment#1#2}} \def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}} % Check whether we're in the right environment: \def\checkenv#1{% \def\temp{#1}% \ifx\thisenv\temp \else \badenverr \fi } % Evironment mismatch, #1 expected: \def\badenverr{% \errhelp = \EMsimple \errmessage{This command can appear only \inenvironment\temp, not \inenvironment\thisenv}% } \def\inenvironment#1{% \ifx#1\empty out of any environment% \else in environment \expandafter\string#1% \fi } % @end foo executes the definition of \Efoo. % But first, it executes a specialized version of \checkenv % \parseargdef\end{% \if 1\csname iscond.#1\endcsname \else % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03 \expandafter\checkenv\csname#1\endcsname \csname E#1\endcsname \endgroup \fi } \newhelp\EMsimple{Press RETURN to continue.} %% Simple single-character @ commands % @@ prints an @ % Kludge this until the fonts are right (grr). \def\@{{\tt\char64}} % This is turned off because it was never documented % and you can use @w{...} around a quote to suppress ligatures. %% Define @` and @' to be the same as ` and ' %% but suppressing ligatures. %\def\`{{`}} %\def\'{{'}} % Used to generate quoted braces. \def\mylbrace {{\tt\char123}} \def\myrbrace {{\tt\char125}} \let\{=\mylbrace \let\}=\myrbrace \begingroup % Definitions to produce \{ and \} commands for indices, % and @{ and @} for the aux file. \catcode`\{ = \other \catcode`\} = \other \catcode`\[ = 1 \catcode`\] = 2 \catcode`\! = 0 \catcode`\\ = \other !gdef!lbracecmd[\{]% !gdef!rbracecmd[\}]% !gdef!lbraceatcmd[@{]% !gdef!rbraceatcmd[@}]% !endgroup % @comma{} to avoid , parsing problems. \let\comma = , % Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent % Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. \let\, = \c \let\dotaccent = \. \def\ringaccent#1{{\accent23 #1}} \let\tieaccent = \t \let\ubaraccent = \b \let\udotaccent = \d % Other special characters: @questiondown @exclamdown @ordf @ordm % Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. \def\questiondown{?`} \def\exclamdown{!`} \def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} \def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} % Dotless i and dotless j, used for accents. \def\imacro{i} \def\jmacro{j} \def\dotless#1{% \def\temp{#1}% \ifx\temp\imacro \ptexi \else\ifx\temp\jmacro \j \else \errmessage{@dotless can be used only with i or j}% \fi\fi } % The \TeX{} logo, as in plain, but resetting the spacing so that a % period following counts as ending a sentence. (Idea found in latex.) % \edef\TeX{\TeX \spacefactor=1000 } % @LaTeX{} logo. Not quite the same results as the definition in % latex.ltx, since we use a different font for the raised A; it's most % convenient for us to use an explicitly smaller font, rather than using % the \scriptstyle font (since we don't reset \scriptstyle and % \scriptscriptstyle). % \def\LaTeX{% L\kern-.36em {\setbox0=\hbox{T}% \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}% \kern-.15em \TeX } % Be sure we're in horizontal mode when doing a tie, since we make space % equivalent to this in @example-like environments. Otherwise, a space % at the beginning of a line will start with \penalty -- and % since \penalty is valid in vertical mode, we'd end up putting the % penalty on the vertical list instead of in the new paragraph. {\catcode`@ = 11 % Avoid using \@M directly, because that causes trouble % if the definition is written into an index file. \global\let\tiepenalty = \@M \gdef\tie{\leavevmode\penalty\tiepenalty\ } } % @: forces normal size whitespace following. \def\:{\spacefactor=1000 } % @* forces a line break. \def\*{\hfil\break\hbox{}\ignorespaces} % @/ allows a line break. \let\/=\allowbreak % @. is an end-of-sentence period. \def\.{.\spacefactor=3000 } % @! is an end-of-sentence bang. \def\!{!\spacefactor=3000 } % @? is an end-of-sentence query. \def\?{?\spacefactor=3000 } % @w prevents a word break. Without the \leavevmode, @w at the % beginning of a paragraph, when TeX is still in vertical mode, would % produce a whole line of output instead of starting the paragraph. \def\w#1{\leavevmode\hbox{#1}} % @group ... @end group forces ... to be all on one page, by enclosing % it in a TeX vbox. We use \vtop instead of \vbox to construct the box % to keep its height that of a normal line. According to the rules for % \topskip (p.114 of the TeXbook), the glue inserted is % max (\topskip - \ht (first item), 0). If that height is large, % therefore, no glue is inserted, and the space between the headline and % the text is small, which looks bad. % % Another complication is that the group might be very large. This can % cause the glue on the previous page to be unduly stretched, because it % does not have much material. In this case, it's better to add an % explicit \vfill so that the extra space is at the bottom. The % threshold for doing this is if the group is more than \vfilllimit % percent of a page (\vfilllimit can be changed inside of @tex). % \newbox\groupbox \def\vfilllimit{0.7} % \envdef\group{% \ifnum\catcode`\^^M=\active \else \errhelp = \groupinvalidhelp \errmessage{@group invalid in context where filling is enabled}% \fi \startsavinginserts % \setbox\groupbox = \vtop\bgroup % Do @comment since we are called inside an environment such as % @example, where each end-of-line in the input causes an % end-of-line in the output. We don't want the end-of-line after % the `@group' to put extra space in the output. Since @group % should appear on a line by itself (according to the Texinfo % manual), we don't worry about eating any user text. \comment } % % The \vtop produces a box with normal height and large depth; thus, TeX puts % \baselineskip glue before it, and (when the next line of text is done) % \lineskip glue after it. Thus, space below is not quite equal to space % above. But it's pretty close. \def\Egroup{% % To get correct interline space between the last line of the group % and the first line afterwards, we have to propagate \prevdepth. \endgraf % Not \par, as it may have been set to \lisppar. \global\dimen1 = \prevdepth \egroup % End the \vtop. % \dimen0 is the vertical size of the group's box. \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox % \dimen2 is how much space is left on the page (more or less). \dimen2 = \pageheight \advance\dimen2 by -\pagetotal % if the group doesn't fit on the current page, and it's a big big % group, force a page break. \ifdim \dimen0 > \dimen2 \ifdim \pagetotal < \vfilllimit\pageheight \page \fi \fi \box\groupbox \prevdepth = \dimen1 \checkinserts } % % TeX puts in an \escapechar (i.e., `@') at the beginning of the help % message, so this ends up printing `@group can only ...'. % \newhelp\groupinvalidhelp{% group can only be used in environments such as @example,^^J% where each line of input produces a line of output.} % @need space-in-mils % forces a page break if there is not space-in-mils remaining. \newdimen\mil \mil=0.001in % Old definition--didn't work. %\parseargdef\need{\par % %% This method tries to make TeX break the page naturally %% if the depth of the box does not fit. %{\baselineskip=0pt% %\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak %\prevdepth=-1000pt %}} \parseargdef\need{% % Ensure vertical mode, so we don't make a big box in the middle of a % paragraph. \par % % If the @need value is less than one line space, it's useless. \dimen0 = #1\mil \dimen2 = \ht\strutbox \advance\dimen2 by \dp\strutbox \ifdim\dimen0 > \dimen2 % % Do a \strut just to make the height of this box be normal, so the % normal leading is inserted relative to the preceding line. % And a page break here is fine. \vtop to #1\mil{\strut\vfil}% % % TeX does not even consider page breaks if a penalty added to the % main vertical list is 10000 or more. But in order to see if the % empty box we just added fits on the page, we must make it consider % page breaks. On the other hand, we don't want to actually break the % page after the empty box. So we use a penalty of 9999. % % There is an extremely small chance that TeX will actually break the % page at this \penalty, if there are no other feasible breakpoints in % sight. (If the user is using lots of big @group commands, which % almost-but-not-quite fill up a page, TeX will have a hard time doing % good page breaking, for example.) However, I could not construct an % example where a page broke at this \penalty; if it happens in a real % document, then we can reconsider our strategy. \penalty9999 % % Back up by the size of the box, whether we did a page break or not. \kern -#1\mil % % Do not allow a page break right after this kern. \nobreak \fi } % @br forces paragraph break (and is undocumented). \let\br = \par % @page forces the start of a new page. % \def\page{\par\vfill\supereject} % @exdent text.... % outputs text on separate line in roman font, starting at standard page margin % This records the amount of indent in the innermost environment. % That's how much \exdent should take out. \newskip\exdentamount % This defn is used inside fill environments such as @defun. \parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break} % This defn is used inside nofill environments such as @example. \parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount \leftline{\hskip\leftskip{\rm#1}}}} % @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current % paragraph. For more general purposes, use the \margin insertion % class. WHICH is `l' or `r'. % \newskip\inmarginspacing \inmarginspacing=1cm \def\strutdepth{\dp\strutbox} % \def\doinmargin#1#2{\strut\vadjust{% \nobreak \kern-\strutdepth \vtop to \strutdepth{% \baselineskip=\strutdepth \vss % if you have multiple lines of stuff to put here, you'll need to % make the vbox yourself of the appropriate size. \ifx#1l% \llap{\ignorespaces #2\hskip\inmarginspacing}% \else \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% \fi \null }% }} \def\inleftmargin{\doinmargin l} \def\inrightmargin{\doinmargin r} % % @inmargin{TEXT [, RIGHT-TEXT]} % (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; % else use TEXT for both). % \def\inmargin#1{\parseinmargin #1,,\finish} \def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0 > 0pt \def\lefttext{#1}% have both texts \def\righttext{#2}% \else \def\lefttext{#1}% have only one text \def\righttext{#1}% \fi % \ifodd\pageno \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin \else \def\temp{\inleftmargin\lefttext}% \fi \temp } % @include file insert text of that file as input. % \def\include{\parseargusing\filenamecatcodes\includezzz} \def\includezzz#1{% \pushthisfilestack \def\thisfile{#1}% {% \makevalueexpandable \def\temp{\input #1 }% \expandafter }\temp \popthisfilestack } \def\filenamecatcodes{% \catcode`\\=\other \catcode`~=\other \catcode`^=\other \catcode`_=\other \catcode`|=\other \catcode`<=\other \catcode`>=\other \catcode`+=\other \catcode`-=\other } \def\pushthisfilestack{% \expandafter\pushthisfilestackX\popthisfilestack\StackTerm } \def\pushthisfilestackX{% \expandafter\pushthisfilestackY\thisfile\StackTerm } \def\pushthisfilestackY #1\StackTerm #2\StackTerm {% \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}% } \def\popthisfilestack{\errthisfilestackempty} \def\errthisfilestackempty{\errmessage{Internal error: the stack of filenames is empty.}} \def\thisfile{} % @center line % outputs that line, centered. % \parseargdef\center{% \ifhmode \let\next\centerH \else \let\next\centerV \fi \next{\hfil \ignorespaces#1\unskip \hfil}% } \def\centerH#1{% {% \hfil\break \advance\hsize by -\leftskip \advance\hsize by -\rightskip \line{#1}% \break }% } \def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}} % @sp n outputs n lines of vertical space \parseargdef\sp{\vskip #1\baselineskip} % @comment ...line which is ignored... % @c is the same as @comment % @ignore ... @end ignore is another way to write a comment \def\comment{\begingroup \catcode`\^^M=\other% \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% \commentxxx} {\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} \let\c=\comment % @paragraphindent NCHARS % We'll use ems for NCHARS, close enough. % NCHARS can also be the word `asis' or `none'. % We cannot feasibly implement @paragraphindent asis, though. % \def\asisword{asis} % no translation, these are keywords \def\noneword{none} % \parseargdef\paragraphindent{% \def\temp{#1}% \ifx\temp\asisword \else \ifx\temp\noneword \defaultparindent = 0pt \else \defaultparindent = #1em \fi \fi \parindent = \defaultparindent } % @exampleindent NCHARS % We'll use ems for NCHARS like @paragraphindent. % It seems @exampleindent asis isn't necessary, but % I preserve it to make it similar to @paragraphindent. \parseargdef\exampleindent{% \def\temp{#1}% \ifx\temp\asisword \else \ifx\temp\noneword \lispnarrowing = 0pt \else \lispnarrowing = #1em \fi \fi } % @firstparagraphindent WORD % If WORD is `none', then suppress indentation of the first paragraph % after a section heading. If WORD is `insert', then do indent at such % paragraphs. % % The paragraph indentation is suppressed or not by calling % \suppressfirstparagraphindent, which the sectioning commands do. % We switch the definition of this back and forth according to WORD. % By default, we suppress indentation. % \def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} \def\insertword{insert} % \parseargdef\firstparagraphindent{% \def\temp{#1}% \ifx\temp\noneword \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent \else\ifx\temp\insertword \let\suppressfirstparagraphindent = \relax \else \errhelp = \EMsimple \errmessage{Unknown @firstparagraphindent option `\temp'}% \fi\fi } % Here is how we actually suppress indentation. Redefine \everypar to % \kern backwards by \parindent, and then reset itself to empty. % % We also make \indent itself not actually do anything until the next % paragraph. % \gdef\dosuppressfirstparagraphindent{% \gdef\indent{% \restorefirstparagraphindent \indent }% \gdef\noindent{% \restorefirstparagraphindent \noindent }% \global\everypar = {% \kern -\parindent \restorefirstparagraphindent }% } \gdef\restorefirstparagraphindent{% \global \let \indent = \ptexindent \global \let \noindent = \ptexnoindent \global \everypar = {}% } % @asis just yields its argument. Used with @table, for example. % \def\asis#1{#1} % @math outputs its argument in math mode. % % One complication: _ usually means subscripts, but it could also mean % an actual _ character, as in @math{@var{some_variable} + 1}. So make % _ active, and distinguish by seeing if the current family is \slfam, % which is what @var uses. { \catcode\underChar = \active \gdef\mathunderscore{% \catcode\underChar=\active \def_{\ifnum\fam=\slfam \_\else\sb\fi}% } } % Another complication: we want \\ (and @\) to output a \ character. % FYI, plain.tex uses \\ as a temporary control sequence (why?), but % this is not advertised and we don't care. Texinfo does not % otherwise define @\. % % The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. \def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} % \def\math{% \tex \mathunderscore \let\\ = \mathbackslash \mathactive $\finishmath } \def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. % Some active characters (such as <) are spaced differently in math. % We have to reset their definitions in case the @math was an argument % to a command which sets the catcodes (such as @item or @section). % { \catcode`^ = \active \catcode`< = \active \catcode`> = \active \catcode`+ = \active \gdef\mathactive{% \let^ = \ptexhat \let< = \ptexless \let> = \ptexgtr \let+ = \ptexplus } } % @bullet and @minus need the same treatment as @math, just above. \def\bullet{$\ptexbullet$} \def\minus{$-$} % @dots{} outputs an ellipsis using the current font. % We do .5em per period so that it has the same spacing in a typewriter % font as three actual period characters. % \def\dots{% \leavevmode \hbox to 1.5em{% \hskip 0pt plus 0.25fil .\hfil.\hfil.% \hskip 0pt plus 0.5fil }% } % @enddots{} is an end-of-sentence ellipsis. % \def\enddots{% \dots \spacefactor=3000 } % @comma{} is so commas can be inserted into text without messing up % Texinfo's parsing. % \let\comma = , % @refill is a no-op. \let\refill=\relax % If working on a large document in chapters, it is convenient to % be able to disable indexing, cross-referencing, and contents, for test runs. % This is done with @novalidate (before @setfilename). % \newif\iflinks \linkstrue % by default we want the aux files. \let\novalidate = \linksfalse % @setfilename is done at the beginning of every texinfo file. % So open here the files we need to have open while reading the input. % This makes it possible to make a .fmt file for texinfo. \def\setfilename{% \fixbackslash % Turn off hack to swallow `\input texinfo'. \iflinks \tryauxfile % Open the new aux file. TeX will close it automatically at exit. \immediate\openout\auxfile=\jobname.aux \fi % \openindices needs to do some work in any case. \openindices \let\setfilename=\comment % Ignore extra @setfilename cmds. % % If texinfo.cnf is present on the system, read it. % Useful for site-wide @afourpaper, etc. \openin 1 texinfo.cnf \ifeof 1 \else \input texinfo.cnf \fi \closein 1 % \comment % Ignore the actual filename. } % Called from \setfilename. % \def\openindices{% \newindex{cp}% \newcodeindex{fn}% \newcodeindex{vr}% \newcodeindex{tp}% \newcodeindex{ky}% \newcodeindex{pg}% } % @bye. \outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} \message{pdf,} % adobe `portable' document format \newcount\tempnum \newcount\lnkcount \newtoks\filename \newcount\filenamelength \newcount\pgn \newtoks\toksA \newtoks\toksB \newtoks\toksC \newtoks\toksD \newbox\boxA \newcount\countA \newif\ifpdf \newif\ifpdfmakepagedest % when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 % can be set). So we test for \relax and 0 as well as \undefined, % borrowed from ifpdf.sty. \ifx\pdfoutput\undefined \else \ifx\pdfoutput\relax \else \ifcase\pdfoutput \else \pdftrue \fi \fi \fi % \ifpdf \input pdfcolor \pdfcatalog{/PageMode /UseOutlines}% \def\dopdfimage#1#2#3{% \def\imagewidth{#2}% \def\imageheight{#3}% % without \immediate, pdftex seg faults when the same image is % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) \ifnum\pdftexversion < 14 \immediate\pdfimage \else \immediate\pdfximage \fi \ifx\empty\imagewidth\else width \imagewidth \fi \ifx\empty\imageheight\else height \imageheight \fi \ifnum\pdftexversion<13 #1.pdf% \else {#1.pdf}% \fi \ifnum\pdftexversion < 14 \else \pdfrefximage \pdflastximage \fi} \def\pdfmkdest#1{{% % We have to set dummies so commands such as @code in a section title % aren't expanded. \atdummies \normalturnoffactive \pdfdest name{#1} xyz% }} \def\pdfmkpgn#1{#1} \let\linkcolor = \Blue % was Cyan, but that seems light? \def\endlink{\Black\pdfendlink} % Adding outlines to PDF; macros for calculating structure of outlines % come from Petr Olsak \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% \else \csname#1\endcsname \fi} \def\advancenumber#1{\tempnum=\expnumber{#1}\relax \advance\tempnum by 1 \expandafter\xdef\csname#1\endcsname{\the\tempnum}} % % #1 is the section text. #2 is the pdf expression for the number % of subentries (or empty, for subsubsections). #3 is the node % text, which might be empty if this toc entry had no % corresponding node. #4 is the page number. % \def\dopdfoutline#1#2#3#4{% % Generate a link to the node text if that exists; else, use the % page number. We could generate a destination for the section % text in the case where a section has no node, but it doesn't % seem worthwhile, since most documents are normally structured. \def\pdfoutlinedest{#3}% \ifx\pdfoutlinedest\empty \def\pdfoutlinedest{#4}\fi % \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{#1}% } % \def\pdfmakeoutlines{% \begingroup % Thanh's hack / proper braces in bookmarks \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace % % Read toc silently, to get counts of subentries for \pdfoutline. \def\numchapentry##1##2##3##4{% \def\thischapnum{##2}% \let\thissecnum\empty \let\thissubsecnum\empty }% \def\numsecentry##1##2##3##4{% \advancenumber{chap\thischapnum}% \def\thissecnum{##2}% \let\thissubsecnum\empty }% \def\numsubsecentry##1##2##3##4{% \advancenumber{sec\thissecnum}% \def\thissubsecnum{##2}% }% \def\numsubsubsecentry##1##2##3##4{% \advancenumber{subsec\thissubsecnum}% }% \let\thischapnum\empty \let\thissecnum\empty \let\thissubsecnum\empty % % use \def rather than \let here because we redefine \chapentry et % al. a second time, below. \def\appentry{\numchapentry}% \def\appsecentry{\numsecentry}% \def\appsubsecentry{\numsubsecentry}% \def\appsubsubsecentry{\numsubsubsecentry}% \def\unnchapentry{\numchapentry}% \def\unnsecentry{\numsecentry}% \def\unnsubsecentry{\numsubsecentry}% \def\unnsubsubsecentry{\numsubsubsecentry}% \input \jobname.toc % % Read toc second time, this time actually producing the outlines. % The `-' means take the \expnumber as the absolute number of % subentries, which we calculated on our first read of the .toc above. % % We use the node names as the destinations. \def\numchapentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% \def\numsecentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% \def\numsubsecentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% \def\numsubsubsecentry##1##2##3##4{% count is always zero \dopdfoutline{##1}{}{##3}{##4}}% % % PDF outlines are displayed using system fonts, instead of % document fonts. Therefore we cannot use special characters, % since the encoding is unknown. For example, the eogonek from % Latin 2 (0xea) gets translated to a | character. Info from % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. % % xx to do this right, we have to translate 8-bit characters to % their "best" equivalent, based on the @documentencoding. Right % now, I guess we'll just let the pdf reader have its way. \indexnofonts \turnoffactive \input \jobname.toc \endgroup } % \def\makelinks #1,{% \def\params{#1}\def\E{END}% \ifx\params\E \let\nextmakelinks=\relax \else \let\nextmakelinks=\makelinks \ifnum\lnkcount>0,\fi \picknum{#1}% \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{\the\pgn}}% \linkcolor #1% \advance\lnkcount by 1% \endlink \fi \nextmakelinks } \def\picknum#1{\expandafter\pn#1} \def\pn#1{% \def\p{#1}% \ifx\p\lbrace \let\nextpn=\ppn \else \let\nextpn=\ppnn \def\first{#1} \fi \nextpn } \def\ppn#1{\pgn=#1\gobble} \def\ppnn{\pgn=\first} \def\pdfmklnk#1{\lnkcount=0\makelinks #1,END,} \def\skipspaces#1{\def\PP{#1}\def\D{|}% \ifx\PP\D\let\nextsp\relax \else\let\nextsp\skipspaces \ifx\p\space\else\addtokens{\filename}{\PP}% \advance\filenamelength by 1 \fi \fi \nextsp} \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} \ifnum\pdftexversion < 14 \let \startlink \pdfannotlink \else \let \startlink \pdfstartlink \fi \def\pdfurl#1{% \begingroup \normalturnoffactive\def\@{@}% \makevalueexpandable \leavevmode\Red \startlink attr{/Border [0 0 0]}% user{/Subtype /Link /A << /S /URI /URI (#1) >>}% \endgroup} \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} \def\maketoks{% \expandafter\poptoks\the\toksA|ENDTOKS|\relax \ifx\first0\adn0 \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 \else \ifnum0=\countA\else\makelink\fi \ifx\first.\let\next=\done\else \let\next=\maketoks \addtokens{\toksB}{\the\toksD} \ifx\first,\addtokens{\toksB}{\space}\fi \fi \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \next} \def\makelink{\addtokens{\toksB}% {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} \def\pdflink#1{% \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} \linkcolor #1\endlink} \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} \else \let\pdfmkdest = \gobble \let\pdfurl = \gobble \let\endlink = \relax \let\linkcolor = \relax \let\pdfmakeoutlines = \relax \fi % \ifx\pdfoutput \message{fonts,} % Change the current font style to #1, remembering it in \curfontstyle. % For now, we do not accumulate font styles: @b{@i{foo}} prints foo in % italics, not bold italics. % \def\setfontstyle#1{% \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. \csname ten#1\endcsname % change the current font } % Select #1 fonts with the current style. % \def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname} \def\rm{\fam=0 \setfontstyle{rm}} \def\it{\fam=\itfam \setfontstyle{it}} \def\sl{\fam=\slfam \setfontstyle{sl}} \def\bf{\fam=\bffam \setfontstyle{bf}} \def\tt{\fam=\ttfam \setfontstyle{tt}} % Texinfo sort of supports the sans serif font style, which plain TeX does not. % So we set up a \sf. \newfam\sffam \def\sf{\fam=\sffam \setfontstyle{sf}} \let\li = \sf % Sometimes we call it \li, not \sf. % We don't need math for this font style. \def\ttsl{\setfontstyle{ttsl}} % Default leading. \newdimen\textleading \textleading = 13.2pt % Set the baselineskip to #1, and the lineskip and strut size % correspondingly. There is no deep meaning behind these magic numbers % used as factors; they just match (closely enough) what Knuth defined. % \def\lineskipfactor{.08333} \def\strutheightpercent{.70833} \def\strutdepthpercent {.29167} % \def\setleading#1{% \normalbaselineskip = #1\relax \normallineskip = \lineskipfactor\normalbaselineskip \normalbaselines \setbox\strutbox =\hbox{% \vrule width0pt height\strutheightpercent\baselineskip depth \strutdepthpercent \baselineskip }% } % Set the font macro #1 to the font named #2, adding on the % specified font prefix (normally `cm'). % #3 is the font's design size, #4 is a scale factor \def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} % Use cm as the default font prefix. % To specify the font prefix, you must define \fontprefix % before you read in texinfo.tex. \ifx\fontprefix\undefined \def\fontprefix{cm} \fi % Support font families that don't use the same naming scheme as CM. \def\rmshape{r} \def\rmbshape{bx} %where the normal face is bold \def\bfshape{b} \def\bxshape{bx} \def\ttshape{tt} \def\ttbshape{tt} \def\ttslshape{sltt} \def\itshape{ti} \def\itbshape{bxti} \def\slshape{sl} \def\slbshape{bxsl} \def\sfshape{ss} \def\sfbshape{ss} \def\scshape{csc} \def\scbshape{csc} % Text fonts (11.2pt, magstep1). \newcount\mainmagstep \ifx\bigger\relax % not really supported. \mainmagstep=\magstep1 \setfont\textrm\rmshape{12}{1000} \setfont\texttt\ttshape{12}{1000} \else \mainmagstep=\magstephalf \setfont\textrm\rmshape{10}{\mainmagstep} \setfont\texttt\ttshape{10}{\mainmagstep} \fi \setfont\textbf\bfshape{10}{\mainmagstep} \setfont\textit\itshape{10}{\mainmagstep} \setfont\textsl\slshape{10}{\mainmagstep} \setfont\textsf\sfshape{10}{\mainmagstep} \setfont\textsc\scshape{10}{\mainmagstep} \setfont\textttsl\ttslshape{10}{\mainmagstep} \font\texti=cmmi10 scaled \mainmagstep \font\textsy=cmsy10 scaled \mainmagstep % A few fonts for @defun names and args. \setfont\defbf\bfshape{10}{\magstep1} \setfont\deftt\ttshape{10}{\magstep1} \setfont\defttsl\ttslshape{10}{\magstep1} \def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} % Fonts for indices, footnotes, small examples (9pt). \setfont\smallrm\rmshape{9}{1000} \setfont\smalltt\ttshape{9}{1000} \setfont\smallbf\bfshape{10}{900} \setfont\smallit\itshape{9}{1000} \setfont\smallsl\slshape{9}{1000} \setfont\smallsf\sfshape{9}{1000} \setfont\smallsc\scshape{10}{900} \setfont\smallttsl\ttslshape{10}{900} \font\smalli=cmmi9 \font\smallsy=cmsy9 % Fonts for small examples (8pt). \setfont\smallerrm\rmshape{8}{1000} \setfont\smallertt\ttshape{8}{1000} \setfont\smallerbf\bfshape{10}{800} \setfont\smallerit\itshape{8}{1000} \setfont\smallersl\slshape{8}{1000} \setfont\smallersf\sfshape{8}{1000} \setfont\smallersc\scshape{10}{800} \setfont\smallerttsl\ttslshape{10}{800} \font\smalleri=cmmi8 \font\smallersy=cmsy8 % Fonts for title page (20.4pt): \setfont\titlerm\rmbshape{12}{\magstep3} \setfont\titleit\itbshape{10}{\magstep4} \setfont\titlesl\slbshape{10}{\magstep4} \setfont\titlett\ttbshape{12}{\magstep3} \setfont\titlettsl\ttslshape{10}{\magstep4} \setfont\titlesf\sfbshape{17}{\magstep1} \let\titlebf=\titlerm \setfont\titlesc\scbshape{10}{\magstep4} \font\titlei=cmmi12 scaled \magstep3 \font\titlesy=cmsy10 scaled \magstep4 \def\authorrm{\secrm} \def\authortt{\sectt} % Chapter (and unnumbered) fonts (17.28pt). \setfont\chaprm\rmbshape{12}{\magstep2} \setfont\chapit\itbshape{10}{\magstep3} \setfont\chapsl\slbshape{10}{\magstep3} \setfont\chaptt\ttbshape{12}{\magstep2} \setfont\chapttsl\ttslshape{10}{\magstep3} \setfont\chapsf\sfbshape{17}{1000} \let\chapbf=\chaprm \setfont\chapsc\scbshape{10}{\magstep3} \font\chapi=cmmi12 scaled \magstep2 \font\chapsy=cmsy10 scaled \magstep3 % Section fonts (14.4pt). \setfont\secrm\rmbshape{12}{\magstep1} \setfont\secit\itbshape{10}{\magstep2} \setfont\secsl\slbshape{10}{\magstep2} \setfont\sectt\ttbshape{12}{\magstep1} \setfont\secttsl\ttslshape{10}{\magstep2} \setfont\secsf\sfbshape{12}{\magstep1} \let\secbf\secrm \setfont\secsc\scbshape{10}{\magstep2} \font\seci=cmmi12 scaled \magstep1 \font\secsy=cmsy10 scaled \magstep2 % Subsection fonts (13.15pt). \setfont\ssecrm\rmbshape{12}{\magstephalf} \setfont\ssecit\itbshape{10}{1315} \setfont\ssecsl\slbshape{10}{1315} \setfont\ssectt\ttbshape{12}{\magstephalf} \setfont\ssecttsl\ttslshape{10}{1315} \setfont\ssecsf\sfbshape{12}{\magstephalf} \let\ssecbf\ssecrm \setfont\ssecsc\scbshape{10}{1315} \font\sseci=cmmi12 scaled \magstephalf \font\ssecsy=cmsy10 scaled 1315 % Reduced fonts for @acro in text (10pt). \setfont\reducedrm\rmshape{10}{1000} \setfont\reducedtt\ttshape{10}{1000} \setfont\reducedbf\bfshape{10}{1000} \setfont\reducedit\itshape{10}{1000} \setfont\reducedsl\slshape{10}{1000} \setfont\reducedsf\sfshape{10}{1000} \setfont\reducedsc\scshape{10}{1000} \setfont\reducedttsl\ttslshape{10}{1000} \font\reducedi=cmmi10 \font\reducedsy=cmsy10 % In order for the font changes to affect most math symbols and letters, % we have to define the \textfont of the standard families. Since % texinfo doesn't allow for producing subscripts and superscripts except % in the main text, we don't bother to reset \scriptfont and % \scriptscriptfont (which would also require loading a lot more fonts). % \def\resetmathfonts{% \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf \textfont\ttfam=\tentt \textfont\sffam=\tensf } % The font-changing commands redefine the meanings of \tenSTYLE, instead % of just \STYLE. We do this because \STYLE needs to also set the % current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire % \tenSTYLE to set the current font. % % Each font-changing command also sets the names \lsize (one size lower) % and \lllsize (three sizes lower). These relative commands are used in % the LaTeX logo and acronyms. % % This all needs generalizing, badly. % \def\textfonts{% \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl \def\lsize{reduced}\def\lllsize{smaller}% \resetmathfonts \setleading{\textleading}} \def\titlefonts{% \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy \let\tenttsl=\titlettsl \def\lsize{chap}\def\lllsize{subsec}% \resetmathfonts \setleading{25pt}} \def\titlefont#1{{\titlefonts\rm #1}} \def\chapfonts{% \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl \def\lsize{sec}\def\lllsize{text}% \resetmathfonts \setleading{19pt}} \def\secfonts{% \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl \def\lsize{subsec}\def\lllsize{reduced}% \resetmathfonts \setleading{16pt}} \def\subsecfonts{% \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl \def\lsize{text}\def\lllsize{small}% \resetmathfonts \setleading{15pt}} \let\subsubsecfonts = \subsecfonts \def\reducedfonts{% \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy \let\tenttsl=\reducedttsl \def\lsize{small}\def\lllsize{smaller}% \resetmathfonts \setleading{10.5pt}} \def\smallfonts{% \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy \let\tenttsl=\smallttsl \def\lsize{smaller}\def\lllsize{smaller}% \resetmathfonts \setleading{10.5pt}} \def\smallerfonts{% \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy \let\tenttsl=\smallerttsl \def\lsize{smaller}\def\lllsize{smaller}% \resetmathfonts \setleading{9.5pt}} % Set the fonts to use with the @small... environments. \let\smallexamplefonts = \smallfonts % About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample % can fit this many characters: % 8.5x11=86 smallbook=72 a4=90 a5=69 % If we use \scriptfonts (8pt), then we can fit this many characters: % 8.5x11=90+ smallbook=80 a4=90+ a5=77 % For me, subjectively, the few extra characters that fit aren't worth % the additional smallness of 8pt. So I'm making the default 9pt. % % By the way, for comparison, here's what fits with @example (10pt): % 8.5x11=71 smallbook=60 a4=75 a5=58 % % I wish the USA used A4 paper. % --karl, 24jan03. % Set up the default fonts, so we can use them for creating boxes. % \textfonts \rm % Define these so they can be easily changed for other fonts. \def\angleleft{$\langle$} \def\angleright{$\rangle$} % Count depth in font-changes, for error checks \newcount\fontdepth \fontdepth=0 % Fonts for short table of contents. \setfont\shortcontrm\rmshape{12}{1000} \setfont\shortcontbf\bfshape{10}{\magstep1} % no cmb12 \setfont\shortcontsl\slshape{12}{1000} \setfont\shortconttt\ttshape{12}{1000} %% Add scribe-like font environments, plus @l for inline lisp (usually sans %% serif) and @ii for TeX italic % \smartitalic{ARG} outputs arg in italics, followed by an italic correction % unless the following character is such as not to need one. \def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else \ptexslash\fi\fi\fi} \def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx} \def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx} % like \smartslanted except unconditionally uses \ttsl. % @var is set to this for defun arguments. \def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx} % like \smartslanted except unconditionally use \sl. We never want % ttsl for book titles, do we? \def\cite#1{{\sl #1}\futurelet\next\smartitalicx} \let\i=\smartitalic \let\slanted=\smartslanted \let\var=\smartslanted \let\dfn=\smartslanted \let\emph=\smartitalic \def\b#1{{\bf #1}} \let\strong=\b % We can't just use \exhyphenpenalty, because that only has effect at % the end of a paragraph. Restore normal hyphenation at the end of the % group within which \nohyphenation is presumably called. % \def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} \def\restorehyphenation{\hyphenchar\font = `- } % Set sfcode to normal for the chars that usually have another value. % Can't use plain's \frenchspacing because it uses the `\x notation, and % sometimes \x has an active definition that messes things up. % \catcode`@=11 \def\frenchspacing{% \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m } \catcode`@=\other \def\t#1{% {\tt \rawbackslash \frenchspacing #1}% \null } \def\samp#1{`\tclose{#1}'\null} \setfont\keyrm\rmshape{8}{1000} \font\keysy=cmsy9 \def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% \vbox{\hrule\kern-0.4pt \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% \kern-0.4pt\hrule}% \kern-.06em\raise0.4pt\hbox{\angleright}}}} % The old definition, with no lozenge: %\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} \def\ctrl #1{{\tt \rawbackslash \hat}#1} % @file, @option are the same as @samp. \let\file=\samp \let\option=\samp % @code is a modification of @t, % which makes spaces the same size as normal in the surrounding text. \def\tclose#1{% {% % Change normal interword space to be same as for the current font. \spaceskip = \fontdimen2\font % % Switch to typewriter. \tt % % But `\ ' produces the large typewriter interword space. \def\ {{\spaceskip = 0pt{} }}% % % Turn off hyphenation. \nohyphenation % \rawbackslash \frenchspacing #1% }% \null } % We *must* turn on hyphenation at `-' and `_' in @code. % Otherwise, it is too hard to avoid overfull hboxes % in the Emacs manual, the Library manual, etc. % Unfortunately, TeX uses one parameter (\hyphenchar) to control % both hyphenation at - and hyphenation within words. % We must therefore turn them both off (\tclose does that) % and arrange explicitly to hyphenate at a dash. % -- rms. { \catcode`\-=\active \catcode`\_=\active % \global\def\code{\begingroup \catcode`\-=\active \let-\codedash \catcode`\_=\active \let_\codeunder \codex } } \def\realdash{-} \def\codedash{-\discretionary{}{}{}} \def\codeunder{% % this is all so @math{@code{var_name}+1} can work. In math mode, _ % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) % will therefore expand the active definition of _, which is us % (inside @code that is), therefore an endless loop. \ifusingtt{\ifmmode \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. \else\normalunderscore \fi \discretionary{}{}{}}% {\_}% } \def\codex #1{\tclose{#1}\endgroup} % @kbd is like @code, except that if the argument is just one @key command, % then @kbd has no effect. % @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), % `example' (@kbd uses ttsl only inside of @example and friends), % or `code' (@kbd uses normal tty font always). \parseargdef\kbdinputstyle{% \def\arg{#1}% \ifx\arg\worddistinct \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% \else\ifx\arg\wordexample \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% \else\ifx\arg\wordcode \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% \else \errhelp = \EMsimple \errmessage{Unknown @kbdinputstyle option `\arg'}% \fi\fi\fi } \def\worddistinct{distinct} \def\wordexample{example} \def\wordcode{code} % Default is `distinct.' \kbdinputstyle distinct \def\xkey{\key} \def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% \ifx\one\xkey\ifx\threex\three \key{#2}% \else{\tclose{\kbdfont\look}}\fi \else{\tclose{\kbdfont\look}}\fi} % For @indicateurl, @env, @command quotes seem unnecessary, so use \code. \let\indicateurl=\code \let\env=\code \let\command=\code % @uref (abbreviation for `urlref') takes an optional (comma-separated) % second argument specifying the text to display and an optional third % arg as text to display instead of (rather than in addition to) the url % itself. First (mandatory) arg is the url. Perhaps eventually put in % a hypertex \special here. % \def\uref#1{\douref #1,,,\finish} \def\douref#1,#2,#3,#4\finish{\begingroup \unsepspaces \pdfurl{#1}% \setbox0 = \hbox{\ignorespaces #3}% \ifdim\wd0 > 0pt \unhbox0 % third arg given, show only that \else \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0 > 0pt \ifpdf \unhbox0 % PDF: 2nd arg given, show only it \else \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url \fi \else \code{#1}% only url given, so show it \fi \fi \endlink \endgroup} % @url synonym for @uref, since that's how everyone uses it. % \let\url=\uref % rms does not like angle brackets --karl, 17may97. % So now @email is just like @uref, unless we are pdf. % %\def\email#1{\angleleft{\tt #1}\angleright} \ifpdf \def\email#1{\doemail#1,,\finish} \def\doemail#1,#2,#3\finish{\begingroup \unsepspaces \pdfurl{mailto:#1}% \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi \endlink \endgroup} \else \let\email=\uref \fi % Check if we are currently using a typewriter font. Since all the % Computer Modern typewriter fonts have zero interword stretch (and % shrink), and it is reasonable to expect all typewriter fonts to have % this property, we can check that font parameter. % \def\ifmonospace{\ifdim\fontdimen3\font=0pt } % Typeset a dimension, e.g., `in' or `pt'. The only reason for the % argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. % \def\dmn#1{\thinspace #1} \def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} % @l was never documented to mean ``switch to the Lisp font'', % and it is not used as such in any manual I can find. We need it for % Polish suppressed-l. --karl, 22sep96. %\def\l#1{{\li #1}\null} % Explicit font changes: @r, @sc, undocumented @ii. \def\r#1{{\rm #1}} % roman font \def\sc#1{{\smallcaps#1}} % smallcaps font \def\ii#1{{\it #1}} % italic font % @acronym for "FBI", "NATO", and the like. % We print this one point size smaller, since it's intended for % all-uppercase. % \def\acronym#1{\doacronym #1,,\finish} \def\doacronym#1,#2,#3\finish{% {\selectfonts\lsize #1}% \def\temp{#2}% \ifx\temp\empty \else \space ({\unsepspaces \ignorespaces \temp \unskip})% \fi } % @abbr for "Comput. J." and the like. % No font change, but don't do end-of-sentence spacing. % \def\abbr#1{\doabbr #1,,\finish} \def\doabbr#1,#2,#3\finish{% {\frenchspacing #1}% \def\temp{#2}% \ifx\temp\empty \else \space ({\unsepspaces \ignorespaces \temp \unskip})% \fi } % @pounds{} is a sterling sign, which Knuth put in the CM italic font. % \def\pounds{{\it\$}} % @registeredsymbol - R in a circle. The font for the R should really % be smaller yet, but lllsize is the best we can do for now. % Adapted from the plain.tex definition of \copyright. % \def\registeredsymbol{% $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}% \hfil\crcr\Orb}}% }$% } % Laurent Siebenmann reports \Orb undefined with: % Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38 % so we'll define it if necessary. % \ifx\Orb\undefined \def\Orb{\mathhexbox20D} \fi \message{page headings,} \newskip\titlepagetopglue \titlepagetopglue = 1.5in \newskip\titlepagebottomglue \titlepagebottomglue = 2pc % First the title page. Must do @settitle before @titlepage. \newif\ifseenauthor \newif\iffinishedtitlepage % Do an implicit @contents or @shortcontents after @end titlepage if the % user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. % \newif\ifsetcontentsaftertitlepage \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue \newif\ifsetshortcontentsaftertitlepage \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue \parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% \endgroup\page\hbox{}\page} \envdef\titlepage{% % Open one extra group, as we want to close it in the middle of \Etitlepage. \begingroup \parindent=0pt \textfonts % Leave some space at the very top of the page. \vglue\titlepagetopglue % No rule at page bottom unless we print one at the top with @title. \finishedtitlepagetrue % % Most title ``pages'' are actually two pages long, with space % at the top of the second. We don't want the ragged left on the second. \let\oldpage = \page \def\page{% \iffinishedtitlepage\else \finishtitlepage \fi \let\page = \oldpage \page \null }% } \def\Etitlepage{% \iffinishedtitlepage\else \finishtitlepage \fi % It is important to do the page break before ending the group, % because the headline and footline are only empty inside the group. % If we use the new definition of \page, we always get a blank page % after the title page, which we certainly don't want. \oldpage \endgroup % % Need this before the \...aftertitlepage checks so that if they are % in effect the toc pages will come out with page numbers. \HEADINGSon % % If they want short, they certainly want long too. \ifsetshortcontentsaftertitlepage \shortcontents \contents \global\let\shortcontents = \relax \global\let\contents = \relax \fi % \ifsetcontentsaftertitlepage \contents \global\let\contents = \relax \global\let\shortcontents = \relax \fi } \def\finishtitlepage{% \vskip4pt \hrule height 2pt width \hsize \vskip\titlepagebottomglue \finishedtitlepagetrue } %%% Macros to be used within @titlepage: \let\subtitlerm=\tenrm \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines \let\tt=\authortt} \parseargdef\title{% \checkenv\titlepage \leftline{\titlefonts\rm #1} % print a rule at the page bottom also. \finishedtitlepagefalse \vskip4pt \hrule height 4pt width \hsize \vskip4pt } \parseargdef\subtitle{% \checkenv\titlepage {\subtitlefont \rightline{#1}}% } % @author should come last, but may come many times. % It can also be used inside @quotation. % \parseargdef\author{% \def\temp{\quotation}% \ifx\thisenv\temp \def\quotationauthor{#1}% printed in \Equotation. \else \checkenv\titlepage \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi {\authorfont \leftline{#1}}% \fi } %%% Set up page headings and footings. \let\thispage=\folio \newtoks\evenheadline % headline on even pages \newtoks\oddheadline % headline on odd pages \newtoks\evenfootline % footline on even pages \newtoks\oddfootline % footline on odd pages % Now make TeX use those variables \headline={{\textfonts\rm \ifodd\pageno \the\oddheadline \else \the\evenheadline \fi}} \footline={{\textfonts\rm \ifodd\pageno \the\oddfootline \else \the\evenfootline \fi}\HEADINGShook} \let\HEADINGShook=\relax % Commands to set those variables. % For example, this is what @headings on does % @evenheading @thistitle|@thispage|@thischapter % @oddheading @thischapter|@thispage|@thistitle % @evenfooting @thisfile|| % @oddfooting ||@thisfile \def\evenheading{\parsearg\evenheadingxxx} \def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} \def\evenheadingyyy #1\|#2\|#3\|#4\finish{% \global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \def\oddheading{\parsearg\oddheadingxxx} \def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} \def\oddheadingyyy #1\|#2\|#3\|#4\finish{% \global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% \def\evenfooting{\parsearg\evenfootingxxx} \def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish} \def\evenfootingyyy #1\|#2\|#3\|#4\finish{% \global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \def\oddfooting{\parsearg\oddfootingxxx} \def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish} \def\oddfootingyyy #1\|#2\|#3\|#4\finish{% \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% % % Leave some space for the footline. Hopefully ok to assume % @evenfooting will not be used by itself. \global\advance\pageheight by -\baselineskip \global\advance\vsize by -\baselineskip } \parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} % @headings double turns headings on for double-sided printing. % @headings single turns headings on for single-sided printing. % @headings off turns them off. % @headings on same as @headings double, retained for compatibility. % @headings after turns on double-sided headings after this page. % @headings doubleafter turns on double-sided headings after this page. % @headings singleafter turns on single-sided headings after this page. % By default, they are off at the start of a document, % and turned `on' after @end titlepage. \def\headings #1 {\csname HEADINGS#1\endcsname} \def\HEADINGSoff{% \global\evenheadline={\hfil} \global\evenfootline={\hfil} \global\oddheadline={\hfil} \global\oddfootline={\hfil}} \HEADINGSoff % When we turn headings on, set the page number to 1. % For double-sided printing, put current file name in lower left corner, % chapter name on inside top of right hand pages, document % title on inside top of left hand pages, and page numbers on outside top % edge of all pages. \def\HEADINGSdouble{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } \let\contentsalignmacro = \chappager % For single-sided printing, chapter title goes across top left of page, % page number on top right. \def\HEADINGSsingle{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\thischapter\hfil\folio}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chappager } \def\HEADINGSon{\HEADINGSdouble} \def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} \let\HEADINGSdoubleafter=\HEADINGSafter \def\HEADINGSdoublex{% \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } \def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} \def\HEADINGSsinglex{% \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\thischapter\hfil\folio}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chappager } % Subroutines used in generating headings % This produces Day Month Year style of output. % Only define if not already defined, in case a txi-??.tex file has set % up a different format (e.g., txi-cs.tex does this). \ifx\today\undefined \def\today{% \number\day\space \ifcase\month \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec \fi \space\number\year} \fi % @settitle line... specifies the title of the document, for headings. % It generates no output of its own. \def\thistitle{\putwordNoTitle} \def\settitle{\parsearg{\gdef\thistitle}} \message{tables,} % Tables -- @table, @ftable, @vtable, @item(x). % default indentation of table text \newdimen\tableindent \tableindent=.8in % default indentation of @itemize and @enumerate text \newdimen\itemindent \itemindent=.3in % margin between end of table item and start of table text. \newdimen\itemmargin \itemmargin=.1in % used internally for \itemindent minus \itemmargin \newdimen\itemmax % Note @table, @ftable, and @vtable define @item, @itemx, etc., with % these defs. % They also define \itemindex % to index the item name in whatever manner is desired (perhaps none). \newif\ifitemxneedsnegativevskip \def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} \def\internalBitem{\smallbreak \parsearg\itemzzz} \def\internalBitemx{\itemxpar \parsearg\itemzzz} \def\itemzzz #1{\begingroup % \advance\hsize by -\rightskip \advance\hsize by -\tableindent \setbox0=\hbox{\itemindicate{#1}}% \itemindex{#1}% \nobreak % This prevents a break before @itemx. % % If the item text does not fit in the space we have, put it on a line % by itself, and do not allow a page break either before or after that % line. We do not start a paragraph here because then if the next % command is, e.g., @kindex, the whatsit would get put into the % horizontal list on a line by itself, resulting in extra blank space. \ifdim \wd0>\itemmax % % Make this a paragraph so we get the \parskip glue and wrapping, % but leave it ragged-right. \begingroup \advance\leftskip by-\tableindent \advance\hsize by\tableindent \advance\rightskip by0pt plus1fil \leavevmode\unhbox0\par \endgroup % % We're going to be starting a paragraph, but we don't want the % \parskip glue -- logically it's part of the @item we just started. \nobreak \vskip-\parskip % % Stop a page break at the \parskip glue coming up. However, if % what follows is an environment such as @example, there will be no % \parskip glue; then the negative vskip we just inserted would % cause the example and the item to crash together. So we use this % bizarre value of 10001 as a signal to \aboveenvbreak to insert % \parskip glue after all. Section titles are handled this way also. % \penalty 10001 \endgroup \itemxneedsnegativevskipfalse \else % The item text fits into the space. Start a paragraph, so that the % following text (if any) will end up on the same line. \noindent % Do this with kerns and \unhbox so that if there is a footnote in % the item text, it can migrate to the main vertical list and % eventually be printed. \nobreak\kern-\tableindent \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 \unhbox0 \nobreak\kern\dimen0 \endgroup \itemxneedsnegativevskiptrue \fi } \def\item{\errmessage{@item while not in a list environment}} \def\itemx{\errmessage{@itemx while not in a list environment}} % @table, @ftable, @vtable. \envdef\table{% \let\itemindex\gobble \tablex } \envdef\ftable{% \def\itemindex ##1{\doind {fn}{\code{##1}}}% \tablex } \envdef\vtable{% \def\itemindex ##1{\doind {vr}{\code{##1}}}% \tablex } \def\tablex#1{% \def\itemindicate{#1}% \parsearg\tabley } \def\tabley#1{% {% \makevalueexpandable \edef\temp{\noexpand\tablez #1\space\space\space}% \expandafter }\temp \endtablez } \def\tablez #1 #2 #3 #4\endtablez{% \aboveenvbreak \ifnum 0#1>0 \advance \leftskip by #1\mil \fi \ifnum 0#2>0 \tableindent=#2\mil \fi \ifnum 0#3>0 \advance \rightskip by #3\mil \fi \itemmax=\tableindent \advance \itemmax by -\itemmargin \advance \leftskip by \tableindent \exdentamount=\tableindent \parindent = 0pt \parskip = \smallskipamount \ifdim \parskip=0pt \parskip=2pt \fi \let\item = \internalBitem \let\itemx = \internalBitemx } \def\Etable{\endgraf\afterenvbreak} \let\Eftable\Etable \let\Evtable\Etable \let\Eitemize\Etable \let\Eenumerate\Etable % This is the counter used by @enumerate, which is really @itemize \newcount \itemno \envdef\itemize{\parsearg\doitemize} \def\doitemize#1{% \aboveenvbreak \itemmax=\itemindent \advance\itemmax by -\itemmargin \advance\leftskip by \itemindent \exdentamount=\itemindent \parindent=0pt \parskip=\smallskipamount \ifdim\parskip=0pt \parskip=2pt \fi \def\itemcontents{#1}% % @itemize with no arg is equivalent to @itemize @bullet. \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi \let\item=\itemizeitem } % Definition of @item while inside @itemize and @enumerate. % \def\itemizeitem{% \advance\itemno by 1 % for enumerations {\let\par=\endgraf \smallbreak}% reasonable place to break {% % If the document has an @itemize directly after a section title, a % \nobreak will be last on the list, and \sectionheading will have % done a \vskip-\parskip. In that case, we don't want to zero % parskip, or the item text will crash with the heading. On the % other hand, when there is normal text preceding the item (as there % usually is), we do want to zero parskip, or there would be too much % space. In that case, we won't have a \nobreak before. At least % that's the theory. \ifnum\lastpenalty<10000 \parskip=0in \fi \noindent \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% \vadjust{\penalty 1200}}% not good to break after first line of item. \flushcr } % \splitoff TOKENS\endmark defines \first to be the first token in % TOKENS, and \rest to be the remainder. % \def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% % Allow an optional argument of an uppercase letter, lowercase letter, % or number, to specify the first label in the enumerated list. No % argument is the same as `1'. % \envparseargdef\enumerate{\enumeratey #1 \endenumeratey} \def\enumeratey #1 #2\endenumeratey{% % If we were given no argument, pretend we were given `1'. \def\thearg{#1}% \ifx\thearg\empty \def\thearg{1}\fi % % Detect if the argument is a single token. If so, it might be a % letter. Otherwise, the only valid thing it can be is a number. % (We will always have one token, because of the test we just made. % This is a good thing, since \splitoff doesn't work given nothing at % all -- the first parameter is undelimited.) \expandafter\splitoff\thearg\endmark \ifx\rest\empty % Only one token in the argument. It could still be anything. % A ``lowercase letter'' is one whose \lccode is nonzero. % An ``uppercase letter'' is one whose \lccode is both nonzero, and % not equal to itself. % Otherwise, we assume it's a number. % % We need the \relax at the end of the \ifnum lines to stop TeX from % continuing to look for a . % \ifnum\lccode\expandafter`\thearg=0\relax \numericenumerate % a number (we hope) \else % It's a letter. \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax \lowercaseenumerate % lowercase letter \else \uppercaseenumerate % uppercase letter \fi \fi \else % Multiple tokens in the argument. We hope it's a number. \numericenumerate \fi } % An @enumerate whose labels are integers. The starting integer is % given in \thearg. % \def\numericenumerate{% \itemno = \thearg \startenumeration{\the\itemno}% } % The starting (lowercase) letter is in \thearg. \def\lowercaseenumerate{% \itemno = \expandafter`\thearg \startenumeration{% % Be sure we're not beyond the end of the alphabet. \ifnum\itemno=0 \errmessage{No more lowercase letters in @enumerate; get a bigger alphabet}% \fi \char\lccode\itemno }% } % The starting (uppercase) letter is in \thearg. \def\uppercaseenumerate{% \itemno = \expandafter`\thearg \startenumeration{% % Be sure we're not beyond the end of the alphabet. \ifnum\itemno=0 \errmessage{No more uppercase letters in @enumerate; get a bigger alphabet} \fi \char\uccode\itemno }% } % Call \doitemize, adding a period to the first argument and supplying the % common last two arguments. Also subtract one from the initial value in % \itemno, since @item increments \itemno. % \def\startenumeration#1{% \advance\itemno by -1 \doitemize{#1.}\flushcr } % @alphaenumerate and @capsenumerate are abbreviations for giving an arg % to @enumerate. % \def\alphaenumerate{\enumerate{a}} \def\capsenumerate{\enumerate{A}} \def\Ealphaenumerate{\Eenumerate} \def\Ecapsenumerate{\Eenumerate} % @multitable macros % Amy Hendrickson, 8/18/94, 3/6/96 % % @multitable ... @end multitable will make as many columns as desired. % Contents of each column will wrap at width given in preamble. Width % can be specified either with sample text given in a template line, % or in percent of \hsize, the current width of text on page. % Table can continue over pages but will only break between lines. % To make preamble: % % Either define widths of columns in terms of percent of \hsize: % @multitable @columnfractions .25 .3 .45 % @item ... % % Numbers following @columnfractions are the percent of the total % current hsize to be used for each column. You may use as many % columns as desired. % Or use a template: % @multitable {Column 1 template} {Column 2 template} {Column 3 template} % @item ... % using the widest term desired in each column. % Each new table line starts with @item, each subsequent new column % starts with @tab. Empty columns may be produced by supplying @tab's % with nothing between them for as many times as empty columns are needed, % ie, @tab@tab@tab will produce two empty columns. % @item, @tab do not need to be on their own lines, but it will not hurt % if they are. % Sample multitable: % @multitable {Column 1 template} {Column 2 template} {Column 3 template} % @item first col stuff @tab second col stuff @tab third col % @item % first col stuff % @tab % second col stuff % @tab % third col % @item first col stuff @tab second col stuff % @tab Many paragraphs of text may be used in any column. % % They will wrap at the width determined by the template. % @item@tab@tab This will be in third column. % @end multitable % Default dimensions may be reset by user. % @multitableparskip is vertical space between paragraphs in table. % @multitableparindent is paragraph indent in table. % @multitablecolmargin is horizontal space to be left between columns. % @multitablelinespace is space to leave between table items, baseline % to baseline. % 0pt means it depends on current normal line spacing. % \newskip\multitableparskip \newskip\multitableparindent \newdimen\multitablecolspace \newskip\multitablelinespace \multitableparskip=0pt \multitableparindent=6pt \multitablecolspace=12pt \multitablelinespace=0pt % Macros used to set up halign preamble: % \let\endsetuptable\relax \def\xendsetuptable{\endsetuptable} \let\columnfractions\relax \def\xcolumnfractions{\columnfractions} \newif\ifsetpercent % #1 is the @columnfraction, usually a decimal number like .5, but might % be just 1. We just use it, whatever it is. % \def\pickupwholefraction#1 {% \global\advance\colcount by 1 \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}% \setuptable } \newcount\colcount \def\setuptable#1{% \def\firstarg{#1}% \ifx\firstarg\xendsetuptable \let\go = \relax \else \ifx\firstarg\xcolumnfractions \global\setpercenttrue \else \ifsetpercent \let\go\pickupwholefraction \else \global\advance\colcount by 1 \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a % separator; typically that is always in the input, anyway. \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% \fi \fi \ifx\go\pickupwholefraction % Put the argument back for the \pickupwholefraction call, so % we'll always have a period there to be parsed. \def\go{\pickupwholefraction#1}% \else \let\go = \setuptable \fi% \fi \go } % multitable-only commands. % % @headitem starts a heading row, which we typeset in bold. % Assignments have to be global since we are inside the implicit group % of an alignment entry. Note that \everycr resets \everytab. \def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}% % % A \tab used to include \hskip1sp. But then the space in a template % line is not enough. That is bad. So let's go back to just `&' until % we encounter the problem it was intended to solve again. % --karl, nathan@acm.org, 20apr99. \def\tab{\checkenv\multitable &\the\everytab}% % @multitable ... @end multitable definitions: % \newtoks\everytab % insert after every tab. % \envdef\multitable{% \vskip\parskip \startsavinginserts % % @item within a multitable starts a normal row. \let\item\crcr % \tolerance=9500 \hbadness=9500 \setmultitablespacing \parskip=\multitableparskip \parindent=\multitableparindent \overfullrule=0pt \global\colcount=0 % \everycr = {% \noalign{% \global\everytab={}% \global\colcount=0 % Reset the column counter. % Check for saved footnotes, etc. \checkinserts % Keeps underfull box messages off when table breaks over pages. %\filbreak % Maybe so, but it also creates really weird page breaks when the % table breaks over pages. Wouldn't \vfil be better? Wait until the % problem manifests itself, so it can be fixed for real --karl. }% }% % \parsearg\domultitable } \def\domultitable#1{% % To parse everything between @multitable and @item: \setuptable#1 \endsetuptable % % This preamble sets up a generic column definition, which will % be used as many times as user calls for columns. % \vtop will set a single line and will also let text wrap and % continue for many paragraphs if desired. \halign\bgroup &% \global\advance\colcount by 1 \multistrut \vtop{% % Use the current \colcount to find the correct column width: \hsize=\expandafter\csname col\the\colcount\endcsname % % In order to keep entries from bumping into each other % we will add a \leftskip of \multitablecolspace to all columns after % the first one. % % If a template has been used, we will add \multitablecolspace % to the width of each template entry. % % If the user has set preamble in terms of percent of \hsize we will % use that dimension as the width of the column, and the \leftskip % will keep entries from bumping into each other. Table will start at % left margin and final column will justify at right margin. % % Make sure we don't inherit \rightskip from the outer environment. \rightskip=0pt \ifnum\colcount=1 % The first column will be indented with the surrounding text. \advance\hsize by\leftskip \else \ifsetpercent \else % If user has not set preamble in terms of percent of \hsize % we will advance \hsize by \multitablecolspace. \advance\hsize by \multitablecolspace \fi % In either case we will make \leftskip=\multitablecolspace: \leftskip=\multitablecolspace \fi % Ignoring space at the beginning and end avoids an occasional spurious % blank line, when TeX decides to break the line at the space before the % box from the multistrut, so the strut ends up on a line by itself. % For example: % @multitable @columnfractions .11 .89 % @item @code{#} % @tab Legal holiday which is valid in major parts of the whole country. % Is automatically provided with highlighting sequences respectively % marking characters. \noindent\ignorespaces##\unskip\multistrut }\cr } \def\Emultitable{% \crcr \egroup % end the \halign \global\setpercentfalse } \def\setmultitablespacing{% test to see if user has set \multitablelinespace. % If so, do nothing. If not, give it an appropriate dimension based on % current baselineskip. \ifdim\multitablelinespace=0pt \setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip \global\advance\multitablelinespace by-\ht0 %% strut to put in table in case some entry doesn't have descenders, %% to keep lines equally spaced \let\multistrut = \strut \else %% FIXME: what is \box0 supposed to be? \gdef\multistrut{\vrule height\multitablelinespace depth\dp0 width0pt\relax} \fi %% Test to see if parskip is larger than space between lines of %% table. If not, do nothing. %% If so, set to same dimension as multitablelinespace. \ifdim\multitableparskip>\multitablelinespace \global\multitableparskip=\multitablelinespace \global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller %% than skip between lines in the table. \fi% \ifdim\multitableparskip=0pt \global\multitableparskip=\multitablelinespace \global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller %% than skip between lines in the table. \fi} \message{conditionals,} % @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, % @ifnotxml always succeed. They currently do nothing; we don't % attempt to check whether the conditionals are properly nested. But we % have to remember that they are conditionals, so that @end doesn't % attempt to close an environment group. % \def\makecond#1{% \expandafter\let\csname #1\endcsname = \relax \expandafter\let\csname iscond.#1\endcsname = 1 } \makecond{iftex} \makecond{ifnotdocbook} \makecond{ifnothtml} \makecond{ifnotinfo} \makecond{ifnotplaintext} \makecond{ifnotxml} % Ignore @ignore, @ifhtml, @ifinfo, and the like. % \def\direntry{\doignore{direntry}} \def\documentdescription{\doignore{documentdescription}} \def\docbook{\doignore{docbook}} \def\html{\doignore{html}} \def\ifdocbook{\doignore{ifdocbook}} \def\ifhtml{\doignore{ifhtml}} \def\ifinfo{\doignore{ifinfo}} \def\ifnottex{\doignore{ifnottex}} \def\ifplaintext{\doignore{ifplaintext}} \def\ifxml{\doignore{ifxml}} \def\ignore{\doignore{ignore}} \def\menu{\doignore{menu}} \def\xml{\doignore{xml}} % Ignore text until a line `@end #1', keeping track of nested conditionals. % % A count to remember the depth of nesting. \newcount\doignorecount \def\doignore#1{\begingroup % Scan in ``verbatim'' mode: \catcode`\@ = \other \catcode`\{ = \other \catcode`\} = \other % % Make sure that spaces turn into tokens that match what \doignoretext wants. \spaceisspace % % Count number of #1's that we've seen. \doignorecount = 0 % % Swallow text until we reach the matching `@end #1'. \dodoignore{#1}% } { \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source. \obeylines % % \gdef\dodoignore#1{% % #1 contains the command name as a string, e.g., `ifinfo'. % % Define a command to find the next `@end #1', which must be on a line % by itself. \long\def\doignoretext##1^^M@end #1{\doignoretextyyy##1^^M@#1\_STOP_}% % And this command to find another #1 command, at the beginning of a % line. (Otherwise, we would consider a line `@c @ifset', for % example, to count as an @ifset for nesting.) \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% % % And now expand that command. \obeylines % \doignoretext ^^M% }% } \def\doignoreyyy#1{% \def\temp{#1}% \ifx\temp\empty % Nothing found. \let\next\doignoretextzzz \else % Found a nested condition, ... \advance\doignorecount by 1 \let\next\doignoretextyyy % ..., look for another. % If we're here, #1 ends with ^^M\ifinfo (for example). \fi \next #1% the token \_STOP_ is present just after this macro. } % We have to swallow the remaining "\_STOP_". % \def\doignoretextzzz#1{% \ifnum\doignorecount = 0 % We have just found the outermost @end. \let\next\enddoignore \else % Still inside a nested condition. \advance\doignorecount by -1 \let\next\doignoretext % Look for the next @end. \fi \next } % Finish off ignored text. \def\enddoignore{\endgroup\ignorespaces} % @set VAR sets the variable VAR to an empty value. % @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. % % Since we want to separate VAR from REST-OF-LINE (which might be % empty), we can't just use \parsearg; we have to insert a space of our % own to delimit the rest of the line, and then take it out again if we % didn't need it. % We rely on the fact that \parsearg sets \catcode`\ =10. % \parseargdef\set{\setyyy#1 \endsetyyy} \def\setyyy#1 #2\endsetyyy{% {% \makevalueexpandable \def\temp{#2}% \edef\next{\gdef\makecsname{SET#1}}% \ifx\temp\empty \next{}% \else \setzzz#2\endsetzzz \fi }% } % Remove the trailing space \setxxx inserted. \def\setzzz#1 \endsetzzz{\next{#1}} % @clear VAR clears (i.e., unsets) the variable VAR. % \parseargdef\clear{% {% \makevalueexpandable \global\expandafter\let\csname SET#1\endcsname=\relax }% } % @value{foo} gets the text saved in variable foo. \def\value{\begingroup\makevalueexpandable\valuexxx} \def\valuexxx#1{\expandablevalue{#1}\endgroup} { \catcode`\- = \active \catcode`\_ = \active % \gdef\makevalueexpandable{% \let\value = \expandablevalue % We don't want these characters active, ... \catcode`\-=\other \catcode`\_=\other % ..., but we might end up with active ones in the argument if % we're called from @code, as @code{@value{foo-bar_}}, though. % So \let them to their normal equivalents. \let-\realdash \let_\normalunderscore } } % We have this subroutine so that we can handle at least some @value's % properly in indexes (we call \makevalueexpandable in \indexdummies). % The command has to be fully expandable (if the variable is set), since % the result winds up in the index file. This means that if the % variable's value contains other Texinfo commands, it's almost certain % it will fail (although perhaps we could fix that with sufficient work % to do a one-level expansion on the result, instead of complete). % \def\expandablevalue#1{% \expandafter\ifx\csname SET#1\endcsname\relax {[No value for ``#1'']}% \message{Variable `#1', used in @value, is not set.}% \else \csname SET#1\endcsname \fi } % @ifset VAR ... @end ifset reads the `...' iff VAR has been defined % with @set. % % To get special treatment of `@end ifset,' call \makeond and the redefine. % \makecond{ifset} \def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} \def\doifset#1#2{% {% \makevalueexpandable \let\next=\empty \expandafter\ifx\csname SET#2\endcsname\relax #1% If not set, redefine \next. \fi \expandafter }\next } \def\ifsetfail{\doignore{ifset}} % @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been % defined with @set, or has been undefined with @clear. % % The `\else' inside the `\doifset' parameter is a trick to reuse the % above code: if the variable is not set, do nothing, if it is set, % then redefine \next to \ifclearfail. % \makecond{ifclear} \def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} \def\ifclearfail{\doignore{ifclear}} % @dircategory CATEGORY -- specify a category of the dir file % which this file should belong to. Ignore this in TeX. \let\dircategory=\comment % @defininfoenclose. \let\definfoenclose=\comment \message{indexing,} % Index generation facilities % Define \newwrite to be identical to plain tex's \newwrite % except not \outer, so it can be used within \newindex. {\catcode`\@=11 \gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} % \newindex {foo} defines an index named foo. % It automatically defines \fooindex such that % \fooindex ...rest of line... puts an entry in the index foo. % It also defines \fooindfile to be the number of the output channel for % the file that accumulates this index. The file's extension is foo. % The name of an index should be no more than 2 characters long % for the sake of vms. % \def\newindex#1{% \iflinks \expandafter\newwrite \csname#1indfile\endcsname \openout \csname#1indfile\endcsname \jobname.#1 % Open the file \fi \expandafter\xdef\csname#1index\endcsname{% % Define @#1index \noexpand\doindex{#1}} } % @defindex foo == \newindex{foo} % \def\defindex{\parsearg\newindex} % Define @defcodeindex, like @defindex except put all entries in @code. % \def\defcodeindex{\parsearg\newcodeindex} % \def\newcodeindex#1{% \iflinks \expandafter\newwrite \csname#1indfile\endcsname \openout \csname#1indfile\endcsname \jobname.#1 \fi \expandafter\xdef\csname#1index\endcsname{% \noexpand\docodeindex{#1}}% } % @synindex foo bar makes index foo feed into index bar. % Do this instead of @defindex foo if you don't want it as a separate index. % % @syncodeindex foo bar similar, but put all entries made for index foo % inside @code. % \def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} \def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} % #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), % #3 the target index (bar). \def\dosynindex#1#2#3{% % Only do \closeout if we haven't already done it, else we'll end up % closing the target index. \expandafter \ifx\csname donesynindex#2\endcsname \undefined % The \closeout helps reduce unnecessary open files; the limit on the % Acorn RISC OS is a mere 16 files. \expandafter\closeout\csname#2indfile\endcsname \expandafter\let\csname\donesynindex#2\endcsname = 1 \fi % redefine \fooindfile: \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname \expandafter\let\csname#2indfile\endcsname=\temp % redefine \fooindex: \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% } % Define \doindex, the driver for all \fooindex macros. % Argument #1 is generated by the calling \fooindex macro, % and it is "foo", the name of the index. % \doindex just uses \parsearg; it calls \doind for the actual work. % This is because \doind is more useful to call from other macros. % There is also \dosubind {index}{topic}{subtopic} % which makes an entry in a two-level index such as the operation index. \def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} \def\singleindexer #1{\doind{\indexname}{#1}} % like the previous two, but they put @code around the argument. \def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} \def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} % Take care of Texinfo commands that can appear in an index entry. % Since there are some commands we want to expand, and others we don't, % we have to laboriously prevent expansion for those that we don't. % \def\indexdummies{% \def\@{@}% change to @@ when we switch to @ as escape char in index files. \def\ {\realbackslash\space }% % Need these in case \tex is in effect and \{ is a \delimiter again. % But can't use \lbracecmd and \rbracecmd because texindex assumes % braces and backslashes are used only as delimiters. \let\{ = \mylbrace \let\} = \myrbrace % % \definedummyword defines \#1 as \realbackslash #1\space, thus % effectively preventing its expansion. This is used only for control % words, not control letters, because the \space would be incorrect % for control characters, but is needed to separate the control word % from whatever follows. % % For control letters, we have \definedummyletter, which omits the % space. % % These can be used both for control words that take an argument and % those that do not. If it is followed by {arg} in the input, then % that will dutifully get written to the index (or wherever). % \def\definedummyword##1{% \expandafter\def\csname ##1\endcsname{\realbackslash ##1\space}% }% \def\definedummyletter##1{% \expandafter\def\csname ##1\endcsname{\realbackslash ##1}% }% \let\definedummyaccent\definedummyletter % % Do the redefinitions. \commondummies } % For the aux file, @ is the escape character. So we want to redefine % everything using @ instead of \realbackslash. When everything uses % @, this will be simpler. % \def\atdummies{% \def\@{@@}% \def\ {@ }% \let\{ = \lbraceatcmd \let\} = \rbraceatcmd % % (See comments in \indexdummies.) \def\definedummyword##1{% \expandafter\def\csname ##1\endcsname{@##1\space}% }% \def\definedummyletter##1{% \expandafter\def\csname ##1\endcsname{@##1}% }% \let\definedummyaccent\definedummyletter % % Do the redefinitions. \commondummies } % Called from \indexdummies and \atdummies. \definedummyword and % \definedummyletter must be defined first. % \def\commondummies{% % \normalturnoffactive % \commondummiesnofonts % \definedummyletter{_}% % % Non-English letters. \definedummyword{AA}% \definedummyword{AE}% \definedummyword{L}% \definedummyword{OE}% \definedummyword{O}% \definedummyword{aa}% \definedummyword{ae}% \definedummyword{l}% \definedummyword{oe}% \definedummyword{o}% \definedummyword{ss}% \definedummyword{exclamdown}% \definedummyword{questiondown}% \definedummyword{ordf}% \definedummyword{ordm}% % % Although these internal commands shouldn't show up, sometimes they do. \definedummyword{bf}% \definedummyword{gtr}% \definedummyword{hat}% \definedummyword{less}% \definedummyword{sf}% \definedummyword{sl}% \definedummyword{tclose}% \definedummyword{tt}% % \definedummyword{LaTeX}% \definedummyword{TeX}% % % Assorted special characters. \definedummyword{bullet}% \definedummyword{comma}% \definedummyword{copyright}% \definedummyword{registeredsymbol}% \definedummyword{dots}% \definedummyword{enddots}% \definedummyword{equiv}% \definedummyword{error}% \definedummyword{expansion}% \definedummyword{minus}% \definedummyword{pounds}% \definedummyword{point}% \definedummyword{print}% \definedummyword{result}% % % Handle some cases of @value -- where it does not contain any % (non-fully-expandable) commands. \makevalueexpandable % % Normal spaces, not active ones. \unsepspaces % % No macro expansion. \turnoffmacros } % \commondummiesnofonts: common to \commondummies and \indexnofonts. % % Better have this without active chars. { \catcode`\~=\other \gdef\commondummiesnofonts{% % Control letters and accents. \definedummyletter{!}% \definedummyaccent{"}% \definedummyaccent{'}% \definedummyletter{*}% \definedummyaccent{,}% \definedummyletter{.}% \definedummyletter{/}% \definedummyletter{:}% \definedummyaccent{=}% \definedummyletter{?}% \definedummyaccent{^}% \definedummyaccent{`}% \definedummyaccent{~}% \definedummyword{u}% \definedummyword{v}% \definedummyword{H}% \definedummyword{dotaccent}% \definedummyword{ringaccent}% \definedummyword{tieaccent}% \definedummyword{ubaraccent}% \definedummyword{udotaccent}% \definedummyword{dotless}% % % Texinfo font commands. \definedummyword{b}% \definedummyword{i}% \definedummyword{r}% \definedummyword{sc}% \definedummyword{t}% % % Commands that take arguments. \definedummyword{acronym}% \definedummyword{cite}% \definedummyword{code}% \definedummyword{command}% \definedummyword{dfn}% \definedummyword{emph}% \definedummyword{env}% \definedummyword{file}% \definedummyword{kbd}% \definedummyword{key}% \definedummyword{math}% \definedummyword{option}% \definedummyword{samp}% \definedummyword{strong}% \definedummyword{tie}% \definedummyword{uref}% \definedummyword{url}% \definedummyword{var}% \definedummyword{verb}% \definedummyword{w}% } } % \indexnofonts is used when outputting the strings to sort the index % by, and when constructing control sequence names. It eliminates all % control sequences and just writes whatever the best ASCII sort string % would be for a given command (usually its argument). % \def\indexnofonts{% % Accent commands should become @asis. \def\definedummyaccent##1{% \expandafter\let\csname ##1\endcsname\asis }% % We can just ignore other control letters. \def\definedummyletter##1{% \expandafter\def\csname ##1\endcsname{}% }% % Hopefully, all control words can become @asis. \let\definedummyword\definedummyaccent % \commondummiesnofonts % % Don't no-op \tt, since it isn't a user-level command % and is used in the definitions of the active chars like <, >, |, etc. % Likewise with the other plain tex font commands. %\let\tt=\asis % \def\ { }% \def\@{@}% % how to handle braces? \def\_{\normalunderscore}% % % Non-English letters. \def\AA{AA}% \def\AE{AE}% \def\L{L}% \def\OE{OE}% \def\O{O}% \def\aa{aa}% \def\ae{ae}% \def\l{l}% \def\oe{oe}% \def\o{o}% \def\ss{ss}% \def\exclamdown{!}% \def\questiondown{?}% \def\ordf{a}% \def\ordm{o}% % \def\LaTeX{LaTeX}% \def\TeX{TeX}% % % Assorted special characters. % (The following {} will end up in the sort string, but that's ok.) \def\bullet{bullet}% \def\comma{,}% \def\copyright{copyright}% \def\registeredsymbol{R}% \def\dots{...}% \def\enddots{...}% \def\equiv{==}% \def\error{error}% \def\expansion{==>}% \def\minus{-}% \def\pounds{pounds}% \def\point{.}% \def\print{-|}% \def\result{=>}% % % Don't write macro names. \emptyusermacros } \let\indexbackslash=0 %overridden during \printindex. \let\SETmarginindex=\relax % put index entries in margin (undocumented)? % Most index entries go through here, but \dosubind is the general case. % #1 is the index name, #2 is the entry text. \def\doind#1#2{\dosubind{#1}{#2}{}} % Workhorse for all \fooindexes. % #1 is name of index, #2 is stuff to put there, #3 is subentry -- % empty if called from \doind, as we usually are (the main exception % is with most defuns, which call us directly). % \def\dosubind#1#2#3{% \iflinks {% % Store the main index entry text (including the third arg). \toks0 = {#2}% % If third arg is present, precede it with a space. \def\thirdarg{#3}% \ifx\thirdarg\empty \else \toks0 = \expandafter{\the\toks0 \space #3}% \fi % \edef\writeto{\csname#1indfile\endcsname}% % \ifvmode \dosubindsanitize \else \dosubindwrite \fi }% \fi } % Write the entry in \toks0 to the index file: % \def\dosubindwrite{% % Put the index entry in the margin if desired. \ifx\SETmarginindex\relax\else \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% \fi % % Remember, we are within a group. \indexdummies % Must do this here, since \bf, etc expand at this stage \escapechar=`\\ \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now % so it will be output as is; and it will print as backslash. % % Process the index entry with all font commands turned off, to % get the string to sort by. {\indexnofonts \edef\temp{\the\toks0}% need full expansion \xdef\indexsorttmp{\temp}% }% % % Set up the complete index entry, with both the sort key and % the original text, including any font commands. We write % three arguments to \entry to the .?? file (four in the % subentry case), texindex reduces to two when writing the .??s % sorted result. \edef\temp{% \write\writeto{% \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}% }% \temp } % Take care of unwanted page breaks: % % If a skip is the last thing on the list now, preserve it % by backing up by \lastskip, doing the \write, then inserting % the skip again. Otherwise, the whatsit generated by the % \write will make \lastskip zero. The result is that sequences % like this: % @end defun % @tindex whatever % @defun ... % will have extra space inserted, because the \medbreak in the % start of the @defun won't see the skip inserted by the @end of % the previous defun. % % But don't do any of this if we're not in vertical mode. We % don't want to do a \vskip and prematurely end a paragraph. % % Avoid page breaks due to these extra skips, too. % % But wait, there is a catch there: % We'll have to check whether \lastskip is zero skip. \ifdim is not % sufficient for this purpose, as it ignores stretch and shrink parts % of the skip. The only way seems to be to check the textual % representation of the skip. % % The following is almost like \def\zeroskipmacro{0.0pt} except that % the ``p'' and ``t'' characters have catcode \other, not 11 (letter). % \edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} % % ..., ready, GO: % \def\dosubindsanitize{% % \lastskip and \lastpenalty cannot both be nonzero simultaneously. \skip0 = \lastskip \edef\lastskipmacro{\the\lastskip}% \count255 = \lastpenalty % % If \lastskip is nonzero, that means the last item was a % skip. And since a skip is discardable, that means this % -\skip0 glue we're inserting is preceded by a % non-discardable item, therefore it is not a potential % breakpoint, therefore no \nobreak needed. \ifx\lastskipmacro\zeroskipmacro \else \vskip-\skip0 \fi % \dosubindwrite % \ifx\lastskipmacro\zeroskipmacro % If \lastskip was zero, perhaps the last item was a penalty, and % perhaps it was >=10000, e.g., a \nobreak. In that case, we want % to re-insert the same penalty (values >10000 are used for various % signals); since we just inserted a non-discardable item, any % following glue (such as a \parskip) would be a breakpoint. For example: % % @deffn deffn-whatever % @vindex index-whatever % Description. % would allow a break between the index-whatever whatsit % and the "Description." paragraph. \ifnum\count255>9999 \penalty\count255 \fi \else % On the other hand, if we had a nonzero \lastskip, % this make-up glue would be preceded by a non-discardable item % (the whatsit from the \write), so we must insert a \nobreak. \nobreak\vskip\skip0 \fi } % The index entry written in the file actually looks like % \entry {sortstring}{page}{topic} % or % \entry {sortstring}{page}{topic}{subtopic} % The texindex program reads in these files and writes files % containing these kinds of lines: % \initial {c} % before the first topic whose initial is c % \entry {topic}{pagelist} % for a topic that is used without subtopics % \primary {topic} % for the beginning of a topic that is used with subtopics % \secondary {subtopic}{pagelist} % for each subtopic. % Define the user-accessible indexing commands % @findex, @vindex, @kindex, @cindex. \def\findex {\fnindex} \def\kindex {\kyindex} \def\cindex {\cpindex} \def\vindex {\vrindex} \def\tindex {\tpindex} \def\pindex {\pgindex} \def\cindexsub {\begingroup\obeylines\cindexsub} {\obeylines % \gdef\cindexsub "#1" #2^^M{\endgroup % \dosubind{cp}{#2}{#1}}} % Define the macros used in formatting output of the sorted index material. % @printindex causes a particular index (the ??s file) to get printed. % It does not print any chapter heading (usually an @unnumbered). % \parseargdef\printindex{\begingroup \dobreak \chapheadingskip{10000}% % \smallfonts \rm \tolerance = 9500 \everypar = {}% don't want the \kern\-parindent from indentation suppression. % % See if the index file exists and is nonempty. % Change catcode of @ here so that if the index file contains % \initial {@} % as its first line, TeX doesn't complain about mismatched braces % (because it thinks @} is a control sequence). \catcode`\@ = 11 \openin 1 \jobname.#1s \ifeof 1 % \enddoublecolumns gets confused if there is no text in the index, % and it loses the chapter title and the aux file entries for the % index. The easiest way to prevent this problem is to make sure % there is some text. \putwordIndexNonexistent \else % % If the index file exists but is empty, then \openin leaves \ifeof % false. We have to make TeX try to read something from the file, so % it can discover if there is anything in it. \read 1 to \temp \ifeof 1 \putwordIndexIsEmpty \else % Index files are almost Texinfo source, but we use \ as the escape % character. It would be better to use @, but that's too big a change % to make right now. \def\indexbackslash{\backslashcurfont}% \catcode`\\ = 0 \escapechar = `\\ \begindoublecolumns \input \jobname.#1s \enddoublecolumns \fi \fi \closein 1 \endgroup} % These macros are used by the sorted index file itself. % Change them to control the appearance of the index. \def\initial#1{{% % Some minor font changes for the special characters. \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt % % Remove any glue we may have, we'll be inserting our own. \removelastskip % % We like breaks before the index initials, so insert a bonus. \penalty -300 % % Typeset the initial. Making this add up to a whole number of % baselineskips increases the chance of the dots lining up from column % to column. It still won't often be perfect, because of the stretch % we need before each entry, but it's better. % % No shrink because it confuses \balancecolumns. \vskip 1.67\baselineskip plus .5\baselineskip \leftline{\secbf #1}% \vskip .33\baselineskip plus .1\baselineskip % % Do our best not to break after the initial. \nobreak }} % \entry typesets a paragraph consisting of the text (#1), dot leaders, and % then page number (#2) flushed to the right margin. It is used for index % and table of contents entries. The paragraph is indented by \leftskip. % % A straightforward implementation would start like this: % \def\entry#1#2{... % But this frozes the catcodes in the argument, and can cause problems to % @code, which sets - active. This problem was fixed by a kludge--- % ``-'' was active throughout whole index, but this isn't really right. % % The right solution is to prevent \entry from swallowing the whole text. % --kasal, 21nov03 \def\entry{% \begingroup % % Start a new paragraph if necessary, so our assignments below can't % affect previous text. \par % % Do not fill out the last line with white space. \parfillskip = 0in % % No extra space above this paragraph. \parskip = 0in % % Do not prefer a separate line ending with a hyphen to fewer lines. \finalhyphendemerits = 0 % % \hangindent is only relevant when the entry text and page number % don't both fit on one line. In that case, bob suggests starting the % dots pretty far over on the line. Unfortunately, a large % indentation looks wrong when the entry text itself is broken across % lines. So we use a small indentation and put up with long leaders. % % \hangafter is reset to 1 (which is the value we want) at the start % of each paragraph, so we need not do anything with that. \hangindent = 2em % % When the entry text needs to be broken, just fill out the first line % with blank space. \rightskip = 0pt plus1fil % % A bit of stretch before each entry for the benefit of balancing % columns. \vskip 0pt plus1pt % % Swallow the left brace of the text (first parameter): \afterassignment\doentry \let\temp = } \def\doentry{% \bgroup % Instead of the swallowed brace. \noindent \aftergroup\finishentry % And now comes the text of the entry. } \def\finishentry#1{% % #1 is the page number. % % The following is kludged to not output a line of dots in the index if % there are no page numbers. The next person who breaks this will be % cursed by a Unix daemon. \def\tempa{{\rm }}% \def\tempb{#1}% \edef\tempc{\tempa}% \edef\tempd{\tempb}% \ifx\tempc\tempd \ % \else % % If we must, put the page number on a line of its own, and fill out % this line with blank space. (The \hfil is overwhelmed with the % fill leaders glue in \indexdotfill if the page number does fit.) \hfil\penalty50 \null\nobreak\indexdotfill % Have leaders before the page number. % % The `\ ' here is removed by the implicit \unskip that TeX does as % part of (the primitive) \par. Without it, a spurious underfull % \hbox ensues. \ifpdf \pdfgettoks#1.% \ \the\toksA \else \ #1% \fi \fi \par \endgroup } % Like \dotfill except takes at least 1 em. \def\indexdotfill{\cleaders \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} \def\primary #1{\line{#1\hfil}} \newskip\secondaryindent \secondaryindent=0.5cm \def\secondary#1#2{{% \parfillskip=0in \parskip=0in \hangindent=1in \hangafter=1 \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill \ifpdf \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. \else #2 \fi \par }} % Define two-column mode, which we use to typeset indexes. % Adapted from the TeXbook, page 416, which is to say, % the manmac.tex format used to print the TeXbook itself. \catcode`\@=11 \newbox\partialpage \newdimen\doublecolumnhsize \def\begindoublecolumns{\begingroup % ended by \enddoublecolumns % Grab any single-column material above us. \output = {% % % Here is a possibility not foreseen in manmac: if we accumulate a % whole lot of material, we might end up calling this \output % routine twice in a row (see the doublecol-lose test, which is % essentially a couple of indexes with @setchapternewpage off). In % that case we just ship out what is in \partialpage with the normal % output routine. Generally, \partialpage will be empty when this % runs and this will be a no-op. See the indexspread.tex test case. \ifvoid\partialpage \else \onepageout{\pagecontents\partialpage}% \fi % \global\setbox\partialpage = \vbox{% % Unvbox the main output page. \unvbox\PAGE \kern-\topskip \kern\baselineskip }% }% \eject % run that output routine to set \partialpage % % Use the double-column output routine for subsequent pages. \output = {\doublecolumnout}% % % Change the page size parameters. We could do this once outside this % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 % format, but then we repeat the same computation. Repeating a couple % of assignments once per index is clearly meaningless for the % execution time, so we may as well do it in one place. % % First we halve the line length, less a little for the gutter between % the columns. We compute the gutter based on the line length, so it % changes automatically with the paper format. The magic constant % below is chosen so that the gutter has the same value (well, +-<1pt) % as it did when we hard-coded it. % % We put the result in a separate register, \doublecolumhsize, so we % can restore it in \pagesofar, after \hsize itself has (potentially) % been clobbered. % \doublecolumnhsize = \hsize \advance\doublecolumnhsize by -.04154\hsize \divide\doublecolumnhsize by 2 \hsize = \doublecolumnhsize % % Double the \vsize as well. (We don't need a separate register here, % since nobody clobbers \vsize.) \vsize = 2\vsize } % The double-column output routine for all double-column pages except % the last. % \def\doublecolumnout{% \splittopskip=\topskip \splitmaxdepth=\maxdepth % Get the available space for the double columns -- the normal % (undoubled) page height minus any material left over from the % previous page. \dimen@ = \vsize \divide\dimen@ by 2 \advance\dimen@ by -\ht\partialpage % % box0 will be the left-hand column, box2 the right. \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ \onepageout\pagesofar \unvbox255 \penalty\outputpenalty } % % Re-output the contents of the output page -- any previous material, % followed by the two boxes we just split, in box0 and box2. \def\pagesofar{% \unvbox\partialpage % \hsize = \doublecolumnhsize \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}% } % % All done with double columns. \def\enddoublecolumns{% \output = {% % Split the last of the double-column material. Leave it on the % current page, no automatic page break. \balancecolumns % % If we end up splitting too much material for the current page, % though, there will be another page break right after this \output % invocation ends. Having called \balancecolumns once, we do not % want to call it again. Therefore, reset \output to its normal % definition right away. (We hope \balancecolumns will never be % called on to balance too much material, but if it is, this makes % the output somewhat more palatable.) \global\output = {\onepageout{\pagecontents\PAGE}}% }% \eject \endgroup % started in \begindoublecolumns % % \pagegoal was set to the doubled \vsize above, since we restarted % the current page. We're now back to normal single-column % typesetting, so reset \pagegoal to the normal \vsize (after the % \endgroup where \vsize got restored). \pagegoal = \vsize } % % Called at the end of the double column material. \def\balancecolumns{% \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. \dimen@ = \ht0 \advance\dimen@ by \topskip \advance\dimen@ by-\baselineskip \divide\dimen@ by 2 % target to split to %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% \splittopskip = \topskip % Loop until we get a decent breakpoint. {% \vbadness = 10000 \loop \global\setbox3 = \copy0 \global\setbox1 = \vsplit3 to \dimen@ \ifdim\ht3>\dimen@ \global\advance\dimen@ by 1pt \repeat }% %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% \setbox0=\vbox to\dimen@{\unvbox1}% \setbox2=\vbox to\dimen@{\unvbox3}% % \pagesofar } \catcode`\@ = \other \message{sectioning,} % Chapters, sections, etc. % \unnumberedno is an oxymoron, of course. But we count the unnumbered % sections so that we can refer to them unambiguously in the pdf % outlines by their "section number". We avoid collisions with chapter % numbers by starting them at 10000. (If a document ever has 10000 % chapters, we're in trouble anyway, I'm sure.) \newcount\unnumberedno \unnumberedno = 10000 \newcount\chapno \newcount\secno \secno=0 \newcount\subsecno \subsecno=0 \newcount\subsubsecno \subsubsecno=0 % This counter is funny since it counts through charcodes of letters A, B, ... \newcount\appendixno \appendixno = `\@ % % \def\appendixletter{\char\the\appendixno} % We do the following ugly conditional instead of the above simple % construct for the sake of pdftex, which needs the actual % letter in the expansion, not just typeset. % \def\appendixletter{% \ifnum\appendixno=`A A% \else\ifnum\appendixno=`B B% \else\ifnum\appendixno=`C C% \else\ifnum\appendixno=`D D% \else\ifnum\appendixno=`E E% \else\ifnum\appendixno=`F F% \else\ifnum\appendixno=`G G% \else\ifnum\appendixno=`H H% \else\ifnum\appendixno=`I I% \else\ifnum\appendixno=`J J% \else\ifnum\appendixno=`K K% \else\ifnum\appendixno=`L L% \else\ifnum\appendixno=`M M% \else\ifnum\appendixno=`N N% \else\ifnum\appendixno=`O O% \else\ifnum\appendixno=`P P% \else\ifnum\appendixno=`Q Q% \else\ifnum\appendixno=`R R% \else\ifnum\appendixno=`S S% \else\ifnum\appendixno=`T T% \else\ifnum\appendixno=`U U% \else\ifnum\appendixno=`V V% \else\ifnum\appendixno=`W W% \else\ifnum\appendixno=`X X% \else\ifnum\appendixno=`Y Y% \else\ifnum\appendixno=`Z Z% % The \the is necessary, despite appearances, because \appendixletter is % expanded while writing the .toc file. \char\appendixno is not % expandable, thus it is written literally, thus all appendixes come out % with the same letter (or @) in the toc without it. \else\char\the\appendixno \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} % Each @chapter defines this as the name of the chapter. % page headings and footings can use it. @section does likewise. % However, they are not reliable, because we don't use marks. \def\thischapter{} \def\thissection{} \newcount\absseclevel % used to calculate proper heading level \newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count % @raisesections: treat @section as chapter, @subsection as section, etc. \def\raisesections{\global\advance\secbase by -1} \let\up=\raisesections % original BFox name % @lowersections: treat @chapter as section, @section as subsection, etc. \def\lowersections{\global\advance\secbase by 1} \let\down=\lowersections % original BFox name % we only have subsub. \chardef\maxseclevel = 3 % % A numbered section within an unnumbered changes to unnumbered too. % To achive this, remember the "biggest" unnum. sec. we are currently in: \chardef\unmlevel = \maxseclevel % % Trace whether the current chapter is an appendix or not: % \chapheadtype is "N" or "A", unnumbered chapters are ignored. \def\chapheadtype{N} % Choose a heading macro % #1 is heading type % #2 is heading level % #3 is text for heading \def\genhead#1#2#3{% % Compute the abs. sec. level: \absseclevel=#2 \advance\absseclevel by \secbase % Make sure \absseclevel doesn't fall outside the range: \ifnum \absseclevel < 0 \absseclevel = 0 \else \ifnum \absseclevel > 3 \absseclevel = 3 \fi \fi % The heading type: \def\headtype{#1}% \if \headtype U% \ifnum \absseclevel < \unmlevel \chardef\unmlevel = \absseclevel \fi \else % Check for appendix sections: \ifnum \absseclevel = 0 \edef\chapheadtype{\headtype}% \else \if \headtype A\if \chapheadtype N% \errmessage{@appendix... within a non-appendix chapter}% \fi\fi \fi % Check for numbered within unnumbered: \ifnum \absseclevel > \unmlevel \def\headtype{U}% \else \chardef\unmlevel = 3 \fi \fi % Now print the heading: \if \headtype U% \ifcase\absseclevel \unnumberedzzz{#3}% \or \unnumberedseczzz{#3}% \or \unnumberedsubseczzz{#3}% \or \unnumberedsubsubseczzz{#3}% \fi \else \if \headtype A% \ifcase\absseclevel \appendixzzz{#3}% \or \appendixsectionzzz{#3}% \or \appendixsubseczzz{#3}% \or \appendixsubsubseczzz{#3}% \fi \else \ifcase\absseclevel \chapterzzz{#3}% \or \seczzz{#3}% \or \numberedsubseczzz{#3}% \or \numberedsubsubseczzz{#3}% \fi \fi \fi \suppressfirstparagraphindent } % an interface: \def\numhead{\genhead N} \def\apphead{\genhead A} \def\unnmhead{\genhead U} % @chapter, @appendix, @unnumbered. Increment top-level counter, reset % all lower-level sectioning counters to zero. % % Also set \chaplevelprefix, which we prepend to @float sequence numbers % (e.g., figures), q.v. By default (before any chapter), that is empty. \let\chaplevelprefix = \empty % \outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz \def\chapterzzz#1{% % section resetting is \global in case the chapter is in a group, such % as an @include file. \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\chapno by 1 % % Used for \float. \gdef\chaplevelprefix{\the\chapno.}% \resetallfloatnos % \message{\putwordChapter\space \the\chapno}% % % Write the actual heading. \chapmacro{#1}{Ynumbered}{\the\chapno}% % % So @section and the like are numbered underneath this chapter. \global\let\section = \numberedsec \global\let\subsection = \numberedsubsec \global\let\subsubsection = \numberedsubsubsec } \outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz \def\appendixzzz#1{% \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\appendixno by 1 \gdef\chaplevelprefix{\appendixletter.}% \resetallfloatnos % \def\appendixnum{\putwordAppendix\space \appendixletter}% \message{\appendixnum}% % \chapmacro{#1}{Yappendix}{\appendixletter}% % \global\let\section = \appendixsec \global\let\subsection = \appendixsubsec \global\let\subsubsection = \appendixsubsubsec } \outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz \def\unnumberedzzz#1{% \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\unnumberedno by 1 % % Since an unnumbered has no number, no prefix for figures. \global\let\chaplevelprefix = \empty \resetallfloatnos % % This used to be simply \message{#1}, but TeX fully expands the % argument to \message. Therefore, if #1 contained @-commands, TeX % expanded them. For example, in `@unnumbered The @cite{Book}', TeX % expanded @cite (which turns out to cause errors because \cite is meant % to be executed, not expanded). % % Anyway, we don't want the fully-expanded definition of @cite to appear % as a result of the \message, we just want `@cite' itself. We use % \the to achieve this: TeX expands \the only once, % simply yielding the contents of . (We also do this for % the toc entries.) \toks0 = {#1}% \message{(\the\toks0)}% % \chapmacro{#1}{Ynothing}{\the\unnumberedno}% % \global\let\section = \unnumberedsec \global\let\subsection = \unnumberedsubsec \global\let\subsubsection = \unnumberedsubsubsec } % @centerchap is like @unnumbered, but the heading is centered. \outer\parseargdef\centerchap{% % Well, we could do the following in a group, but that would break % an assumption that \chapmacro is called at the outermost level. % Thus we are safer this way: --kasal, 24feb04 \let\centerparametersmaybe = \centerparameters \unnmhead0{#1}% \let\centerparametersmaybe = \relax } % @top is like @unnumbered. \let\top\unnumbered % Sections. \outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz \def\seczzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% } \outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz \def\appendixsectionzzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% } \let\appendixsec\appendixsection \outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz \def\unnumberedseczzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% } % Subsections. \outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz \def\numberedsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% } \outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz \def\appendixsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Yappendix}% {\appendixletter.\the\secno.\the\subsecno}% } \outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz \def\unnumberedsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Ynothing}% {\the\unnumberedno.\the\secno.\the\subsecno}% } % Subsubsections. \outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz \def\numberedsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Ynumbered}% {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% } \outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz \def\appendixsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Yappendix}% {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% } \outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz \def\unnumberedsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Ynothing}% {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}% } % These macros control what the section commands do, according % to what kind of chapter we are in (ordinary, appendix, or unnumbered). % Define them by default for a numbered chapter. \let\section = \numberedsec \let\subsection = \numberedsubsec \let\subsubsection = \numberedsubsubsec % Define @majorheading, @heading and @subheading % NOTE on use of \vbox for chapter headings, section headings, and such: % 1) We use \vbox rather than the earlier \line to permit % overlong headings to fold. % 2) \hyphenpenalty is set to 10000 because hyphenation in a % heading is obnoxious; this forbids it. % 3) Likewise, headings look best if no \parindent is used, and % if justification is not attempted. Hence \raggedright. \def\majorheading{% {\advance\chapheadingskip by 10pt \chapbreak }% \parsearg\chapheadingzzz } \def\chapheading{\chapbreak \parsearg\chapheadingzzz} \def\chapheadingzzz#1{% {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 \parindent=0pt\raggedright \rm #1\hfill}}% \bigskip \par\penalty 200\relax \suppressfirstparagraphindent } % @heading, @subheading, @subsubheading. \parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{} \suppressfirstparagraphindent} \parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{} \suppressfirstparagraphindent} \parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{} \suppressfirstparagraphindent} % These macros generate a chapter, section, etc. heading only % (including whitespace, linebreaking, etc. around it), % given all the information in convenient, parsed form. %%% Args are the skip and penalty (usually negative) \def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} %%% Define plain chapter starts, and page on/off switching for it % Parameter controlling skip before chapter headings (if needed) \newskip\chapheadingskip \def\chapbreak{\dobreak \chapheadingskip {-4000}} \def\chappager{\par\vfill\supereject} \def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} \def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} \def\CHAPPAGoff{% \global\let\contentsalignmacro = \chappager \global\let\pchapsepmacro=\chapbreak \global\let\pagealignmacro=\chappager} \def\CHAPPAGon{% \global\let\contentsalignmacro = \chappager \global\let\pchapsepmacro=\chappager \global\let\pagealignmacro=\chappager \global\def\HEADINGSon{\HEADINGSsingle}} \def\CHAPPAGodd{% \global\let\contentsalignmacro = \chapoddpage \global\let\pchapsepmacro=\chapoddpage \global\let\pagealignmacro=\chapoddpage \global\def\HEADINGSon{\HEADINGSdouble}} \CHAPPAGon % Chapter opening. % % #1 is the text, #2 is the section type (Ynumbered, Ynothing, % Yappendix, Yomitfromtoc), #3 the chapter number. % % To test against our argument. \def\Ynothingkeyword{Ynothing} \def\Yomitfromtockeyword{Yomitfromtoc} \def\Yappendixkeyword{Yappendix} % \def\chapmacro#1#2#3{% \pchapsepmacro {% \chapfonts \rm % % Have to define \thissection before calling \donoderef, because the % xref code eventually uses it. On the other hand, it has to be called % after \pchapsepmacro, or the headline will change too soon. \gdef\thissection{#1}% \gdef\thischaptername{#1}% % % Only insert the separating space if we have a chapter/appendix % number, and don't print the unnumbered ``number''. \def\temptype{#2}% \ifx\temptype\Ynothingkeyword \setbox0 = \hbox{}% \def\toctype{unnchap}% \def\thischapter{#1}% \else\ifx\temptype\Yomitfromtockeyword \setbox0 = \hbox{}% contents like unnumbered, but no toc entry \def\toctype{omit}% \xdef\thischapter{}% \else\ifx\temptype\Yappendixkeyword \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% \def\toctype{app}% % We don't substitute the actual chapter name into \thischapter % because we don't want its macros evaluated now. And we don't % use \thissection because that changes with each section. % \xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}% \else \setbox0 = \hbox{#3\enspace}% \def\toctype{numchap}% \xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}% \fi\fi\fi % % Write the toc entry for this chapter. Must come before the % \donoderef, because we include the current node name in the toc % entry, and \donoderef resets it to empty. \writetocentry{\toctype}{#1}{#3}% % % For pdftex, we have to write out the node definition (aka, make % the pdfdest) after any page break, but before the actual text has % been typeset. If the destination for the pdf outline is after the % text, then jumping from the outline may wind up with the text not % being visible, for instance under high magnification. \donoderef{#2}% % % Typeset the actual heading. \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright \hangindent=\wd0 \centerparametersmaybe \unhbox0 #1\par}% }% \nobreak\bigskip % no page break after a chapter title \nobreak } % @centerchap -- centered and unnumbered. \let\centerparametersmaybe = \relax \def\centerparameters{% \advance\rightskip by 3\rightskip \leftskip = \rightskip \parfillskip = 0pt } % I don't think this chapter style is supported any more, so I'm not % updating it with the new noderef stuff. We'll see. --karl, 11aug03. % \def\setchapterstyle #1 {\csname CHAPF#1\endcsname} % \def\unnchfopen #1{% \chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 \parindent=0pt\raggedright \rm #1\hfill}}\bigskip \par\nobreak } \def\chfopen #1#2{\chapoddpage {\chapfonts \vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% \par\penalty 5000 % } \def\centerchfopen #1{% \chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 \parindent=0pt \hfill {\rm #1}\hfill}}\bigskip \par\nobreak } \def\CHAPFopen{% \global\let\chapmacro=\chfopen \global\let\centerchapmacro=\centerchfopen} % Section titles. These macros combine the section number parts and % call the generic \sectionheading to do the printing. % \newskip\secheadingskip \def\secheadingbreak{\dobreak \secheadingskip{-1000}} % Subsection titles. \newskip\subsecheadingskip \def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}} % Subsubsection titles. \def\subsubsecheadingskip{\subsecheadingskip} \def\subsubsecheadingbreak{\subsecheadingbreak} % Print any size, any type, section title. % % #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is % the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the % section number. % \def\sectionheading#1#2#3#4{% {% % Switch to the right set of fonts. \csname #2fonts\endcsname \rm % % Insert space above the heading. \csname #2headingbreak\endcsname % % Only insert the space after the number if we have a section number. \def\sectionlevel{#2}% \def\temptype{#3}% % \ifx\temptype\Ynothingkeyword \setbox0 = \hbox{}% \def\toctype{unn}% \gdef\thissection{#1}% \else\ifx\temptype\Yomitfromtockeyword % for @headings -- no section number, don't include in toc, % and don't redefine \thissection. \setbox0 = \hbox{}% \def\toctype{omit}% \let\sectionlevel=\empty \else\ifx\temptype\Yappendixkeyword \setbox0 = \hbox{#4\enspace}% \def\toctype{app}% \gdef\thissection{#1}% \else \setbox0 = \hbox{#4\enspace}% \def\toctype{num}% \gdef\thissection{#1}% \fi\fi\fi % % Write the toc entry (before \donoderef). See comments in \chfplain. \writetocentry{\toctype\sectionlevel}{#1}{#4}% % % Write the node reference (= pdf destination for pdftex). % Again, see comments in \chfplain. \donoderef{#3}% % % Output the actual section heading. \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright \hangindent=\wd0 % zero if no section number \unhbox0 #1}% }% % Add extra space after the heading -- half of whatever came above it. % Don't allow stretch, though. \kern .5 \csname #2headingskip\endcsname % % Do not let the kern be a potential breakpoint, as it would be if it % was followed by glue. \nobreak % % We'll almost certainly start a paragraph next, so don't let that % glue accumulate. (Not a breakpoint because it's preceded by a % discardable item.) \vskip-\parskip % % This is purely so the last item on the list is a known \penalty > % 10000. This is so \startdefun can avoid allowing breakpoints after % section headings. Otherwise, it would insert a valid breakpoint between: % % @section sec-whatever % @deffn def-whatever \penalty 10001 } \message{toc,} % Table of contents. \newwrite\tocfile % Write an entry to the toc file, opening it if necessary. % Called from @chapter, etc. % % Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno} % We append the current node name (if any) and page number as additional % arguments for the \{chap,sec,...}entry macros which will eventually % read this. The node name is used in the pdf outlines as the % destination to jump to. % % We open the .toc file for writing here instead of at @setfilename (or % any other fixed time) so that @contents can be anywhere in the document. % But if #1 is `omit', then we don't do anything. This is used for the % table of contents chapter openings themselves. % \newif\iftocfileopened \def\omitkeyword{omit}% % \def\writetocentry#1#2#3{% \edef\writetoctype{#1}% \ifx\writetoctype\omitkeyword \else \iftocfileopened\else \immediate\openout\tocfile = \jobname.toc \global\tocfileopenedtrue \fi % \iflinks \toks0 = {#2}% \toks2 = \expandafter{\lastnode}% \edef\temp{\write\tocfile{\realbackslash #1entry{\the\toks0}{#3}% {\the\toks2}{\noexpand\folio}}}% \temp \fi \fi % % Tell \shipout to create a pdf destination on each page, if we're % writing pdf. These are used in the table of contents. We can't % just write one on every page because the title pages are numbered % 1 and 2 (the page numbers aren't printed), and so are the first % two pages of the document. Thus, we'd have two destinations named % `1', and two named `2'. \ifpdf \global\pdfmakepagedesttrue \fi } \newskip\contentsrightmargin \contentsrightmargin=1in \newcount\savepageno \newcount\lastnegativepageno \lastnegativepageno = -1 % Prepare to read what we've written to \tocfile. % \def\startcontents#1{% % If @setchapternewpage on, and @headings double, the contents should % start on an odd page, unlike chapters. Thus, we maintain % \contentsalignmacro in parallel with \pagealignmacro. % From: Torbjorn Granlund \contentsalignmacro \immediate\closeout\tocfile % % Don't need to put `Contents' or `Short Contents' in the headline. % It is abundantly clear what they are. \def\thischapter{}% \chapmacro{#1}{Yomitfromtoc}{}% % \savepageno = \pageno \begingroup % Set up to handle contents files properly. \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 % We can't do this, because then an actual ^ in a section % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97. %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi \raggedbottom % Worry more about breakpoints than the bottom. \advance\hsize by -\contentsrightmargin % Don't use the full line length. % % Roman numerals for page numbers. \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi } % Normal (long) toc. \def\contents{% \startcontents{\putwordTOC}% \openin 1 \jobname.toc \ifeof 1 \else \input \jobname.toc \fi \vfill \eject \contentsalignmacro % in case @setchapternewpage odd is in effect \ifeof 1 \else \pdfmakeoutlines \fi \closein 1 \endgroup \lastnegativepageno = \pageno \global\pageno = \savepageno } % And just the chapters. \def\summarycontents{% \startcontents{\putwordShortTOC}% % \let\numchapentry = \shortchapentry \let\appentry = \shortchapentry \let\unnchapentry = \shortunnchapentry % We want a true roman here for the page numbers. \secfonts \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl \let\tt=\shortconttt \rm \hyphenpenalty = 10000 \advance\baselineskip by 1pt % Open it up a little. \def\numsecentry##1##2##3##4{} \let\appsecentry = \numsecentry \let\unnsecentry = \numsecentry \let\numsubsecentry = \numsecentry \let\appsubsecentry = \numsecentry \let\unnsubsecentry = \numsecentry \let\numsubsubsecentry = \numsecentry \let\appsubsubsecentry = \numsecentry \let\unnsubsubsecentry = \numsecentry \openin 1 \jobname.toc \ifeof 1 \else \input \jobname.toc \fi \closein 1 \vfill \eject \contentsalignmacro % in case @setchapternewpage odd is in effect \endgroup \lastnegativepageno = \pageno \global\pageno = \savepageno } \let\shortcontents = \summarycontents % Typeset the label for a chapter or appendix for the short contents. % The arg is, e.g., `A' for an appendix, or `3' for a chapter. % \def\shortchaplabel#1{% % This space should be enough, since a single number is .5em, and the % widest letter (M) is 1em, at least in the Computer Modern fonts. % But use \hss just in case. % (This space doesn't include the extra space that gets added after % the label; that gets put in by \shortchapentry above.) % % We'd like to right-justify chapter numbers, but that looks strange % with appendix letters. And right-justifying numbers and % left-justifying letters looks strange when there is less than 10 % chapters. Have to read the whole toc once to know how many chapters % there are before deciding ... \hbox to 1em{#1\hss}% } % These macros generate individual entries in the table of contents. % The first argument is the chapter or section name. % The last argument is the page number. % The arguments in between are the chapter number, section number, ... % Chapters, in the main contents. \def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} % % Chapters, in the short toc. % See comments in \dochapentry re vbox and related settings. \def\shortchapentry#1#2#3#4{% \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}% } % Appendices, in the main contents. % Need the word Appendix, and a fixed-size box. % \def\appendixbox#1{% % We use M since it's probably the widest letter. \setbox0 = \hbox{\putwordAppendix{} M}% \hbox to \wd0{\putwordAppendix{} #1\hss}} % \def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}} % Unnumbered chapters. \def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} \def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}} % Sections. \def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}} \let\appsecentry=\numsecentry \def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}} % Subsections. \def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}} \let\appsubsecentry=\numsubsecentry \def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}} % And subsubsections. \def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}} \let\appsubsubsecentry=\numsubsubsecentry \def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}} % This parameter controls the indentation of the various levels. % Same as \defaultparindent. \newdimen\tocindent \tocindent = 15pt % Now for the actual typesetting. In all these, #1 is the text and #2 is the % page number. % % If the toc has to be broken over pages, we want it to be at chapters % if at all possible; hence the \penalty. \def\dochapentry#1#2{% \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip \begingroup \chapentryfonts \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup \nobreak\vskip .25\baselineskip plus.1\baselineskip } \def\dosecentry#1#2{\begingroup \secentryfonts \leftskip=\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} \def\dosubsecentry#1#2{\begingroup \subsecentryfonts \leftskip=2\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} \def\dosubsubsecentry#1#2{\begingroup \subsubsecentryfonts \leftskip=3\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} % We use the same \entry macro as for the index entries. \let\tocentry = \entry % Space between chapter (or whatever) number and the title. \def\labelspace{\hskip1em \relax} \def\dopageno#1{{\rm #1}} \def\doshortpageno#1{{\rm #1}} \def\chapentryfonts{\secfonts \rm} \def\secentryfonts{\textfonts} \def\subsecentryfonts{\textfonts} \def\subsubsecentryfonts{\textfonts} \message{environments,} % @foo ... @end foo. % @point{}, @result{}, @expansion{}, @print{}, @equiv{}. % % Since these characters are used in examples, it should be an even number of % \tt widths. Each \tt character is 1en, so two makes it 1em. % \def\point{$\star$} \def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} \def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} \def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} \def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} % The @error{} command. % Adapted from the TeXbook's \boxit. % \newbox\errorbox % {\tentt \global\dimen0 = 3em}% Width of the box. \dimen2 = .55pt % Thickness of rules % The text. (`r' is open on the right, `e' somewhat less so on the left.) \setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} % \setbox\errorbox=\hbox to \dimen0{\hfil \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. \advance\hsize by -2\dimen2 % Rules. \vbox{% \hrule height\dimen2 \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. \kern3pt\vrule width\dimen2}% Space to right. \hrule height\dimen2} \hfil} % \def\error{\leavevmode\lower.7ex\copy\errorbox} % @tex ... @end tex escapes into raw Tex temporarily. % One exception: @ is still an escape character, so that @end tex works. % But \@ or @@ will get a plain tex @ character. \envdef\tex{% \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie \catcode `\%=14 \catcode `\+=\other \catcode `\"=\other \catcode `\|=\other \catcode `\<=\other \catcode `\>=\other \escapechar=`\\ % \let\b=\ptexb \let\bullet=\ptexbullet \let\c=\ptexc \let\,=\ptexcomma \let\.=\ptexdot \let\dots=\ptexdots \let\equiv=\ptexequiv \let\!=\ptexexclam \let\i=\ptexi \let\indent=\ptexindent \let\noindent=\ptexnoindent \let\{=\ptexlbrace \let\+=\tabalign \let\}=\ptexrbrace \let\/=\ptexslash \let\*=\ptexstar \let\t=\ptext % \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% \def\@{@}% } % There is no need to define \Etex. % Define @lisp ... @end lisp. % @lisp environment forms a group so it can rebind things, % including the definition of @end lisp (which normally is erroneous). % Amount to narrow the margins by for @lisp. \newskip\lispnarrowing \lispnarrowing=0.4in % This is the definition that ^^M gets inside @lisp, @example, and other % such environments. \null is better than a space, since it doesn't % have any width. \def\lisppar{\null\endgraf} % This space is always present above and below environments. \newskip\envskipamount \envskipamount = 0pt % Make spacing and below environment symmetrical. We use \parskip here % to help in doing that, since in @example-like environments \parskip % is reset to zero; thus the \afterenvbreak inserts no space -- but the % start of the next paragraph will insert \parskip. % \def\aboveenvbreak{{% % =10000 instead of <10000 because of a special case in \itemzzz and % \sectionheading, q.v. \ifnum \lastpenalty=10000 \else \advance\envskipamount by \parskip \endgraf \ifdim\lastskip<\envskipamount \removelastskip % it's not a good place to break if the last penalty was \nobreak % or better ... \ifnum\lastpenalty<10000 \penalty-50 \fi \vskip\envskipamount \fi \fi }} \let\afterenvbreak = \aboveenvbreak % \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. \let\nonarrowing=\relax % @cartouche ... @end cartouche: draw rectangle w/rounded corners around % environment contents. \font\circle=lcircle10 \newdimen\circthick \newdimen\cartouter\newdimen\cartinner \newskip\normbskip\newskip\normpskip\newskip\normlskip \circthick=\fontdimen8\circle % \def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth \def\ctr{{\hskip 6pt\circle\char'010}} \def\cbl{{\circle\char'012\hskip -6pt}} \def\cbr{{\hskip 6pt\circle\char'011}} \def\carttop{\hbox to \cartouter{\hskip\lskip \ctl\leaders\hrule height\circthick\hfil\ctr \hskip\rskip}} \def\cartbot{\hbox to \cartouter{\hskip\lskip \cbl\leaders\hrule height\circthick\hfil\cbr \hskip\rskip}} % \newskip\lskip\newskip\rskip \envdef\cartouche{% \ifhmode\par\fi % can't be in the midst of a paragraph. \startsavinginserts \lskip=\leftskip \rskip=\rightskip \leftskip=0pt\rightskip=0pt % we want these *outside*. \cartinner=\hsize \advance\cartinner by-\lskip \advance\cartinner by-\rskip \cartouter=\hsize \advance\cartouter by 18.4pt % allow for 3pt kerns on either % side, and for 6pt waste from % each corner char, and rule thickness \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip % Flag to tell @lisp, etc., not to narrow margin. \let\nonarrowing=\comment \vbox\bgroup \baselineskip=0pt\parskip=0pt\lineskip=0pt \carttop \hbox\bgroup \hskip\lskip \vrule\kern3pt \vbox\bgroup \kern3pt \hsize=\cartinner \baselineskip=\normbskip \lineskip=\normlskip \parskip=\normpskip \vskip -\parskip \comment % For explanation, see the end of \def\group. } \def\Ecartouche{% \ifhmode\par\fi \kern3pt \egroup \kern3pt\vrule \hskip\rskip \egroup \cartbot \egroup \checkinserts } % This macro is called at the beginning of all the @example variants, % inside a group. \def\nonfillstart{% \aboveenvbreak \hfuzz = 12pt % Don't be fussy \sepspaces % Make spaces be word-separators rather than space tokens. \let\par = \lisppar % don't ignore blank lines \obeylines % each line of input is a line of output \parskip = 0pt \parindent = 0pt \emergencystretch = 0pt % don't try to avoid overfull boxes % @cartouche defines \nonarrowing to inhibit narrowing % at next level down. \ifx\nonarrowing\relax \advance \leftskip by \lispnarrowing \exdentamount=\lispnarrowing \fi \let\exdent=\nofillexdent } % If you want all examples etc. small: @set dispenvsize small. % If you want even small examples the full size: @set dispenvsize nosmall. % This affects the following displayed environments: % @example, @display, @format, @lisp % \def\smallword{small} \def\nosmallword{nosmall} \let\SETdispenvsize\relax \def\setnormaldispenv{% \ifx\SETdispenvsize\smallword \smallexamplefonts \rm \fi } \def\setsmalldispenv{% \ifx\SETdispenvsize\nosmallword \else \smallexamplefonts \rm \fi } % We often define two environments, @foo and @smallfoo. % Let's do it by one command: \def\makedispenv #1#2{ \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2} \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2} \expandafter\let\csname E#1\endcsname \afterenvbreak \expandafter\let\csname Esmall#1\endcsname \afterenvbreak } % Define two synonyms: \def\maketwodispenvs #1#2#3{ \makedispenv{#1}{#3} \makedispenv{#2}{#3} } % @lisp: indented, narrowed, typewriter font; @example: same as @lisp. % % @smallexample and @smalllisp: use smaller fonts. % Originally contributed by Pavel@xerox. % \maketwodispenvs {lisp}{example}{% \nonfillstart \tt \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. \gobble % eat return } % @display/@smalldisplay: same as @lisp except keep current font. % \makedispenv {display}{% \nonfillstart \gobble } % @format/@smallformat: same as @display except don't narrow margins. % \makedispenv{format}{% \let\nonarrowing = t% \nonfillstart \gobble } % @flushleft: same as @format, but doesn't obey \SETdispenvsize. \envdef\flushleft{% \let\nonarrowing = t% \nonfillstart \gobble } \let\Eflushleft = \afterenvbreak % @flushright. % \envdef\flushright{% \let\nonarrowing = t% \nonfillstart \advance\leftskip by 0pt plus 1fill \gobble } \let\Eflushright = \afterenvbreak % @quotation does normal linebreaking (hence we can't use \nonfillstart) % and narrows the margins. We keep \parskip nonzero in general, since % we're doing normal filling. So, when using \aboveenvbreak and % \afterenvbreak, temporarily make \parskip 0. % \envdef\quotation{% {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip \parindent=0pt % % @cartouche defines \nonarrowing to inhibit narrowing at next level down. \ifx\nonarrowing\relax \advance\leftskip by \lispnarrowing \advance\rightskip by \lispnarrowing \exdentamount = \lispnarrowing \let\nonarrowing = \relax \fi \parsearg\quotationlabel } % We have retained a nonzero parskip for the environment, since we're % doing normal filling. % \def\Equotation{% \par \ifx\quotationauthor\undefined\else % indent a bit. \leftline{\kern 2\leftskip \sl ---\quotationauthor}% \fi {\parskip=0pt \afterenvbreak}% } % If we're given an argument, typeset it in bold with a colon after. \def\quotationlabel#1{% \def\temp{#1}% \ifx\temp\empty \else {\bf #1: }% \fi } % LaTeX-like @verbatim...@end verbatim and @verb{...} % If we want to allow any as delimiter, % we need the curly braces so that makeinfo sees the @verb command, eg: % `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org % % [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. % % [Knuth] p.344; only we need to do the other characters Texinfo sets % active too. Otherwise, they get lost as the first character on a % verbatim line. \def\dospecials{% \do\ \do\\\do\{\do\}\do\$\do\&% \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% \do\<\do\>\do\|\do\@\do+\do\"% } % % [Knuth] p. 380 \def\uncatcodespecials{% \def\do##1{\catcode`##1=\other}\dospecials} % % [Knuth] pp. 380,381,391 % Disable Spanish ligatures ?` and !` of \tt font \begingroup \catcode`\`=\active\gdef`{\relax\lq} \endgroup % % Setup for the @verb command. % % Eight spaces for a tab \begingroup \catcode`\^^I=\active \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} \endgroup % \def\setupverb{% \tt % easiest (and conventionally used) font for verbatim \def\par{\leavevmode\endgraf}% \catcode`\`=\active \tabeightspaces % Respect line breaks, % print special symbols as themselves, and % make each space count % must do in this order: \obeylines \uncatcodespecials \sepspaces } % Setup for the @verbatim environment % % Real tab expansion \newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount % \def\starttabbox{\setbox0=\hbox\bgroup} \begingroup \catcode`\^^I=\active \gdef\tabexpand{% \catcode`\^^I=\active \def^^I{\leavevmode\egroup \dimen0=\wd0 % the width so far, or since the previous tab \divide\dimen0 by\tabw \multiply\dimen0 by\tabw % compute previous multiple of \tabw \advance\dimen0 by\tabw % advance to next multiple of \tabw \wd0=\dimen0 \box0 \starttabbox }% } \endgroup \def\setupverbatim{% \nonfillstart \advance\leftskip by -\defbodyindent % Easiest (and conventionally used) font for verbatim \tt \def\par{\leavevmode\egroup\box0\endgraf}% \catcode`\`=\active \tabexpand % Respect line breaks, % print special symbols as themselves, and % make each space count % must do in this order: \obeylines \uncatcodespecials \sepspaces \everypar{\starttabbox}% } % Do the @verb magic: verbatim text is quoted by unique % delimiter characters. Before first delimiter expect a % right brace, after last delimiter expect closing brace: % % \def\doverb'{'#1'}'{#1} % % [Knuth] p. 382; only eat outer {} \begingroup \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] \endgroup % \def\verb{\begingroup\setupverb\doverb} % % % Do the @verbatim magic: define the macro \doverbatim so that % the (first) argument ends when '@end verbatim' is reached, ie: % % \def\doverbatim#1@end verbatim{#1} % % For Texinfo it's a lot easier than for LaTeX, % because texinfo's \verbatim doesn't stop at '\end{verbatim}': % we need not redefine '\', '{' and '}'. % % Inspired by LaTeX's verbatim command set [latex.ltx] % \begingroup \catcode`\ =\active \obeylines % % ignore everything up to the first ^^M, that's the newline at the end % of the @verbatim input line itself. Otherwise we get an extra blank % line in the output. \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% % We really want {...\end verbatim} in the body of the macro, but % without the active space; thus we have to use \xdef and \gobble. \endgroup % \envdef\verbatim{% \setupverbatim\doverbatim } \let\Everbatim = \afterenvbreak % @verbatiminclude FILE - insert text of file in verbatim environment. % \def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude} % \def\doverbatiminclude#1{% {% \makevalueexpandable \setupverbatim \input #1 \afterenvbreak }% } % @copying ... @end copying. % Save the text away for @insertcopying later. % % We save the uninterpreted tokens, rather than creating a box. % Saving the text in a box would be much easier, but then all the % typesetting commands (@smallbook, font changes, etc.) have to be done % beforehand -- and a) we want @copying to be done first in the source % file; b) letting users define the frontmatter in as flexible order as % possible is very desirable. % \def\copying{\checkenv{}\begingroup\scanargctxt\docopying} \def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} % \def\insertcopying{% \begingroup \parindent = 0pt % paragraph indentation looks wrong on title page \scanexp\copyingtext \endgroup } \message{defuns,} % @defun etc. \newskip\defbodyindent \defbodyindent=.4in \newskip\defargsindent \defargsindent=50pt \newskip\deflastargmargin \deflastargmargin=18pt % Start the processing of @deffn: \def\startdefun{% \ifnum\lastpenalty<10000 \medbreak \else % If there are two @def commands in a row, we'll have a \nobreak, % which is there to keep the function description together with its % header. But if there's nothing but headers, we need to allow a % break somewhere. Check specifically for penalty 10002, inserted % by \defargscommonending, instead of 10000, since the sectioning % commands also insert a nobreak penalty, and we don't want to allow % a break between a section heading and a defun. % \ifnum\lastpenalty=10002 \penalty2000 \fi % % Similarly, after a section heading, do not allow a break. % But do insert the glue. \medskip % preceded by discardable penalty, so not a breakpoint \fi % \parindent=0in \advance\leftskip by \defbodyindent \exdentamount=\defbodyindent } \def\dodefunx#1{% % First, check whether we are in the right environment: \checkenv#1% % % As above, allow line break if we have multiple x headers in a row. % It's not a great place, though. \ifnum\lastpenalty=10002 \penalty3000 \fi % % And now, it's time to reuse the body of the original defun: \expandafter\gobbledefun#1% } \def\gobbledefun#1\startdefun{} % \printdefunline \deffnheader{text} % \def\printdefunline#1#2{% \begingroup % call \deffnheader: #1#2 \endheader % common ending: \interlinepenalty = 10000 \advance\rightskip by 0pt plus 1fil \endgraf \nobreak\vskip -\parskip \penalty 10002 % signal to \startdefun and \dodefunx % Some of the @defun-type tags do not enable magic parentheses, % rendering the following check redundant. But we don't optimize. \checkparencounts \endgroup } \def\Edefun{\endgraf\medbreak} % \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; % the only thing remainnig is to define \deffnheader. % \def\makedefun#1{% \expandafter\let\csname E#1\endcsname = \Edefun \edef\temp{\noexpand\domakedefun \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% \temp } % \domakedefun \deffn \deffnx \deffnheader % % Define \deffn and \deffnx, without parameters. % \deffnheader has to be defined explicitly. % \def\domakedefun#1#2#3{% \envdef#1{% \startdefun \parseargusing\activeparens{\printdefunline#3}% }% \def#2{\dodefunx#1}% \def#3% } %%% Untyped functions: % @deffn category name args \makedefun{deffn}{\deffngeneral{}} % @deffn category class name args \makedefun{defop}#1 {\defopon{#1\ \putwordon}} % \defopon {category on}class name args \def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } % \deffngeneral {subind}category name args % \def\deffngeneral#1#2 #3 #4\endheader{% % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}. \dosubind{fn}{\code{#3}}{#1}% \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% } %%% Typed functions: % @deftypefn category type name args \makedefun{deftypefn}{\deftypefngeneral{}} % @deftypeop category class type name args \makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} % \deftypeopon {category on}class type name args \def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } % \deftypefngeneral {subind}category type name args % \def\deftypefngeneral#1#2 #3 #4 #5\endheader{% \dosubind{fn}{\code{#4}}{#1}% \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } %%% Typed variables: % @deftypevr category type var args \makedefun{deftypevr}{\deftypecvgeneral{}} % @deftypecv category class type var args \makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} % \deftypecvof {category of}class type var args \def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } % \deftypecvgeneral {subind}category type var args % \def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% \dosubind{vr}{\code{#4}}{#1}% \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } %%% Untyped variables: % @defvr category var args \makedefun{defvr}#1 {\deftypevrheader{#1} {} } % @defcv category class var args \makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} % \defcvof {category of}class var args \def\defcvof#1#2 {\deftypecvof{#1}#2 {} } %%% Type: % @deftp category name args \makedefun{deftp}#1 #2 #3\endheader{% \doind{tp}{\code{#2}}% \defname{#1}{}{#2}\defunargs{#3\unskip}% } % Remaining @defun-like shortcuts: \makedefun{defun}{\deffnheader{\putwordDeffunc} } \makedefun{defmac}{\deffnheader{\putwordDefmac} } \makedefun{defspec}{\deffnheader{\putwordDefspec} } \makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} } \makedefun{defvar}{\defvrheader{\putwordDefvar} } \makedefun{defopt}{\defvrheader{\putwordDefopt} } \makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } \makedefun{defmethod}{\defopon\putwordMethodon} \makedefun{deftypemethod}{\deftypeopon\putwordMethodon} \makedefun{defivar}{\defcvof\putwordInstanceVariableof} \makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} % \defname, which formats the name of the @def (not the args). % #1 is the category, such as "Function". % #2 is the return type, if any. % #3 is the function name. % % We are followed by (but not passed) the arguments, if any. % \def\defname#1#2#3{% % Get the values of \leftskip and \rightskip as they were outside the @def... \advance\leftskip by -\defbodyindent % % How we'll format the type name. Putting it in brackets helps % distinguish it from the body text that may end up on the next line % just below it. \def\temp{#1}% \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} % % Figure out line sizes for the paragraph shape. % The first line needs space for \box0; but if \rightskip is nonzero, % we need only space for the part of \box0 which exceeds it: \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip % The continuations: \dimen2=\hsize \advance\dimen2 by -\defargsindent % (plain.tex says that \dimen1 should be used only as global.) \parshape 2 0in \dimen0 \defargsindent \dimen2 % % Put the type name to the right margin. \noindent \hbox to 0pt{% \hfil\box0 \kern-\hsize % \hsize has to be shortened this way: \kern\leftskip % Intentionally do not respect \rightskip, since we need the space. }% % % Allow all lines to be underfull without complaint: \tolerance=10000 \hbadness=10000 \exdentamount=\defbodyindent {% % defun fonts. We use typewriter by default (used to be bold) because: % . we're printing identifiers, they should be in tt in principle. % . in languages with many accents, such as Czech or French, it's % common to leave accents off identifiers. The result looks ok in % tt, but exceedingly strange in rm. % . we don't want -- and --- to be treated as ligatures. % . this still does not fix the ?` and !` ligatures, but so far no % one has made identifiers using them :). \df \tt \def\temp{#2}% return value type \ifx\temp\empty\else \tclose{\temp} \fi #3% output function name }% {\rm\enskip}% hskip 0.5 em of \tenrm % \boldbrax % arguments will be output next, if any. } % Print arguments in slanted roman (not ttsl), inconsistently with using % tt for the name. This is because literal text is sometimes needed in % the argument list (groff manual), and ttsl and tt are not very % distinguishable. Prevent hyphenation at `-' chars. % \def\defunargs#1{% % use sl by default (not ttsl), % tt for the names. \df \sl \hyphenchar\font=0 % % On the other hand, if an argument has two dashes (for instance), we % want a way to get ttsl. Let's try @var for that. \let\var=\ttslanted #1% \sl\hyphenchar\font=45 } % We want ()&[] to print specially on the defun line. % \def\activeparens{% \catcode`\(=\active \catcode`\)=\active \catcode`\[=\active \catcode`\]=\active \catcode`\&=\active } % Make control sequences which act like normal parenthesis chars. \let\lparen = ( \let\rparen = ) % Be sure that we always have a definition for `(', etc. For example, % if the fn name has parens in it, \boldbrax will not be in effect yet, % so TeX would otherwise complain about undefined control sequence. { \activeparens \global\let(=\lparen \global\let)=\rparen \global\let[=\lbrack \global\let]=\rbrack \global\let& = \& \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} \gdef\magicamp{\let&=\amprm} } \newcount\parencount % If we encounter &foo, then turn on ()-hacking afterwards \newif\ifampseen \def\amprm#1 {\ampseentrue{\bf\ }} \def\parenfont{% \ifampseen % At the first level, print parens in roman, % otherwise use the default font. \ifnum \parencount=1 \rm \fi \else % The \sf parens (in \boldbrax) actually are a little bolder than % the contained text. This is especially needed for [ and ] . \sf \fi } \def\infirstlevel#1{% \ifampseen \ifnum\parencount=1 #1% \fi \fi } \def\bfafterword#1 {#1 \bf} \def\opnr{% \global\advance\parencount by 1 {\parenfont(}% \infirstlevel \bfafterword } \def\clnr{% {\parenfont)}% \infirstlevel \sl \global\advance\parencount by -1 } \newcount\brackcount \def\lbrb{% \global\advance\brackcount by 1 {\bf[}% } \def\rbrb{% {\bf]}% \global\advance\brackcount by -1 } \def\checkparencounts{% \ifnum\parencount=0 \else \badparencount \fi \ifnum\brackcount=0 \else \badbrackcount \fi } \def\badparencount{% \errmessage{Unbalanced parentheses in @def}% \global\parencount=0 } \def\badbrackcount{% \errmessage{Unbalanced square braces in @def}% \global\brackcount=0 } \message{macros,} % @macro. % To do this right we need a feature of e-TeX, \scantokens, % which we arrange to emulate with a temporary file in ordinary TeX. \ifx\eTeXversion\undefined \newwrite\macscribble \def\scantokens#1{% \toks0={#1}% \immediate\openout\macscribble=\jobname.tmp \immediate\write\macscribble{\the\toks0}% \immediate\closeout\macscribble \input \jobname.tmp } \fi \def\scanmacro#1{% \begingroup \newlinechar`\^^M \let\xeatspaces\eatspaces % Undo catcode changes of \startcontents and \doprintindex \catcode`\@=0 \catcode`\\=\other \escapechar=`\@ % ... and \example \spaceisspace % % Append \endinput to make sure that TeX does not see the ending newline. % % I've verified that it is necessary both for e-TeX and for ordinary TeX % --kasal, 29nov03 \scantokens{#1\endinput}% \endgroup } \def\scanexp#1{% \edef\temp{\noexpand\scanmacro{#1}}% \temp } \newcount\paramno % Count of parameters \newtoks\macname % Macro name \newif\ifrecursive % Is it recursive? \def\macrolist{} % List of all defined macros in the form % \do\macro1\do\macro2... % Utility routines. % This does \let #1 = #2, except with \csnames. \def\cslet#1#2{% \expandafter\expandafter \expandafter\let \expandafter\expandafter \csname#1\endcsname \csname#2\endcsname} % Trim leading and trailing spaces off a string. % Concepts from aro-bend problem 15 (see CTAN). {\catcode`\@=11 \gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} \gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} \gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} \def\unbrace#1{#1} \unbrace{\gdef\trim@@@ #1 } #2@{#1} } % Trim a single trailing ^^M off a string. {\catcode`\^^M=\other \catcode`\Q=3% \gdef\eatcr #1{\eatcra #1Q^^MQ}% \gdef\eatcra#1^^MQ{\eatcrb#1Q}% \gdef\eatcrb#1Q#2Q{#1}% } % Macro bodies are absorbed as an argument in a context where % all characters are catcode 10, 11 or 12, except \ which is active % (as in normal texinfo). It is necessary to change the definition of \. % It's necessary to have hard CRs when the macro is executed. This is % done by making ^^M (\endlinechar) catcode 12 when reading the macro % body, and then making it the \newlinechar in \scanmacro. \def\scanctxt{% \catcode`\~=\other \catcode`\^=\other \catcode`\_=\other \catcode`\|=\other \catcode`\<=\other \catcode`\>=\other \catcode`\+=\other \catcode`\@=\other } \def\scanargctxt{% \scanctxt \catcode`\\=\other \catcode`\^^M=\other } \def\macrobodyctxt{% \scanctxt \catcode`\{=\other \catcode`\}=\other \catcode`\^^M=\other \usembodybackslash } \def\macroargctxt{% \scanctxt \catcode`\\=\other } % \mbodybackslash is the definition of \ in @macro bodies. % It maps \foo\ => \csname macarg.foo\endcsname => #N % where N is the macro parameter number. % We define \csname macarg.\endcsname to be \realbackslash, so % \\ in macro replacement text gets you a backslash. {\catcode`@=0 @catcode`@\=@active @gdef@usembodybackslash{@let\=@mbodybackslash} @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} } \expandafter\def\csname macarg.\endcsname{\realbackslash} \def\macro{\recursivefalse\parsearg\macroxxx} \def\rmacro{\recursivetrue\parsearg\macroxxx} \def\macroxxx#1{% \getargs{#1}% now \macname is the macname and \argl the arglist \ifx\argl\empty % no arguments \paramno=0% \else \expandafter\parsemargdef \argl;% \fi \if1\csname ismacro.\the\macname\endcsname \message{Warning: redefining \the\macname}% \else \expandafter\ifx\csname \the\macname\endcsname \relax \else \errmessage{Macro name \the\macname\space already defined}\fi \global\cslet{macsave.\the\macname}{\the\macname}% \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% % Add the macroname to \macrolist \toks0 = \expandafter{\macrolist\do}% \xdef\macrolist{\the\toks0 \expandafter\noexpand\csname\the\macname\endcsname}% \fi \begingroup \macrobodyctxt \ifrecursive \expandafter\parsermacbody \else \expandafter\parsemacbody \fi} \parseargdef\unmacro{% \if1\csname ismacro.#1\endcsname \global\cslet{#1}{macsave.#1}% \global\expandafter\let \csname ismacro.#1\endcsname=0% % Remove the macro name from \macrolist: \begingroup \expandafter\let\csname#1\endcsname \relax \let\do\unmacrodo \xdef\macrolist{\macrolist}% \endgroup \else \errmessage{Macro #1 not defined}% \fi } % Called by \do from \dounmacro on each macro. The idea is to omit any % macro definitions that have been changed to \relax. % \def\unmacrodo#1{% \ifx#1\relax % remove this \else \noexpand\do \noexpand #1% \fi } % This makes use of the obscure feature that if the last token of a % is #, then the preceding argument is delimited by % an opening brace, and that opening brace is not consumed. \def\getargs#1{\getargsxxx#1{}} \def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} \def\getmacname #1 #2\relax{\macname={#1}} \def\getmacargs#1{\def\argl{#1}} % Parse the optional {params} list. Set up \paramno and \paramlist % so \defmacro knows what to do. Define \macarg.blah for each blah % in the params list, to be ##N where N is the position in that list. % That gets used by \mbodybackslash (above). % We need to get `macro parameter char #' into several definitions. % The technique used is stolen from LaTeX: let \hash be something % unexpandable, insert that wherever you need a #, and then redefine % it to # just before using the token list produced. % % The same technique is used to protect \eatspaces till just before % the macro is used. \def\parsemargdef#1;{\paramno=0\def\paramlist{}% \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} \def\parsemargdefxxx#1,{% \if#1;\let\next=\relax \else \let\next=\parsemargdefxxx \advance\paramno by 1% \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname {\xeatspaces{\hash\the\paramno}}% \edef\paramlist{\paramlist\hash\the\paramno,}% \fi\next} % These two commands read recursive and nonrecursive macro bodies. % (They're different since rec and nonrec macros end differently.) \long\def\parsemacbody#1@end macro% {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% \long\def\parsermacbody#1@end rmacro% {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% % This defines the macro itself. There are six cases: recursive and % nonrecursive macros of zero, one, and many arguments. % Much magic with \expandafter here. % \xdef is used so that macro definitions will survive the file % they're defined in; @include reads the file inside a group. \def\defmacro{% \let\hash=##% convert placeholders to macro parameter chars \ifrecursive \ifcase\paramno % 0 \expandafter\xdef\csname\the\macname\endcsname{% \noexpand\scanmacro{\temp}}% \or % 1 \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\braceorline \expandafter\noexpand\csname\the\macname xxx\endcsname}% \expandafter\xdef\csname\the\macname xxx\endcsname##1{% \egroup\noexpand\scanmacro{\temp}}% \else % many \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\csname\the\macname xx\endcsname}% \expandafter\xdef\csname\the\macname xx\endcsname##1{% \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% \expandafter\expandafter \expandafter\xdef \expandafter\expandafter \csname\the\macname xxx\endcsname \paramlist{\egroup\noexpand\scanmacro{\temp}}% \fi \else \ifcase\paramno % 0 \expandafter\xdef\csname\the\macname\endcsname{% \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \or % 1 \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\braceorline \expandafter\noexpand\csname\the\macname xxx\endcsname}% \expandafter\xdef\csname\the\macname xxx\endcsname##1{% \egroup \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \else % many \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \expandafter\noexpand\csname\the\macname xx\endcsname}% \expandafter\xdef\csname\the\macname xx\endcsname##1{% \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% \expandafter\expandafter \expandafter\xdef \expandafter\expandafter \csname\the\macname xxx\endcsname \paramlist{% \egroup \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \fi \fi} \def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} % \braceorline decides whether the next nonwhitespace character is a % {. If so it reads up to the closing }, if not, it reads the whole % line. Whatever was read is then fed to the next control sequence % as an argument (by \parsebrace or \parsearg) \def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx} \def\braceorlinexxx{% \ifx\nchar\bgroup\else \expandafter\parsearg \fi \next} % We want to disable all macros during \shipout so that they are not % expanded by \write. \def\turnoffmacros{\begingroup \def\do##1{\let\noexpand##1=\relax}% \edef\next{\macrolist}\expandafter\endgroup\next} % For \indexnofonts, we need to get rid of all macros, leaving only the % arguments (if present). Of course this is not nearly correct, but it % is the best we can do for now. makeinfo does not expand macros in the % argument to @deffn, which ends up writing an index entry, and texindex % isn't prepared for an index sort entry that starts with \. % % Since macro invocations are followed by braces, we can just redefine them % to take a single TeX argument. The case of a macro invocation that % goes to end-of-line is not handled. % \def\emptyusermacros{\begingroup \def\do##1{\let\noexpand##1=\noexpand\asis}% \edef\next{\macrolist}\expandafter\endgroup\next} % @alias. % We need some trickery to remove the optional spaces around the equal % sign. Just make them active and then expand them all to nothing. \def\alias{\parseargusing\obeyspaces\aliasxxx} \def\aliasxxx #1{\aliasyyy#1\relax} \def\aliasyyy #1=#2\relax{% {% \expandafter\let\obeyedspace=\empty \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% }% \next } \message{cross references,} \newwrite\auxfile \newif\ifhavexrefs % True if xref values are known. \newif\ifwarnedxrefs % True if we warned once that they aren't known. % @inforef is relatively simple. \def\inforef #1{\inforefzzz #1,,,,**} \def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, node \samp{\ignorespaces#1{}}} % @node's only job in TeX is to define \lastnode, which is used in % cross-references. The @node line might or might not have commas, and % might or might not have spaces before the first comma, like: % @node foo , bar , ... % We don't want such trailing spaces in the node name. % \parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse} % % also remove a trailing comma, in case of something like this: % @node Help-Cross, , , Cross-refs \def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} \def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} \let\nwnode=\node \let\lastnode=\empty % Write a cross-reference definition for the current node. #1 is the % type (Ynumbered, Yappendix, Ynothing). % \def\donoderef#1{% \ifx\lastnode\empty\else \setref{\lastnode}{#1}% \global\let\lastnode=\empty \fi } % @anchor{NAME} -- define xref target at arbitrary point. % \newcount\savesfregister % \def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} \def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} \def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} % \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an % anchor), which consists of three parts: % 1) NAME-title - the current sectioning name taken from \thissection, % or the anchor name. % 2) NAME-snt - section number and type, passed as the SNT arg, or % empty for anchors. % 3) NAME-pg - the page number. % % This is called from \donoderef, \anchor, and \dofloat. In the case of % floats, there is an additional part, which is not written here: % 4) NAME-lof - the text as it should appear in a @listoffloats. % \def\setref#1#2{% \pdfmkdest{#1}% \iflinks {% \atdummies % preserve commands, but don't expand them \turnoffactive \otherbackslash \edef\writexrdef##1##2{% \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef ##1}{##2}}% these are parameters of \writexrdef }% \toks0 = \expandafter{\thissection}% \immediate \writexrdef{title}{\the\toks0 }% \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. \writexrdef{pg}{\folio}% will be written later, during \shipout }% \fi } % @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is % the node name, #2 the name of the Info cross-reference, #3 the printed % node name, #4 the name of the Info file, #5 the name of the printed % manual. All but the node name can be omitted. % \def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} \def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} \def\ref#1{\xrefX[#1,,,,,,,]} \def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup \unsepspaces \def\printedmanual{\ignorespaces #5}% \def\printedrefname{\ignorespaces #3}% \setbox1=\hbox{\printedmanual\unskip}% \setbox0=\hbox{\printedrefname\unskip}% \ifdim \wd0 = 0pt % No printed node name was explicitly given. \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax % Use the node name inside the square brackets. \def\printedrefname{\ignorespaces #1}% \else % Use the actual chapter/section title appear inside % the square brackets. Use the real section title if we have it. \ifdim \wd1 > 0pt % It is in another manual, so we don't have it. \def\printedrefname{\ignorespaces #1}% \else \ifhavexrefs % We know the real title if we have the xref values. \def\printedrefname{\refx{#1-title}{}}% \else % Otherwise just copy the Info node name. \def\printedrefname{\ignorespaces #1}% \fi% \fi \fi \fi % % Make link in pdf output. \ifpdf \leavevmode \getfilename{#4}% {\turnoffactive \otherbackslash \ifnum\filenamelength>0 \startlink attr{/Border [0 0 0]}% goto file{\the\filename.pdf} name{#1}% \else \startlink attr{/Border [0 0 0]}% goto name{\pdfmkpgn{#1}}% \fi }% \linkcolor \fi % % Float references are printed completely differently: "Figure 1.2" % instead of "[somenode], p.3". We distinguish them by the % LABEL-title being set to a magic string. {% % Have to otherify everything special to allow the \csname to % include an _ in the xref name, etc. \indexnofonts \turnoffactive \otherbackslash \expandafter\global\expandafter\let\expandafter\Xthisreftitle \csname XR#1-title\endcsname }% \iffloat\Xthisreftitle % If the user specified the print name (third arg) to the ref, % print it instead of our usual "Figure 1.2". \ifdim\wd0 = 0pt \refx{#1-snt}% \else \printedrefname \fi % % if the user also gave the printed manual name (fifth arg), append % "in MANUALNAME". \ifdim \wd1 > 0pt \space \putwordin{} \cite{\printedmanual}% \fi \else % node/anchor (non-float) references. % % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not % insert empty discretionaries after hyphens, which means that it will % not find a line break at a hyphen in a node names. Since some manuals % are best written with fairly long node names, containing hyphens, this % is a loss. Therefore, we give the text of the node name again, so it % is as if TeX is seeing it for the first time. \ifdim \wd1 > 0pt \putwordsection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}% \else % _ (for example) has to be the character _ for the purposes of the % control sequence corresponding to the node, but it has to expand % into the usual \leavevmode...\vrule stuff for purposes of % printing. So we \turnoffactive for the \refx-snt, back on for the % printing, back off for the \refx-pg. {\turnoffactive \otherbackslash % Only output a following space if the -snt ref is nonempty; for % @unnumbered and @anchor, it won't be. \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi }% % output the `[mynode]' via a macro so it can be overridden. \xrefprintnodename\printedrefname % % But we always want a comma and a space: ,\space % % output the `page 3'. \turnoffactive \otherbackslash \putwordpage\tie\refx{#1-pg}{}% \fi \fi \endlink \endgroup} % This macro is called from \xrefX for the `[nodename]' part of xref % output. It's a separate macro only so it can be changed more easily, % since square brackets don't work well in some documents. Particularly % one that Bob is working on :). % \def\xrefprintnodename#1{[#1]} % Things referred to by \setref. % \def\Ynothing{} \def\Yomitfromtoc{} \def\Ynumbered{% \ifnum\secno=0 \putwordChapter@tie \the\chapno \else \ifnum\subsecno=0 \putwordSection@tie \the\chapno.\the\secno \else \ifnum\subsubsecno=0 \putwordSection@tie \the\chapno.\the\secno.\the\subsecno \else \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno \fi\fi\fi } \def\Yappendix{% \ifnum\secno=0 \putwordAppendix@tie @char\the\appendixno{}% \else \ifnum\subsecno=0 \putwordSection@tie @char\the\appendixno.\the\secno \else \ifnum\subsubsecno=0 \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno \else \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno \fi\fi\fi } % Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. % If its value is nonempty, SUFFIX is output afterward. % \def\refx#1#2{% {% \indexnofonts \otherbackslash \expandafter\global\expandafter\let\expandafter\thisrefX \csname XR#1\endcsname }% \ifx\thisrefX\relax % If not defined, say something at least. \angleleft un\-de\-fined\angleright \iflinks \ifhavexrefs \message{\linenumber Undefined cross reference `#1'.}% \else \ifwarnedxrefs\else \global\warnedxrefstrue \message{Cross reference values unknown; you must run TeX again.}% \fi \fi \fi \else % It's defined, so just use it. \thisrefX \fi #2% Output the suffix in any case. } % This is the macro invoked by entries in the aux file. Usually it's % just a \def (we prepend XR to the control sequence name to avoid % collisions). But if this is a float type, we have more work to do. % \def\xrdef#1#2{% \expandafter\gdef\csname XR#1\endcsname{#2}% remember this xref value. % % Was that xref control sequence that we just defined for a float? \expandafter\iffloat\csname XR#1\endcsname % it was a float, and we have the (safe) float type in \iffloattype. \expandafter\let\expandafter\floatlist \csname floatlist\iffloattype\endcsname % % Is this the first time we've seen this float type? \expandafter\ifx\floatlist\relax \toks0 = {\do}% yes, so just \do \else % had it before, so preserve previous elements in list. \toks0 = \expandafter{\floatlist\do}% \fi % % Remember this xref in the control sequence \floatlistFLOATTYPE, % for later use in \listoffloats. \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0{#1}}% \fi } % Read the last existing aux file, if any. No error if none exists. % \def\tryauxfile{% \openin 1 \jobname.aux \ifeof 1 \else \readauxfile \global\havexrefstrue \fi \closein 1 } \def\readauxfile{\begingroup \catcode`\^^@=\other \catcode`\^^A=\other \catcode`\^^B=\other \catcode`\^^C=\other \catcode`\^^D=\other \catcode`\^^E=\other \catcode`\^^F=\other \catcode`\^^G=\other \catcode`\^^H=\other \catcode`\^^K=\other \catcode`\^^L=\other \catcode`\^^N=\other \catcode`\^^P=\other \catcode`\^^Q=\other \catcode`\^^R=\other \catcode`\^^S=\other \catcode`\^^T=\other \catcode`\^^U=\other \catcode`\^^V=\other \catcode`\^^W=\other \catcode`\^^X=\other \catcode`\^^Z=\other \catcode`\^^[=\other \catcode`\^^\=\other \catcode`\^^]=\other \catcode`\^^^=\other \catcode`\^^_=\other % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. % in xref tags, i.e., node names. But since ^^e4 notation isn't % supported in the main text, it doesn't seem desirable. Furthermore, % that is not enough: for node names that actually contain a ^ % character, we would end up writing a line like this: 'xrdef {'hat % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first % argument, and \hat is not an expandable control sequence. It could % all be worked out, but why? Either we support ^^ or we don't. % % The other change necessary for this was to define \auxhat: % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter % and then to call \auxhat in \setq. % \catcode`\^=\other % % Special characters. Should be turned off anyway, but... \catcode`\~=\other \catcode`\[=\other \catcode`\]=\other \catcode`\"=\other \catcode`\_=\other \catcode`\|=\other \catcode`\<=\other \catcode`\>=\other \catcode`\$=\other \catcode`\#=\other \catcode`\&=\other \catcode`\%=\other \catcode`+=\other % avoid \+ for paranoia even though we've turned it off % % This is to support \ in node names and titles, since the \ % characters end up in a \csname. It's easier than % leaving it active and making its active definition an actual \ % character. What I don't understand is why it works in the *value* % of the xrdef. Seems like it should be a catcode12 \, and that % should not typeset properly. But it works, so I'm moving on for % now. --karl, 15jan04. \catcode`\\=\other % % Make the characters 128-255 be printing characters. {% \count 1=128 \def\loop{% \catcode\count 1=\other \advance\count 1 by 1 \ifnum \count 1<256 \loop \fi }% }% % % @ is our escape character in .aux files, and we need braces. \catcode`\{=1 \catcode`\}=2 \catcode`\@=0 % \input \jobname.aux \endgroup} \message{insertions,} % including footnotes. \newcount \footnoteno % The trailing space in the following definition for supereject is % vital for proper filling; pages come out unaligned when you do a % pagealignmacro call if that space before the closing brace is % removed. (Generally, numeric constants should always be followed by a % space to prevent strange expansion errors.) \def\supereject{\par\penalty -20000\footnoteno =0 } % @footnotestyle is meaningful for info output only. \let\footnotestyle=\comment {\catcode `\@=11 % % Auto-number footnotes. Otherwise like plain. \gdef\footnote{% \let\indent=\ptexindent \let\noindent=\ptexnoindent \global\advance\footnoteno by \@ne \edef\thisfootno{$^{\the\footnoteno}$}% % % In case the footnote comes at the end of a sentence, preserve the % extra spacing after we do the footnote number. \let\@sf\empty \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi % % Remove inadvertent blank space before typesetting the footnote number. \unskip \thisfootno\@sf \dofootnote }% % Don't bother with the trickery in plain.tex to not require the % footnote text as a parameter. Our footnotes don't need to be so general. % % Oh yes, they do; otherwise, @ifset (and anything else that uses % \parseargline) fails inside footnotes because the tokens are fixed when % the footnote is read. --karl, 16nov96. % \gdef\dofootnote{% \insert\footins\bgroup % We want to typeset this text as a normal paragraph, even if the % footnote reference occurs in (for example) a display environment. % So reset some parameters. \hsize=\pagewidth \interlinepenalty\interfootnotelinepenalty \splittopskip\ht\strutbox % top baseline for broken footnotes \splitmaxdepth\dp\strutbox \floatingpenalty\@MM \leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip \parindent\defaultparindent % \smallfonts \rm % % Because we use hanging indentation in footnotes, a @noindent appears % to exdent this text, so make it be a no-op. makeinfo does not use % hanging indentation so @noindent can still be needed within footnote % text after an @example or the like (not that this is good style). \let\noindent = \relax % % Hang the footnote text off the number. Use \everypar in case the % footnote extends for more than one paragraph. \everypar = {\hang}% \textindent{\thisfootno}% % % Don't crash into the line above the footnote text. Since this % expands into a box, it must come within the paragraph, lest it % provide a place where TeX can split the footnote. \footstrut \futurelet\next\fo@t } }%end \catcode `\@=11 % In case a @footnote appears in a vbox, save the footnote text and create % the real \insert just after the vbox finished. Otherwise, the insertion % would be lost. % Similarily, if a @footnote appears inside an alignment, save the footnote % text to a box and make the \insert when a row of the table is finished. % And the same can be done for other insert classes. --kasal, 16nov03. % Replace the \insert primitive by a cheating macro. % Deeper inside, just make sure that the saved insertions are not spilled % out prematurely. % \def\startsavinginserts{% \ifx \insert\ptexinsert \let\insert\saveinsert \else \let\checkinserts\relax \fi } % This \insert replacement works for both \insert\footins{foo} and % \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}. % \def\saveinsert#1{% \edef\next{\noexpand\savetobox \makeSAVEname#1}% \afterassignment\next % swallow the left brace \let\temp = } \def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}} \def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1} \def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi} \def\placesaveins#1{% \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname {\box#1}% } % eat @SAVE -- beware, all of them have catcode \other: { \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-) \gdef\gobblesave @SAVE{} } % initialization: \def\newsaveins #1{% \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}% \next } \def\newsaveinsX #1{% \csname newbox\endcsname #1% \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts \checksaveins #1}% } % initialize: \let\checkinserts\empty \newsaveins\footins \newsaveins\margin % @image. We use the macros from epsf.tex to support this. % If epsf.tex is not installed and @image is used, we complain. % % Check for and read epsf.tex up front. If we read it only at @image % time, we might be inside a group, and then its definitions would get % undone and the next image would fail. \openin 1 = epsf.tex \ifeof 1 \else % Do not bother showing banner with epsf.tex v2.7k (available in % doc/epsf.tex and on ctan). \def\epsfannounce{\toks0 = }% \input epsf.tex \fi \closein 1 % % We will only complain once about lack of epsf.tex. \newif\ifwarnednoepsf \newhelp\noepsfhelp{epsf.tex must be installed for images to work. It is also included in the Texinfo distribution, or you can get it from ftp://tug.org/tex/epsf.tex.} % \def\image#1{% \ifx\epsfbox\undefined \ifwarnednoepsf \else \errhelp = \noepsfhelp \errmessage{epsf.tex not found, images will be ignored}% \global\warnednoepsftrue \fi \else \imagexxx #1,,,,,\finish \fi } % % Arguments to @image: % #1 is (mandatory) image filename; we tack on .eps extension. % #2 is (optional) width, #3 is (optional) height. % #4 is (ignored optional) html alt text. % #5 is (ignored optional) extension. % #6 is just the usual extra ignored arg for parsing this stuff. \newif\ifimagevmode \def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup \catcode`\^^M = 5 % in case we're inside an example \normalturnoffactive % allow _ et al. in names % If the image is by itself, center it. \ifvmode \imagevmodetrue \nobreak\bigskip % Usually we'll have text after the image which will insert % \parskip glue, so insert it here too to equalize the space % above and below. \nobreak\vskip\parskip \nobreak \line\bgroup\hss \fi % % Output the image. \ifpdf \dopdfimage{#1}{#2}{#3}% \else % \epsfbox itself resets \epsf?size at each figure. \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi \epsfbox{#1.eps}% \fi % \ifimagevmode \hss \egroup \bigbreak \fi % space after the image \endgroup} % @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables, % etc. We don't actually implement floating yet, we always include the % float "here". But it seemed the best name for the future. % \envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish} % There may be a space before second and/or third parameter; delete it. \def\eatcommaspace#1, {#1,} % #1 is the optional FLOATTYPE, the text label for this float, typically % "Figure", "Table", "Example", etc. Can't contain commas. If omitted, % this float will not be numbered and cannot be referred to. % % #2 is the optional xref label. Also must be present for the float to % be referable. % % #3 is the optional positioning argument; for now, it is ignored. It % will somehow specify the positions allowed to float to (here, top, bottom). % % We keep a separate counter for each FLOATTYPE, which we reset at each % chapter-level command. \let\resetallfloatnos=\empty % \def\dofloat#1,#2,#3,#4\finish{% \let\thiscaption=\empty \let\thisshortcaption=\empty % % don't lose footnotes inside @float. % % BEWARE: when the floats start float, we have to issue warning whenever an % insert appears inside a float which could possibly float. --kasal, 26may04 % \startsavinginserts % % We can't be used inside a paragraph. \par % \vtop\bgroup \def\floattype{#1}% \def\floatlabel{#2}% \def\floatloc{#3}% we do nothing with this yet. % \ifx\floattype\empty \let\safefloattype=\empty \else {% % the floattype might have accents or other special characters, % but we need to use it in a control sequence name. \indexnofonts \turnoffactive \xdef\safefloattype{\floattype}% }% \fi % % If label is given but no type, we handle that as the empty type. \ifx\floatlabel\empty \else % We want each FLOATTYPE to be numbered separately (Figure 1, % Table 1, Figure 2, ...). (And if no label, no number.) % \expandafter\getfloatno\csname\safefloattype floatno\endcsname \global\advance\floatno by 1 % {% % This magic value for \thissection is output by \setref as the % XREFLABEL-title value. \xrefX uses it to distinguish float % labels (which have a completely different output format) from % node and anchor labels. And \xrdef uses it to construct the % lists of floats. % \edef\thissection{\floatmagic=\safefloattype}% \setref{\floatlabel}{Yfloat}% }% \fi % % start with \parskip glue, I guess. \vskip\parskip % % Don't suppress indentation if a float happens to start a section. \restorefirstparagraphindent } % we have these possibilities: % @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap % @float Foo,lbl & no caption: Foo 1.1 % @float Foo & @caption{Cap}: Foo: Cap % @float Foo & no caption: Foo % @float ,lbl & Caption{Cap}: 1.1: Cap % @float ,lbl & no caption: 1.1 % @float & @caption{Cap}: Cap % @float & no caption: % \def\Efloat{% \let\floatident = \empty % % In all cases, if we have a float type, it comes first. \ifx\floattype\empty \else \def\floatident{\floattype}\fi % % If we have an xref label, the number comes next. \ifx\floatlabel\empty \else \ifx\floattype\empty \else % if also had float type, need tie first. \appendtomacro\floatident{\tie}% \fi % the number. \appendtomacro\floatident{\chaplevelprefix\the\floatno}% \fi % % Start the printed caption with what we've constructed in % \floatident, but keep it separate; we need \floatident again. \let\captionline = \floatident % \ifx\thiscaption\empty \else \ifx\floatident\empty \else \appendtomacro\captionline{: }% had ident, so need a colon between \fi % % caption text. \appendtomacro\captionline{\scanexp\thiscaption}% \fi % % If we have anything to print, print it, with space before. % Eventually this needs to become an \insert. \ifx\captionline\empty \else \vskip.5\parskip \captionline \fi % % If have an xref label, write the list of floats info. Do this % after the caption, to avoid chance of it being a breakpoint. \ifx\floatlabel\empty \else % Write the text that goes in the lof to the aux file as % \floatlabel-lof. Besides \floatident, we include the short % caption if specified, else the full caption if specified, else nothing. {% \atdummies \turnoffactive \otherbackslash \immediate\write\auxfile{@xrdef{\floatlabel-lof}{% \floatident \ifx\thisshortcaption\empty \ifx\thiscaption\empty \else : \thiscaption \fi \else : \thisshortcaption \fi }}% }% \fi % % Space below caption, if we printed anything. \ifx\printedsomething\empty \else \vskip\parskip \fi \egroup % end of \vtop % % place the captured inserts % % BEWARE: when the floats start float, we have to issue warning whenever an % insert appears inside a float which could possibly float. --kasal, 26may04 % \checkinserts } % Append the tokens #2 to the definition of macro #1, not expanding either. % \def\appendtomacro#1#2{% \expandafter\def\expandafter#1\expandafter{#1#2}% } % @caption, @shortcaption % \def\caption{\docaption\thiscaption} \def\shortcaption{\docaption\thisshortcaption} \def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption} \def\defcaption#1#2{\egroup \def#1{#2}} % The parameter is the control sequence identifying the counter we are % going to use. Create it if it doesn't exist and assign it to \floatno. \def\getfloatno#1{% \ifx#1\relax % Haven't seen this figure type before. \csname newcount\endcsname #1% % % Remember to reset this floatno at the next chap. \expandafter\gdef\expandafter\resetallfloatnos \expandafter{\resetallfloatnos #1=0 }% \fi \let\floatno#1% } % \setref calls this to get the XREFLABEL-snt value. We want an @xref % to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we % first read the @float command. % \def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}% % Magic string used for the XREFLABEL-title value, so \xrefX can % distinguish floats from other xref types. \def\floatmagic{!!float!!} % #1 is the control sequence we are passed; we expand into a conditional % which is true if #1 represents a float ref. That is, the magic % \thissection value which we \setref above. % \def\iffloat#1{\expandafter\doiffloat#1==\finish} % % #1 is (maybe) the \floatmagic string. If so, #2 will be the % (safe) float type for this float. We set \iffloattype to #2. % \def\doiffloat#1=#2=#3\finish{% \def\temp{#1}% \def\iffloattype{#2}% \ifx\temp\floatmagic } % @listoffloats FLOATTYPE - print a list of floats like a table of contents. % \parseargdef\listoffloats{% \def\floattype{#1}% floattype {% % the floattype might have accents or other special characters, % but we need to use it in a control sequence name. \indexnofonts \turnoffactive \xdef\safefloattype{\floattype}% }% % % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE. \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax \ifhavexrefs % if the user said @listoffloats foo but never @float foo. \message{\linenumber No `\safefloattype' floats to list.}% \fi \else \begingroup \leftskip=\tocindent % indent these entries like a toc \let\do=\listoffloatsdo \csname floatlist\safefloattype\endcsname \endgroup \fi } % This is called on each entry in a list of floats. We're passed the % xref label, in the form LABEL-title, which is how we save it in the % aux file. We strip off the -title and look up \XRLABEL-lof, which % has the text we're supposed to typeset here. % % Figures without xref labels will not be included in the list (since % they won't appear in the aux file). % \def\listoffloatsdo#1{\listoffloatsdoentry#1\finish} \def\listoffloatsdoentry#1-title\finish{{% % Can't fully expand XR#1-lof because it can contain anything. Just % pass the control sequence. On the other hand, XR#1-pg is just the % page number, and we want to fully expand that so we can get a link % in pdf output. \toksA = \expandafter{\csname XR#1-lof\endcsname}% % % use the same \entry macro we use to generate the TOC and index. \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}% \writeentry }} \message{localization,} % and i18n. % @documentlanguage is usually given very early, just after % @setfilename. If done too late, it may not override everything % properly. Single argument is the language abbreviation. % It would be nice if we could set up a hyphenation file here. % \parseargdef\documentlanguage{% \tex % read txi-??.tex file in plain TeX. % Read the file if it exists. \openin 1 txi-#1.tex \ifeof 1 \errhelp = \nolanghelp \errmessage{Cannot read language file txi-#1.tex}% \else \input txi-#1.tex \fi \closein 1 \endgroup } \newhelp\nolanghelp{The given language definition file cannot be found or is empty. Maybe you need to install it? In the current directory should work if nowhere else does.} % @documentencoding should change something in TeX eventually, most % likely, but for now just recognize it. \let\documentencoding = \comment % Page size parameters. % \newdimen\defaultparindent \defaultparindent = 15pt \chapheadingskip = 15pt plus 4pt minus 2pt \secheadingskip = 12pt plus 3pt minus 2pt \subsecheadingskip = 9pt plus 2pt minus 2pt % Prevent underfull vbox error messages. \vbadness = 10000 % Don't be so finicky about underfull hboxes, either. \hbadness = 2000 % Following George Bush, just get rid of widows and orphans. \widowpenalty=10000 \clubpenalty=10000 % Use TeX 3.0's \emergencystretch to help line breaking, but if we're % using an old version of TeX, don't do anything. We want the amount of % stretch added to depend on the line length, hence the dependence on % \hsize. We call this whenever the paper size is set. % \def\setemergencystretch{% \ifx\emergencystretch\thisisundefined % Allow us to assign to \emergencystretch anyway. \def\emergencystretch{\dimen0}% \else \emergencystretch = .15\hsize \fi } % Parameters in order: 1) textheight; 2) textwidth; 3) voffset; % 4) hoffset; 5) binding offset; 6) topskip; 7) physical page height; 8) % physical page width. % % We also call \setleading{\textleading}, so the caller should define % \textleading. The caller should also set \parskip. % \def\internalpagesizes#1#2#3#4#5#6#7#8{% \voffset = #3\relax \topskip = #6\relax \splittopskip = \topskip % \vsize = #1\relax \advance\vsize by \topskip \outervsize = \vsize \advance\outervsize by 2\topandbottommargin \pageheight = \vsize % \hsize = #2\relax \outerhsize = \hsize \advance\outerhsize by 0.5in \pagewidth = \hsize % \normaloffset = #4\relax \bindingoffset = #5\relax % \ifpdf \pdfpageheight #7\relax \pdfpagewidth #8\relax \fi % \setleading{\textleading} % \parindent = \defaultparindent \setemergencystretch } % @letterpaper (the default). \def\letterpaper{{\globaldefs = 1 \parskip = 3pt plus 2pt minus 1pt \textleading = 13.2pt % % If page is nothing but text, make it come out even. \internalpagesizes{46\baselineskip}{6in}% {\voffset}{.25in}% {\bindingoffset}{36pt}% {11in}{8.5in}% }} % Use @smallbook to reset parameters for 7x9.5 (or so) format. \def\smallbook{{\globaldefs = 1 \parskip = 2pt plus 1pt \textleading = 12pt % \internalpagesizes{7.5in}{5in}% {\voffset}{.25in}% {\bindingoffset}{16pt}% {9.25in}{7in}% % \lispnarrowing = 0.3in \tolerance = 700 \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = .5cm }} % Use @afourpaper to print on European A4 paper. \def\afourpaper{{\globaldefs = 1 \parskip = 3pt plus 2pt minus 1pt \textleading = 13.2pt % % Double-side printing via postscript on Laserjet 4050 % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. % To change the settings for a different printer or situation, adjust % \normaloffset until the front-side and back-side texts align. Then % do the same for \bindingoffset. You can set these for testing in % your texinfo source file like this: % @tex % \global\normaloffset = -6mm % \global\bindingoffset = 10mm % @end tex \internalpagesizes{51\baselineskip}{160mm} {\voffset}{\hoffset}% {\bindingoffset}{44pt}% {297mm}{210mm}% % \tolerance = 700 \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = 5mm }} % Use @afivepaper to print on European A5 paper. % From romildo@urano.iceb.ufop.br, 2 July 2000. % He also recommends making @example and @lisp be small. \def\afivepaper{{\globaldefs = 1 \parskip = 2pt plus 1pt minus 0.1pt \textleading = 12.5pt % \internalpagesizes{160mm}{120mm}% {\voffset}{\hoffset}% {\bindingoffset}{8pt}% {210mm}{148mm}% % \lispnarrowing = 0.2in \tolerance = 800 \hfuzz = 1.2pt \contentsrightmargin = 0pt \defbodyindent = 2mm \tableindent = 12mm }} % A specific text layout, 24x15cm overall, intended for A4 paper. \def\afourlatex{{\globaldefs = 1 \afourpaper \internalpagesizes{237mm}{150mm}% {\voffset}{4.6mm}% {\bindingoffset}{7mm}% {297mm}{210mm}% % % Must explicitly reset to 0 because we call \afourpaper. \globaldefs = 0 }} % Use @afourwide to print on A4 paper in landscape format. \def\afourwide{{\globaldefs = 1 \afourpaper \internalpagesizes{241mm}{165mm}% {\voffset}{-2.95mm}% {\bindingoffset}{7mm}% {297mm}{210mm}% \globaldefs = 0 }} % @pagesizes TEXTHEIGHT[,TEXTWIDTH] % Perhaps we should allow setting the margins, \topskip, \parskip, % and/or leading, also. Or perhaps we should compute them somehow. % \parseargdef\pagesizes{\pagesizesyyy #1,,\finish} \def\pagesizesyyy#1,#2,#3\finish{{% \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi \globaldefs = 1 % \parskip = 3pt plus 2pt minus 1pt \setleading{\textleading}% % \dimen0 = #1 \advance\dimen0 by \voffset % \dimen2 = \hsize \advance\dimen2 by \normaloffset % \internalpagesizes{#1}{\hsize}% {\voffset}{\normaloffset}% {\bindingoffset}{44pt}% {\dimen0}{\dimen2}% }} % Set default to letter. % \letterpaper \message{and turning on texinfo input format.} % Define macros to output various characters with catcode for normal text. \catcode`\"=\other \catcode`\~=\other \catcode`\^=\other \catcode`\_=\other \catcode`\|=\other \catcode`\<=\other \catcode`\>=\other \catcode`\+=\other \catcode`\$=\other \def\normaldoublequote{"} \def\normaltilde{~} \def\normalcaret{^} \def\normalunderscore{_} \def\normalverticalbar{|} \def\normalless{<} \def\normalgreater{>} \def\normalplus{+} \def\normaldollar{$}%$ font-lock fix % This macro is used to make a character print one way in \tt % (where it can probably be output as-is), and another way in other fonts, % where something hairier probably needs to be done. % % #1 is what to print if we are indeed using \tt; #2 is what to print % otherwise. Since all the Computer Modern typewriter fonts have zero % interword stretch (and shrink), and it is reasonable to expect all % typewriter fonts to have this, we can check that font parameter. % \def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} % Same as above, but check for italic font. Actually this also catches % non-italic slanted fonts since it is impossible to distinguish them from % italic fonts. But since this is only used by $ and it uses \sl anyway % this is not a problem. \def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} % Turn off all special characters except @ % (and those which the user can use as if they were ordinary). % Most of these we simply print from the \tt font, but for some, we can % use math or other variants that look better in normal text. \catcode`\"=\active \def\activedoublequote{{\tt\char34}} \let"=\activedoublequote \catcode`\~=\active \def~{{\tt\char126}} \chardef\hat=`\^ \catcode`\^=\active \def^{{\tt \hat}} \catcode`\_=\active \def_{\ifusingtt\normalunderscore\_} % Subroutine for the previous macro. \def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } \catcode`\|=\active \def|{{\tt\char124}} \chardef \less=`\< \catcode`\<=\active \def<{{\tt \less}} \chardef \gtr=`\> \catcode`\>=\active \def>{{\tt \gtr}} \catcode`\+=\active \def+{{\tt \char 43}} \catcode`\$=\active \def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix % If a .fmt file is being used, characters that might appear in a file % name cannot be active until we have parsed the command line. % So turn them off again, and have \everyjob (or @setfilename) turn them on. % \otherifyactive is called near the end of this file. \def\otherifyactive{\catcode`+=\other \catcode`\_=\other} \catcode`\@=0 % \backslashcurfont outputs one backslash character in current font, % as in \char`\\. \global\chardef\backslashcurfont=`\\ \global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work % \rawbackslash defines an active \ to do \backslashcurfont. % \otherbackslash defines an active \ to be a literal `\' character with % catcode other. {\catcode`\\=\active @gdef@rawbackslash{@let\=@backslashcurfont} @gdef@otherbackslash{@let\=@realbackslash} } % \realbackslash is an actual character `\' with catcode other. {\catcode`\\=\other @gdef@realbackslash{\}} % \normalbackslash outputs one backslash in fixed width font. \def\normalbackslash{{\tt\backslashcurfont}} \catcode`\\=\active % Used sometimes to turn off (effectively) the active characters % even after parsing them. @def@turnoffactive{% @let"=@normaldoublequote @let\=@realbackslash @let~=@normaltilde @let^=@normalcaret @let_=@normalunderscore @let|=@normalverticalbar @let<=@normalless @let>=@normalgreater @let+=@normalplus @let$=@normaldollar %$ font-lock fix @unsepspaces } % Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of % the literal character `\'. (Thus, \ is not expandable when this is in % effect.) % @def@normalturnoffactive{@turnoffactive @let\=@normalbackslash} % Make _ and + \other characters, temporarily. % This is canceled by @fixbackslash. @otherifyactive % If a .fmt file is being used, we don't want the `\input texinfo' to show up. % That is what \eatinput is for; after that, the `\' should revert to printing % a backslash. % @gdef@eatinput input texinfo{@fixbackslash} @global@let\ = @eatinput % On the other hand, perhaps the file did not have a `\input texinfo'. Then % the first `\{ in the file would cause an error. This macro tries to fix % that, assuming it is called before the first `\' could plausibly occur. % Also back turn on active characters that might appear in the input % file name, in case not using a pre-dumped format. % @gdef@fixbackslash{% @ifx\@eatinput @let\ = @normalbackslash @fi @catcode`+=@active @catcode`@_=@active } % Say @foo, not \foo, in error messages. @escapechar = `@@ % These look ok in all fonts, so just make them not special. @catcode`@& = @other @catcode`@# = @other @catcode`@% = @other @c Local variables: @c eval: (add-hook 'write-file-hooks 'time-stamp) @c page-delimiter: "^\\\\message" @c time-stamp-start: "def\\\\texinfoversion{" @c time-stamp-format: "%:y-%02m-%02d.%02H" @c time-stamp-end: "}" @c End: @c vim:sw=2: @ignore arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115 @end ignore kbuild-3686/src/oldsed/config/lcmessage.m40000664000175000017500000000271315053010105020420 0ustar locutuslocutus# lcmessage.m4 serial 2 (gettext-0.10.40) dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995. # Check whether LC_MESSAGES is available in . AC_DEFUN([AM_LC_MESSAGES], [if test $ac_cv_header_locale_h = yes; then AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, [AC_TRY_LINK([#include ], [return LC_MESSAGES], am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) if test $am_cv_val_LC_MESSAGES = yes; then AC_DEFINE(HAVE_LC_MESSAGES, 1, [Define if your file defines LC_MESSAGES.]) fi fi]) kbuild-3686/src/oldsed/config/stdbool.m40000664000175000017500000000403115053010105020116 0ustar locutuslocutus# Check for stdbool.h that conforms to C99. # Copyright (C) 2002-2003 Free Software Foundation, Inc. # 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, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # This macro is only needed in autoconf <= 2.54. Newer versions of autoconf # have this macro built-in. AC_DEFUN([AC_HEADER_STDBOOL], [AC_CACHE_CHECK([for stdbool.h that conforms to C99], [ac_cv_header_stdbool_h], [AC_TRY_COMPILE( [ #include #ifndef bool "error: bool is not defined" #endif #ifndef false "error: false is not defined" #endif #if false "error: false is not 0" #endif #ifndef true "error: false is not defined" #endif #if true != 1 "error: true is not 1" #endif #ifndef __bool_true_false_are_defined "error: __bool_true_false_are_defined is not defined" #endif struct s { _Bool s: 1; _Bool t; } s; char a[true == 1 ? 1 : -1]; char b[false == 0 ? 1 : -1]; char c[__bool_true_false_are_defined == 1 ? 1 : -1]; char d[(bool) -0.5 == true ? 1 : -1]; bool e = &s; char f[(_Bool) -0.0 == false ? 1 : -1]; char g[true]; char h[sizeof (_Bool)]; char i[sizeof s.t]; ], [ return !a + !b + !c + !d + !e + !f + !g + !h + !i; ], [ac_cv_header_stdbool_h=yes], [ac_cv_header_stdbool_h=no])]) AC_CHECK_TYPES([_Bool]) if test $ac_cv_header_stdbool_h = yes; then AC_DEFINE(HAVE_STDBOOL_H, 1, [Define to 1 if stdbool.h conforms to C99.]) fi]) kbuild-3686/src/oldsed/config/texi2dvi0000775000175000017500000005546315053010105017711 0ustar locutuslocutus#! /bin/sh # texi2dvi --- produce DVI (or PDF) files from Texinfo (or LaTeX) sources. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001, # 2002, 2003 Free Software Foundation, Inc. # # 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, 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, you can either send email to this # program's maintainer or write to: The Free Software Foundation, # Inc.; 51 Franklin Street, Fifth Floor; Boston, MA 02110-1301, USA. # # Original author: Noah Friedman . # # Please send bug reports, etc. to bug-texinfo@gnu.org. # If possible, please send a copy of the output of the script called with # the `--debug' option when making a bug report. program=`echo $0 | sed -e 's!.*/!!'` version="texi2dvi (GNU Texinfo 4.5) Copyright (C) 2003 Free Software Foundation, Inc. There is NO warranty. You may redistribute this software under the terms of the GNU General Public License. For more information about these matters, see the files named COPYING." usage="Usage: $program [OPTION]... FILE... Run each Texinfo or LaTeX FILE through TeX in turn until all cross-references are resolved, building all indices. The directory containing each FILE is searched for included files. The suffix of FILE is used to determine its language (LaTeX or Texinfo). Makeinfo is used to perform Texinfo macro expansion before running TeX when needed. Operation modes: -b, --batch no interaction -c, --clean remove all auxiliary files -D, --debug turn on shell debugging (set -x) -h, --help display this help and exit successfully -o, --output=OFILE leave output in OFILE (implies --clean); Only one input FILE may be specified in this case -q, --quiet no output unless errors (implies --batch) -s, --silent same as --quiet -v, --version display version information and exit successfully -V, --verbose report on what is done TeX tuning: -@ use @input instead of \input; for preloaded Texinfo -e, -E, --expand force macro expansion using makeinfo -I DIR search DIR for Texinfo files -l, --language=LANG specify the LANG of FILE (LaTeX or Texinfo) -p, --pdf use pdftex or pdflatex for processing -t, --texinfo=CMD insert CMD after @setfilename in copy of input file multiple values accumulate The values of the BIBTEX, LATEX (or PDFLATEX), MAKEINDEX, MAKEINFO, TEX (or PDFTEX), and TEXINDEX environment variables are used to run those commands, if they are set. Email bug reports to , general questions and discussion to . Texinfo home page: http://www.gnu.org/software/texinfo/" # Initialize variables for option overriding and otherwise. # Don't use `unset' since old bourne shells don't have this command. # Instead, assign them an empty value. batch=false # eval for batch mode clean= debug= escape='\' expand= # t for expansion via makeinfo miincludes= # makeinfo include path oformat=dvi oname= # --output quiet= # by default let the tools' message be displayed set_language= textra= tmpdir=${TMPDIR:-/tmp}/t2d$$ # avoid collisions on 8.3 filesystems. txincludes= # TEXINPUTS extensions, with trailing colon txiprereq=19990129 # minimum texinfo.tex version to have macro expansion verbose=false # echo for verbose mode orig_pwd=`pwd` # Systems which define $COMSPEC or $ComSpec use semicolons to separate # directories in TEXINPUTS. if test -n "$COMSPEC$ComSpec"; then path_sep=";" else path_sep=":" fi # Pacify verbose cds. CDPATH=${ZSH_VERSION+.}$path_sep # In case someone crazy insists on using grep -E. : ${EGREP=egrep} # Save this so we can construct a new TEXINPUTS path for each file. TEXINPUTS_orig="$TEXINPUTS" # Unfortunately makeindex does not read TEXINPUTS. INDEXSTYLE_orig="$INDEXSTYLE" export TEXINPUTS INDEXSTYLE # Push a token among the arguments that will be used to notice when we # ended options/arguments parsing. # Use "set dummy ...; shift" rather than 'set - ..." because on # Solaris set - turns off set -x (but keeps set -e). # Use ${1+"$@"} rather than "$@" because Digital Unix and Ultrix 4.3 # still expand "$@" to a single argument (the empty string) rather # than nothing at all. arg_sep="$$--$$" set dummy ${1+"$@"} "$arg_sep"; shift # # Parse command line arguments. while test x"$1" != x"$arg_sep"; do # Handle --option=value by splitting apart and putting back on argv. case "$1" in --*=*) opt=`echo "$1" | sed -e 's/=.*//'` val=`echo "$1" | sed -e 's/[^=]*=//'` shift set dummy "$opt" "$val" ${1+"$@"}; shift ;; esac # This recognizes --quark as --quiet. So what. case "$1" in -@ ) escape=@;; # Silently and without documentation accept -b and --b[atch] as synonyms. -b | --b*) batch=eval;; -q | -s | --q* | --s*) quiet=t; batch=eval;; -c | --c*) clean=t;; -D | --d*) debug=t;; -e | -E | --e*) expand=t;; -h | --h*) echo "$usage"; exit 0;; -I | --I*) shift miincludes="$miincludes -I $1" txincludes="$txincludes$1$path_sep" ;; -l | --l*) shift; set_language=$1;; -o | --o*) shift clean=t case "$1" in /* | ?:/*) oname=$1;; *) oname="$orig_pwd/$1";; esac;; -p | --p*) oformat=pdf;; -t | --t*) shift; textra="$textra\\ $1";; -v | --vers*) echo "$version"; exit 0;; -V | --verb*) verbose=echo;; --) # What remains are not options. shift while test x"$1" != x"$arg_sep"; do set dummy ${1+"$@"} "$1"; shift shift done break;; -*) echo "$0: Unknown or ambiguous option \`$1'." >&2 echo "$0: Try \`--help' for more information." >&2 exit 1;; *) set dummy ${1+"$@"} "$1"; shift;; esac shift done # Pop the token shift # Interpret remaining command line args as filenames. case $# in 0) echo "$0: Missing file arguments." >&2 echo "$0: Try \`--help' for more information." >&2 exit 2 ;; 1) ;; *) if test -n "$oname"; then echo "$0: Can't use option \`--output' with more than one argument." >&2 exit 2 fi ;; esac # Prepare the temporary directory. Remove it at exit, unless debugging. if test -z "$debug"; then trap "cd / && rm -rf $tmpdir" 0 1 2 15 fi # Create the temporary directory with strict rights (umask 077 && mkdir $tmpdir) || exit 1 # Prepare the tools we might need. This may be extra work in some # cases, but improves the readibility of the script. utildir=$tmpdir/utils mkdir $utildir || exit 1 # A sed script that preprocesses Texinfo sources in order to keep the # iftex sections only. We want to remove non TeX sections, and # comment (with `@c texi2dvi') TeX sections so that makeinfo does not # try to parse them. Nevertheless, while commenting TeX sections, # don't comment @macro/@end macro so that makeinfo does propagate # them. Unfortunately makeinfo --iftex --no-ifhtml --no-ifinfo # doesn't work well enough (yet) to use that, so work around with sed. comment_iftex_sed=$utildir/comment.sed cat <$comment_iftex_sed /^@tex/,/^@end tex/{ s/^/@c texi2dvi/ } /^@iftex/,/^@end iftex/{ s/^/@c texi2dvi/ /^@c texi2dvi@macro/,/^@c texi2dvi@end macro/{ s/^@c texi2dvi// } } /^@html/,/^@end html/{ s/^/@c (texi2dvi)/ } /^@ifhtml/,/^@end ifhtml/{ s/^/@c (texi2dvi)/ } /^@ifnottex/,/^@end ifnottex/{ s/^/@c (texi2dvi)/ } /^@ifinfo/,/^@end ifinfo/{ /^@node/p /^@menu/,/^@end menu/p t s/^/@c (texi2dvi)/ } s/^@ifnotinfo/@c texi2dvi@ifnotinfo/ s/^@end ifnotinfo/@c texi2dvi@end ifnotinfo/ EOF # Uncommenting is simple: Remove any leading `@c texi2dvi'. uncomment_iftex_sed=$utildir/uncomment.sed cat <$uncomment_iftex_sed s/^@c texi2dvi// EOF # A shell script that computes the list of xref files. # Takes the filename (without extension) of which we look for xref # files as argument. The index files must be reported last. get_xref_files=$utildir/get_xref.sh cat <<\EOF >$get_xref_files #! /bin/sh # Get list of xref files (indexes, tables and lists). # Find all files having root filename with a two-letter extension, # saves the ones that are really Texinfo-related files. .?o? catches # many files: .toc, .log, LaTeX tables and lists, FiXme's .lox, maybe more. for this_file in "$1".?o? "$1".aux "$1".?? "$1".idx; do # If file is empty, skip it. test -s "$this_file" || continue # If the file is not suitable to be an index or xref file, don't # process it. The file can't be if its first character is not a # backslash or single quote. first_character=`sed -n '1s/^\(.\).*$/\1/p;q' $this_file` if test "x$first_character" = "x\\" \ || test "x$first_character" = "x'"; then xref_files="$xref_files ./$this_file" fi done echo "$xref_files" EOF chmod 500 $get_xref_files # File descriptor usage: # 0 standard input # 1 standard output (--verbose messages) # 2 standard error # 3 some systems may open it to /dev/tty # 4 used on the Kubota Titan # 5 tools output (turned off by --quiet) # Tools' output. If quiet, discard, else redirect to the message flow. if test "$quiet" = t; then exec 5>/dev/null else exec 5>&1 fi # Enable tracing test "$debug" = t && set -x # # TeXify files. for command_line_filename in ${1+"$@"}; do $verbose "Processing $command_line_filename ..." # If the COMMAND_LINE_FILENAME is not absolute (e.g., --debug.tex), # prepend `./' in order to avoid that the tools take it as an option. echo "$command_line_filename" | $EGREP '^(/|[A-z]:/)' >/dev/null \ || command_line_filename="./$command_line_filename" # See if the file exists. If it doesn't we're in trouble since, even # though the user may be able to reenter a valid filename at the tex # prompt (assuming they're attending the terminal), this script won't # be able to find the right xref files and so forth. if test ! -r "$command_line_filename"; then echo "$0: Could not read $command_line_filename, skipping." >&2 continue fi # Get the name of the current directory. We want the full path # because in clean mode we are in tmp, in which case a relative # path has no meaning. filename_dir=`echo $command_line_filename | sed 's!/[^/]*$!!;s!^$!.!'` filename_dir=`cd "$filename_dir" >/dev/null && pwd` # Strip directory part but leave extension. filename_ext=`basename "$command_line_filename"` # Strip extension. filename_noext=`echo "$filename_ext" | sed 's/\.[^.]*$//'` ext=`echo "$filename_ext" | sed 's/^.*\.//'` # _src. Use same basename since we want to generate aux files with # the same basename as the manual. If --expand, then output the # macro-expanded file to here, else copy the original file. tmpdir_src=$tmpdir/src filename_src=$tmpdir_src/$filename_noext.$ext # _xtr. The file with the user's extra commands. tmpdir_xtr=$tmpdir/xtr filename_xtr=$tmpdir_xtr/$filename_noext.$ext # _bak. Copies of the previous xref files (another round is run if # they differ from the new one). tmpdir_bak=$tmpdir/bak # Make all those directories and give up if we can't succeed. mkdir $tmpdir_src $tmpdir_xtr $tmpdir_bak || exit 1 # Source file might include additional sources. # We want `.:$orig_pwd' before anything else. (We'll add `.:' later # after all other directories have been turned into absolute paths.) # `.' goes first to ensure that any old .aux, .cps, # etc. files in ${directory} don't get used in preference to fresher # files in `.'. Include orig_pwd in case we are in clean mode, where # we've cd'd to a temp directory. common="$orig_pwd$path_sep$filename_dir$path_sep$txincludes" TEXINPUTS="$common$TEXINPUTS_orig" INDEXSTYLE="$common$INDEXSTYLE_orig" # Convert relative paths to absolute paths, so we can run in another # directory (e.g., in --clean mode, or during the macro-support # detection.) # # Empty path components are meaningful to tex. We rewrite them # as `EMPTY' so they don't get lost when we split on $path_sep. TEXINPUTS=`echo $TEXINPUTS |sed 's/^:/EMPTY:/;s/:$/:EMPTY/;s/::/:EMPTY:/g'` INDEXSTYLE=`echo $INDEXSTYLE |sed 's/^:/EMPTY:/;s/:$/:EMPTY/;s/::/:EMPTY:/g'` save_IFS=$IFS IFS=$path_sep set x $TEXINPUTS; shift TEXINPUTS=. for dir do case $dir in EMPTY) TEXINPUTS=$TEXINPUTS$path_sep ;; [\\/]* | ?:[\\/]*) # Absolute paths don't need to be expansed. TEXINPUTS=$TEXINPUTS$path_sep$dir ;; *) abs=`cd "$dir" && pwd` && TEXINPUTS=$TEXINPUTS$path_sep$abs ;; esac done set x $INDEXSTYLE; shift INDEXSTYLE=. for dir do case $dir in EMPTY) INDEXSTYLE=$INDEXSTYLE$path_sep ;; [\\/]* | ?:[\\/]*) # Absolute paths don't need to be expansed. INDEXSTYLE=$INDEXSTYLE$path_sep$dir ;; *) abs=`cd "$dir" && pwd` && INDEXSTYLE=$INDEXSTYLE$path_sep$abs ;; esac done IFS=$save_IFS # If the user explicitly specified the language, use that. # Otherwise, if the first line is \input texinfo, assume it's texinfo. # Otherwise, guess from the file extension. if test -n "$set_language"; then language=$set_language elif sed 1q "$command_line_filename" | grep 'input texinfo' >/dev/null; then language=texinfo else language= fi # Get the type of the file (latex or texinfo) from the given language # we just guessed, or from the file extension if not set yet. case ${language:-$filename_ext} in [lL]a[tT]e[xX] | *.ltx | *.tex) # Assume a LaTeX file. LaTeX needs bibtex and uses latex for # compilation. No makeinfo. bibtex=${BIBTEX:-bibtex} makeinfo= # no point in running makeinfo on latex source. texindex=${MAKEINDEX:-makeindex} if test $oformat = dvi; then tex=${LATEX:-latex} else tex=${PDFLATEX:-pdflatex} fi ;; *) # Assume a Texinfo file. Texinfo files need makeinfo, texindex and tex. bibtex= texindex=${TEXINDEX:-texindex} if test $oformat = dvi; then tex=${TEX:-tex} else tex=${PDFTEX:-pdftex} fi # Unless required by the user, makeinfo expansion is wanted only # if texinfo.tex is too old. if test "$expand" = t; then makeinfo=${MAKEINFO:-makeinfo} else # Check if texinfo.tex performs macro expansion by looking for # its version. The version is a date of the form YEAR-MO-DA. # We don't need to use [0-9] to match the digits since anyway # the comparison with $txiprereq, a number, will fail with non # digits. txiversion_tex=txiversion.tex echo '\input texinfo.tex @bye' >$tmpdir/$txiversion_tex # Run in the tmpdir to avoid leaving files. eval `cd $tmpdir >/dev/null && $tex $txiversion_tex 2>/dev/null | sed -n 's/^.*\[\(.*\)version \(....\)-\(..\)-\(..\).*$/txiformat=\1 txiversion="\2\3\4"/p'` $verbose "texinfo.tex preloaded as \`$txiformat', version is \`$txiversion' ..." if test "$txiprereq" -le "$txiversion" >/dev/null 2>&1; then makeinfo= else makeinfo=${MAKEINFO:-makeinfo} fi # As long as we had to run TeX, offer the user this convenience if test "$txiformat" = Texinfo; then escape=@ fi fi ;; esac # Expand macro commands in the original source file using Makeinfo. # Always use `end' footnote style, since the `separate' style # generates different output (arguably this is a bug in -E). # Discard main info output, the user asked to run TeX, not makeinfo. if test -n "$makeinfo"; then $verbose "Macro-expanding $command_line_filename to $filename_src ..." sed -f $comment_iftex_sed "$command_line_filename" \ | $makeinfo --footnote-style=end -I "$filename_dir" $miincludes \ -o /dev/null --macro-expand=- \ | sed -f $uncomment_iftex_sed >"$filename_src" filename_input=$filename_src fi # If makeinfo failed (or was not even run), use the original file as input. if test $? -ne 0 \ || test ! -r "$filename_src"; then $verbose "Reverting to $command_line_filename ..." filename_input=$filename_dir/$filename_ext fi # Used most commonly for @finalout, @smallbook, etc. if test -n "$textra"; then $verbose "Inserting extra commands: $textra" sed '/^@setfilename/a\ '"$textra" "$filename_input" >$filename_xtr filename_input=$filename_xtr fi # If clean mode was specified, then move to the temporary directory. if test "$clean" = t; then $verbose "cd $tmpdir_src" cd "$tmpdir_src" || exit 1 fi while :; do # will break out of loop below orig_xref_files=`$get_xref_files "$filename_noext"` # Save copies of originals for later comparison. if test -n "$orig_xref_files"; then $verbose "Backing up xref files: `echo $orig_xref_files | sed 's|\./||g'`" cp $orig_xref_files $tmpdir_bak fi # Run bibtex on current file. # - If its input (AUX) exists. # - If AUX contains both `\bibdata' and `\bibstyle'. # - If some citations are missing (LOG contains `Citation'). # or the LOG complains of a missing .bbl # # We run bibtex first, because I can see reasons for the indexes # to change after bibtex is run, but I see no reason for the # converse. # # Don't try to be too smart. Running bibtex only if the bbl file # exists and is older than the LaTeX file is wrong, since the # document might include files that have changed. Because there # can be several AUX (if there are \include's), but a single LOG, # looking for missing citations in LOG is easier, though we take # the risk to match false messages. if test -n "$bibtex" \ && test -r "$filename_noext.aux" \ && test -r "$filename_noext.log" \ && (grep '^\\bibdata[{]' "$filename_noext.aux" \ && grep '^\\bibstyle[{]' "$filename_noext.aux" \ && (grep 'Warning:.*Citation.*undefined' "$filename_noext.log" \ || grep 'No file .*\.bbl\.' "$filename_noext.log")) \ >/dev/null 2>&1; \ then $verbose "Running $bibtex $filename_noext ..." if $bibtex "$filename_noext" >&5; then :; else echo "$0: $bibtex exited with bad status, quitting." >&2 exit 1 fi fi # What we'll run texindex on -- exclude non-index files. # Since we know index files are last, it is correct to remove everything # before .aux and .?o?. But don't really do o # -- don't match whitespace as . # Otherwise, if orig_xref_files contains something like # foo.xo foo.whatever # the space after the o will get matched. index_files=`echo "$orig_xref_files" \ | sed "s!.*\.aux!!g; s!./$filename_noext\.[^ ]o[^ ]!!g; s/^[ ]*//;s/[ ]*$//"` # Run texindex (or makeindex) on current index files. If they # already exist, and after running TeX a first time the index # files don't change, then there's no reason to run TeX again. # But we won't know that if the index files are out of date or # nonexistent. if test -n "$texindex" && test -n "$index_files"; then $verbose "Running $texindex $index_files ..." if $texindex $index_files 2>&5 1>&2; then :; else echo "$0: $texindex exited with bad status, quitting." >&2 exit 1 fi fi # Finally, run TeX. # Prevent $ESCAPE from being interpreted by the shell if it happens # to be `/'. $batch tex_args="\\${escape}nonstopmode\ \\${escape}input" cmd="$tex $tex_args $filename_input" $verbose "Running $cmd ..." if $cmd >&5; then :; else echo "$0: $tex exited with bad status, quitting." >&2 echo "$0: see $filename_noext.log for errors." >&2 test "$clean" = t \ && cp "$filename_noext.log" "$orig_pwd" exit 1 fi # Decide if looping again is needed. finished=t # LaTeX (and the package changebar) report in the LOG file if it # should be rerun. This is needed for files included from # subdirs, since texi2dvi does not try to compare xref files in # subdirs. Performing xref files test is still good since LaTeX # does not report changes in xref files. if grep "Rerun to get" "$filename_noext.log" >/dev/null 2>&1; then finished= fi # Check if xref files changed. new_xref_files=`$get_xref_files "$filename_noext"` $verbose "Original xref files = `echo $orig_xref_files | sed 's|\./||g'`" $verbose "New xref files = `echo $new_xref_files | sed 's|\./||g'`" # If old and new lists don't at least have the same file list, # then one file or another has definitely changed. test "x$orig_xref_files" != "x$new_xref_files" && finished= # File list is the same. We must compare each file until we find # a difference. if test -n "$finished"; then for this_file in $new_xref_files; do $verbose "Comparing xref file `echo $this_file | sed 's|\./||g'` ..." # cmp -s returns nonzero exit status if files differ. if cmp -s "$this_file" "$tmpdir_bak/$this_file"; then :; else # We only need to keep comparing until we find one that # differs, because we'll have to run texindex & tex again no # matter how many more there might be. finished= $verbose "xref file `echo $this_file | sed 's|\./||g'` differed ..." test "$debug" = t && diff -c "$tmpdir_bak/$this_file" "$this_file" break fi done fi # If finished, exit the loop, else rerun the loop. test -n "$finished" && break done # If we were in clean mode, compilation was in a tmp directory. # Copy the DVI (or PDF) file into the directory where the compilation # has been done. (The temp dir is about to get removed anyway.) # We also return to the original directory so that # - the next file is processed in correct conditions # - the temporary file can be removed if test -n "$clean"; then if test -n "$oname"; then dest=$oname else dest=$orig_pwd fi $verbose "Copying $oformat file from `pwd` to $dest" cp -p "./$filename_noext.$oformat" "$dest" cd / # in case $orig_pwd is on a different drive (for DOS) cd $orig_pwd || exit 1 fi # Remove temporary files. if test "x$debug" = "x"; then $verbose "Removing $tmpdir_src $tmpdir_xtr $tmpdir_bak ..." cd / rm -rf $tmpdir_src $tmpdir_xtr $tmpdir_bak fi done $verbose "$0 done." exit 0 # exit successfully, not however we ended the loop. kbuild-3686/src/oldsed/config/config.rpath0000775000175000017500000003236715053010105020533 0ustar locutuslocutus#! /bin/sh # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # # Copyright 1996-2002 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld # should be set by the caller. # # The set of defined variables is at the end of this script. # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). libext=a shlibext= host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix3* | aix4* | aix5*) if test "$host_cpu" = ia64; then wl='-Wl,' fi ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6*) wl='-Wl,' ;; linux*) echo '__INTEL_COMPILER' > conftest.$ac_ext if $CC -E conftest.$ac_ext >/dev/null | grep __INTEL_COMPILER >/dev/null then : else # Intel icc wl='-Qoption,ld,' fi ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; solaris*) wl='-Wl,' ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) if test "x$host_vendor" = xsni; then wl='-LD' else wl='-Wl,' fi ;; esac fi hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no 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 case "$host_os" in aix3* | aix4* | aix5*) # On AIX, the GNU linker is very broken ld_shlibs=no ;; amigaos*) 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 : 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' ;; solaris* | sysv5*) if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' fi else case "$host_os" in aix3*) # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) 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 hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi else 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 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 fi if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib' else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib' fi fi ;; amigaos*) 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=' ' libext=lib ;; darwin* | rhapsody*) hardcode_direct=yes ;; freebsd1*) ld_shlibs=no ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; freebsd2*) hardcode_direct=yes hardcode_minus_L=yes ;; freebsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; hpux9* | hpux10* | hpux11*) 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. ;; irix5* | irix6*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; newsos6) hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; openbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; osf3*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) if test "$GCC" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else # Both cc and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; sco3.2v5*) ;; solaris*) hardcode_libdir_flag_spec='-R$libdir' ;; sunos4*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes ;; sysv4) if test "x$host_vendor" = xsno; then hardcode_direct=yes # is this really true??? else hardcode_direct=no # Motorola manual says yes, but my tests say they lie fi ;; sysv4.3*) ;; sysv5*) hardcode_libdir_flag_spec= ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4.2uw2*) hardcode_direct=yes hardcode_minus_L=no ;; sysv5uw7* | unixware7*) ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics libname_spec='lib$name' sys_lib_dlsearch_path_spec="/lib /usr/lib" sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" case "$host_os" in aix3*) shlibext=so ;; aix4* | aix5*) shlibext=so ;; amigaos*) shlibext=ixlibrary ;; beos*) shlibext=so ;; bsdi4*) shlibext=so 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" ;; cygwin* | mingw* | pw32*) case $GCC,$host_os in yes,cygwin*) shlibext=dll.a ;; yes,mingw*) shlibext=dll sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"` ;; yes,pw32*) shlibext=dll ;; *) shlibext=dll ;; esac ;; darwin* | rhapsody*) shlibext=dylib ;; freebsd1*) ;; freebsd*) shlibext=so ;; gnu*) shlibext=so ;; hpux9* | hpux10* | hpux11*) shlibext=sl ;; irix5* | irix6*) shlibext=so case "$host_os" in irix5*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 ") libsuff= shlibsuff= ;; *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" ;; linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) ;; linux-gnu*) shlibext=so ;; netbsd*) shlibext=so ;; newsos6) shlibext=so ;; openbsd*) shlibext=so ;; os2*) libname_spec='$name' shlibext=dll ;; osf3* | osf4* | osf5*) shlibext=so 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*) shlibext=so ;; solaris*) shlibext=so ;; sunos4*) shlibext=so ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) shlibext=so case "$host_vendor" in motorola) sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; uts4*) shlibext=so ;; dgux*) shlibext=so ;; sysv4*MP*) if test -d /usr/nec; then shlibext=so fi ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_sys_lib_search_path_spec=`echo "X$sys_lib_search_path_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_sys_lib_dlsearch_path_spec=`echo "X$sys_lib_dlsearch_path_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi for src do # Protect names starting with `-'. case $src in -*) src=./$src ;; esac if test -n "$dir_arg"; then dst=$src src= if test -d "$dst"; then mkdircmd=: chmodcmd= else mkdircmd=$mkdirprog fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dstarg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dstarg # Protect names starting with `-'. case $dst in -*) dst=./$dst ;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dstarg: Is a directory" >&2 exit 1 fi dst=$dst/`basename "$src"` fi fi # This sed command emulates the dirname command. dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # Skip lots of stat calls in the usual case. if test ! -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 test $# -ne 0 ; do pathcomp=$pathcomp$1 shift if test ! -d "$pathcomp"; then $mkdirprog "$pathcomp" # mkdir can fail with a `File exist' error in case several # install-sh are creating the directory concurrently. This # is OK. test -d "$pathcomp" || exit fi pathcomp=$pathcomp/ done fi if test -n "$dir_arg"; then $doit $mkdircmd "$dst" \ && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } else dstfile=`basename "$dst"` # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 trap '(exit $?); exit' 1 2 13 15 # Copy the file name to the temp name. $doit $cpprog "$src" "$dsttmp" && # 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 $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && # Now rename the file to the real destination. { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ || { # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { if test -f "$dstdir/$dstfile"; then $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ || { echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 (exit 1); exit } else : fi } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" } } fi || { (exit 1); exit; } done # The final little trick to "correctly" pass the exit status to the exit trap. { (exit 0); exit } # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: kbuild-3686/src/oldsed/config/codeset.m40000664000175000017500000000157615053010105020111 0ustar locutuslocutus# codeset.m4 serial AM1 (gettext-0.10.40) dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. dnl From Bruno Haible. AC_DEFUN([AM_LANGINFO_CODESET], [ AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset, [AC_TRY_LINK([#include ], [char* cs = nl_langinfo(CODESET);], am_cv_langinfo_codeset=yes, am_cv_langinfo_codeset=no) ]) if test $am_cv_langinfo_codeset = yes; then AC_DEFINE(HAVE_LANGINFO_CODESET, 1, [Define if you have and nl_langinfo(CODESET).]) fi ]) kbuild-3686/src/oldsed/config/mdate-sh0000775000175000017500000001150115053010105017636 0ustar locutuslocutus#!/bin/sh # Get modification time of a file or directory and pretty-print it. scriptversion=2003-11-09.00 # Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc. # written by Ulrich Drepper , June 1995 # # 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, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . case $1 in '') echo "$0: No file. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: mdate-sh [--help] [--version] FILE Pretty-print the modification time of FILE. Report bugs to . EOF exit 0 ;; -v | --v*) echo "mdate-sh $scriptversion" exit 0 ;; esac # Prevent date giving response in another language. LANG=C export LANG LC_ALL=C export LC_ALL LC_TIME=C export LC_TIME save_arg1="$1" # Find out how to get the extended ls output of a file or directory. if ls -L /dev/null 1>/dev/null 2>&1; then ls_command='ls -L -l -d' else ls_command='ls -l -d' fi # A `ls -l' line looks as follows on OS/2. # drwxrwx--- 0 Aug 11 2001 foo # This differs from Unix, which adds ownership information. # drwxrwx--- 2 root root 4096 Aug 11 2001 foo # # To find the date, we split the line on spaces and iterate on words # until we find a month. This cannot work with files whose owner is a # user named `Jan', or `Feb', etc. However, it's unlikely that `/' # will be owned by a user whose name is a month. So we first look at # the extended ls output of the root directory to decide how many # words should be skipped to get the date. # On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below. set - x`$ls_command /` # Find which argument is the month. month= command= until test $month do shift # Add another shift to the command. command="$command shift;" case $1 in Jan) month=January; nummonth=1;; Feb) month=February; nummonth=2;; Mar) month=March; nummonth=3;; Apr) month=April; nummonth=4;; May) month=May; nummonth=5;; Jun) month=June; nummonth=6;; Jul) month=July; nummonth=7;; Aug) month=August; nummonth=8;; Sep) month=September; nummonth=9;; Oct) month=October; nummonth=10;; Nov) month=November; nummonth=11;; Dec) month=December; nummonth=12;; esac done # Get the extended ls output of the file or directory. set - x`eval "$ls_command \"\$save_arg1\""` # Remove all preceding arguments eval $command # Get the month. Next argument is day, followed by the year or time. case $1 in Jan) month=January; nummonth=1;; Feb) month=February; nummonth=2;; Mar) month=March; nummonth=3;; Apr) month=April; nummonth=4;; May) month=May; nummonth=5;; Jun) month=June; nummonth=6;; Jul) month=July; nummonth=7;; Aug) month=August; nummonth=8;; Sep) month=September; nummonth=9;; Oct) month=October; nummonth=10;; Nov) month=November; nummonth=11;; Dec) month=December; nummonth=12;; esac day=$2 # Here we have to deal with the problem that the ls output gives either # the time of day or the year. case $3 in *:*) set `date`; eval year=\$$# case $2 in Jan) nummonthtod=1;; Feb) nummonthtod=2;; Mar) nummonthtod=3;; Apr) nummonthtod=4;; May) nummonthtod=5;; Jun) nummonthtod=6;; Jul) nummonthtod=7;; Aug) nummonthtod=8;; Sep) nummonthtod=9;; Oct) nummonthtod=10;; Nov) nummonthtod=11;; Dec) nummonthtod=12;; esac # For the first six month of the year the time notation can also # be used for files modified in the last year. if (expr $nummonth \> $nummonthtod) > /dev/null; then year=`expr $year - 1` fi;; *) year=$3;; esac # The result. echo $day $month $year # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: kbuild-3686/src/oldsed/config/config.sub0000775000175000017500000007501415053010105020202 0ustar locutuslocutus#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. timestamp='2004-06-24' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted 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, 2002, 2003, 2004 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* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ kfreebsd*-gnu* | knetbsd*-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 | -knuth | -cray) 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] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | m32r | m32rle | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | msp430 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic4x | 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-* | c55x-* | c6x-* \ | clipper-* | craynv-* | 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-* | iq2000-* \ | m32r-* | m32rle-* \ | 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-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | msp430-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | 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 ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; 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 ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16c) basic_machine=cr16c-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; 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 ;; 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 ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; 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 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; 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 ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-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 ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; 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 ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv8 | 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* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*) # 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-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -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 ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; 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 ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 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: kbuild-3686/src/oldsed/config/glibc21.m40000664000175000017500000000172715053010105017704 0ustar locutuslocutus# glibc21.m4 serial 2 (fileutils-4.1.3, gettext-0.10.40) dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. # Test for the GNU C Library, version 2.1 or newer. # From Bruno Haible. AC_DEFUN([jm_GLIBC21], [ AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer, ac_cv_gnu_library_2_1, [AC_EGREP_CPP([Lucky GNU user], [ #include #ifdef __GNU_LIBRARY__ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) Lucky GNU user #endif #endif ], ac_cv_gnu_library_2_1=yes, ac_cv_gnu_library_2_1=no) ] ) AC_SUBST(GLIBC21) GLIBC21="$ac_cv_gnu_library_2_1" ] ) kbuild-3686/src/oldsed/config/depcomp0000775000175000017500000003555115053010105017576 0ustar locutuslocutus#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2004-05-31.23 # Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. # 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, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit 0 ;; -v | --v*) echo "depcomp $scriptversion" exit 0 ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi stat=$? if test -f "$tmpdepfile"; then : else stripped=`echo "$stripped" | sed 's,^.*/,,'` tmpdepfile="$stripped.u" fi if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi if test -f "$tmpdepfile"; then outname="$stripped.o" # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # Dependencies are output in .lo.d with libtool 1.4. # With libtool 1.5 they are output both in $dir.libs/$base.o.d # and in $dir.libs/$base.o.d and $dir$base.o.d. We process the # latter, because the former will be cleaned when $dir.libs is # erased. tmpdepfile1="$dir.libs/$base.lo.d" tmpdepfile2="$dir$base.o.d" tmpdepfile3="$dir.libs/$base.d" "$@" -Wc,-MD else tmpdepfile1="$dir$base.o.d" tmpdepfile2="$dir$base.d" tmpdepfile3="$dir$base.d" "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi if test -f "$tmpdepfile1"; then tmpdepfile="$tmpdepfile1" elif test -f "$tmpdepfile2"; then tmpdepfile="$tmpdepfile2" else tmpdepfile="$tmpdepfile3" fi if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # X makedepend shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes ;; esac case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix="`echo $object | sed 's/^.*\././'`" touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. "$@" || exit $? IFS=" " for arg do case "$arg" in "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: kbuild-3686/src/oldsed/config/missing0000775000175000017500000002467215053010105017622 0ustar locutuslocutus#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2003-09-02.23 # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 # Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 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, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case "$1" in -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] Send bug reports to ." ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; aclocal*) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` fi if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then # We have makeinfo, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` fi touch $file ;; tar) shift if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 fi # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: kbuild-3686/src/oldsed/config/lib-prefix.m40000664000175000017500000001175515053010105020524 0ustar locutuslocutus# lib-prefix.m4 serial 1 (gettext-0.11) dnl Copyright (C) 2001-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. dnl From Bruno Haible. dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed dnl to access previously installed libraries. The basic assumption is that dnl a user will want packages to use other packages he previously installed dnl with the same --prefix option. dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate dnl libraries, but is otherwise very convenient. AC_DEFUN([AC_LIB_PREFIX], [ AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_ARG_WITH([lib-prefix], [ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib --without-lib-prefix don't search for libraries in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/lib" fi fi ]) if test $use_additional = yes; then dnl Potentially add $additional_includedir to $CPPFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's already present in $CPPFLAGS, dnl 3. if it's /usr/local/include and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= for x in $CPPFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $CPPFLAGS. CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" fi fi fi fi dnl Potentially add $additional_libdir to $LDFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's already present in $LDFLAGS, dnl 3. if it's /usr/local/lib and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/lib"; then haveit= for x in $LDFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_libdir" = "X/usr/local/lib"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LDFLAGS. LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" fi fi fi fi fi ]) dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, dnl acl_final_exec_prefix, containing the values to which $prefix and dnl $exec_prefix will expand at the end of the configure script. AC_DEFUN([AC_LIB_PREPARE_PREFIX], [ dnl Unfortunately, prefix and exec_prefix get only finally determined dnl at the end of configure. if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" ]) dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the dnl variables prefix and exec_prefix bound to the values they will have dnl at the end of the configure script. AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], [ acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" $1 exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" ]) kbuild-3686/src/oldsed/config/lib-ld.m40000664000175000017500000000626015053010105017621 0ustar locutuslocutus# lib-ld.m4 serial 1 (gettext-0.11) dnl Copyright (C) 1996-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. dnl Subroutines of libtool.m4, dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision dnl with libtool.m4. dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. AC_DEFUN([AC_LIB_PROG_LD_GNU], [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, [# I'd rather use --version here, but apparently some GNU ld's only accept -v. if $LD -v 2>&1 &5; then acl_cv_prog_gnu_ld=yes else acl_cv_prog_gnu_ld=no fi]) with_gnu_ld=$acl_cv_prog_gnu_ld ]) dnl From libtool-1.4. Sets the variable LD. AC_DEFUN([AC_LIB_PROG_LD], [AC_ARG_WITH(gnu-ld, [ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by GCC]) 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 AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(acl_cv_path_LD, [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 acl_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 "$acl_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 acl_cv_path_LD="$LD" # Let the user override the test with a path. fi]) LD="$acl_cv_path_LD" if test -n "$LD"; then AC_MSG_RESULT($LD) else AC_MSG_RESULT(no) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) AC_LIB_PROG_LD_GNU ]) kbuild-3686/src/oldsed/config/strverscmp.m40000664000175000017500000000133515053010105020664 0ustar locutuslocutus# strverscmp.m4 serial 1 dnl Copyright (C) 2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. AC_DEFUN([gl_FUNC_STRVERSCMP], [ dnl Persuade glibc to declare strverscmp(). AC_REQUIRE([AC_GNU_SOURCE]) AC_REPLACE_FUNCS(strverscmp) if test $ac_cv_func_strverscmp = no; then gl_PREREQ_STRVERSCMP fi ]) # Prerequisites of lib/strverscmp.c. AC_DEFUN([gl_PREREQ_STRVERSCMP], [ : ]) kbuild-3686/src/oldsed/config/config.guess0000775000175000017500000012466615053010105020547 0ustar locutuslocutus#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. timestamp='2004-08-11' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches 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, 2002, 2003, 2004 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. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ;' # 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 ;; amd64:OpenBSD:*:*) echo x86_64-unknown-openbsd${UNAME_RELEASE} exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; cats:OpenBSD:*:*) echo arm-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; luna88k:OpenBSD:*:*) echo m88k-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 ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit 0 ;; macppc:MirBSD:*:*) echo powerppc-unknown-mirbsd${UNAME_RELEASE} exit 0 ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 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 ;; *:OS400:*:*) echo powerpc-ibm-os400 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:4.0:6*) echo sparc-icl-nx6 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 ;; m68k:machten:*:*) echo m68k-apple-machten${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'` \ && exit 0 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 && exit 0 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` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then # avoid double evaluation of $set_cc_for_build test -n "$CC_FOR_BUILD" || eval $set_cc_for_build if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi 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 && exit 0 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*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 ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${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 ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 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 ;; 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*:[34]*) echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' 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:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m32r*: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=` 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=` 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 ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu 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 #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` 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:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable 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[5678]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 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:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in *86) UNAME_PROCESSOR=i686 ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-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-?: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 ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit 0 ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms && exit 0 ;; I*) echo ia64-dec-vms && exit 0 ;; V*) echo vax-dec-vms && exit 0 ;; esac 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 && exit 0 # 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: kbuild-3686/src/oldsed/config/gettext-ver.m40000664000175000017500000000004715053010105020731 0ustar locutuslocutusAC_DEFUN([AM_GNU_GETTEXT_VERSION], []) kbuild-3686/src/oldsed/config/getline.m40000664000175000017500000000256215053010105020106 0ustar locutuslocutus#serial 4 dnl See if there's a working, system-supplied version of the getline function. dnl We can't just do AC_REPLACE_FUNCS(getline) because some systems dnl have a function by that name in -linet that doesn't have anything dnl to do with the function we need. AC_DEFUN([AM_FUNC_GETLINE], [dnl am_getline_needs_run_time_check=no AC_CHECK_FUNC(getline, dnl Found it in some library. Verify that it works. am_getline_needs_run_time_check=yes, am_cv_func_working_getline=no) if test $am_getline_needs_run_time_check = yes; then AC_CACHE_CHECK([for working getline function], am_cv_func_working_getline, [echo fooN |tr -d '\012'|tr N '\012' > conftest.data AC_TRY_RUN([ # include # include # include int main () { /* Based on a test program from Karl Heuer. */ char *line = NULL; size_t siz = 0; int len; FILE *in = fopen ("./conftest.data", "r"); if (!in) return 1; len = getline (&line, &siz, in); exit ((len == 4 && line && strcmp (line, "foo\n") == 0) ? 0 : 1); } ], am_cv_func_working_getline=yes dnl The library version works. , am_cv_func_working_getline=no dnl The library version does NOT work. , am_cv_func_working_getline=no dnl We're cross compiling. )]) fi if test $am_cv_func_working_getline = no; then AC_LIBOBJ(getline) fi ]) kbuild-3686/src/oldsed/config/progtest.m40000664000175000017500000000407415053010105020326 0ustar locutuslocutus# progtest.m4 serial 2 (gettext-0.10.40) dnl Copyright (C) 1996-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1996. # Search path for a program which passes the given test. dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) AC_DEFUN([AM_PATH_PROG_WITH_TEST], [# Extract the first word of "$2", so it can be a program name with args. set dummy $2; ac_word=[$]2 AC_MSG_CHECKING([for $ac_word]) AC_CACHE_VAL(ac_cv_path_$1, [case "[$]$1" in /*) ac_cv_path_$1="[$]$1" # Let the user override the test with a path. ;; *) IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" for ac_dir in ifelse([$5], , $PATH, [$5]); do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if [$3]; then ac_cv_path_$1="$ac_dir/$ac_word" break fi fi done IFS="$ac_save_ifs" dnl If no 4th arg is given, leave the cache variable unset, dnl so AC_PATH_PROGS will keep looking. ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" ])dnl ;; esac])dnl $1="$ac_cv_path_$1" if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then AC_MSG_RESULT([$]$1) else AC_MSG_RESULT(no) fi AC_SUBST($1)dnl ]) kbuild-3686/src/oldsed/config/iconv.m40000664000175000017500000000641315053010105017574 0ustar locutuslocutus# iconv.m4 serial AM3 (gettext-0.11) dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. dnl From Bruno Haible. AC_DEFUN([AM_ICONV_LINK], [ dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and dnl those with the standalone portable GNU libiconv installed). dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_LIB_LINKFLAGS_BODY([iconv]) dnl Add $INCICONV to CPPFLAGS before performing the following checks, dnl because if the user has installed libiconv and not disabled its use dnl via --without-libiconv-prefix, he wants to use it. The first dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed. am_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [ am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], am_cv_func_iconv=yes) if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], am_cv_lib_iconv=yes am_cv_func_iconv=yes) LIBS="$am_save_LIBS" fi ]) if test "$am_cv_func_iconv" = yes; then AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.]) fi if test "$am_cv_lib_iconv" = yes; then AC_MSG_CHECKING([how to link with libiconv]) AC_MSG_RESULT([$LIBICONV]) else dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV dnl either. CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi AC_SUBST(LIBICONV) AC_SUBST(LTLIBICONV) ]) AC_DEFUN([AM_ICONV], [ AC_REQUIRE([AM_ICONV_LINK]) if test "$am_cv_func_iconv" = yes; then AC_MSG_CHECKING([for iconv declaration]) AC_CACHE_VAL(am_cv_proto_iconv, [ AC_TRY_COMPILE([ #include #include extern #ifdef __cplusplus "C" #endif #if defined(__STDC__) || defined(__cplusplus) size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); #else size_t iconv(); #endif ], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const") am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` AC_MSG_RESULT([$]{ac_t:- }[$]am_cv_proto_iconv) AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1, [Define as const if the declaration of iconv() needs const.]) fi ]) kbuild-3686/src/oldsed/config/gettext.m40000664000175000017500000005232615053010105020146 0ustar locutuslocutus# gettext.m4 serial 12 (gettext-0.11) dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2002. dnl Macro to add for using GNU gettext. dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The dnl default (if it is not specified or empty) is 'no-libtool'. dnl INTLSYMBOL should be 'external' for packages with no intl directory, dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. dnl If INTLSYMBOL is 'use-libtool', then a libtool library dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, dnl depending on --{enable,disable}-{shared,static} and on the presence of dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library dnl $(top_builddir)/intl/libintl.a will be created. dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext dnl implementations (in libc or libintl) without the ngettext() function dnl will be ignored. dnl INTLDIR is used to find the intl libraries. If empty, dnl the value `$(top_builddir)/intl/' is used. dnl dnl The result of the configuration is one of three cases: dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled dnl and used. dnl Catalog format: GNU --> install in $(datadir) dnl Catalog extension: .mo after installation, .gmo in source tree dnl 2) GNU gettext has been found in the system's C library. dnl Catalog format: GNU --> install in $(datadir) dnl Catalog extension: .mo after installation, .gmo in source tree dnl 3) No internationalization, always use English msgid. dnl Catalog format: none dnl Catalog extension: none dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. dnl The use of .gmo is historical (it was needed to avoid overwriting the dnl GNU format catalogs when building on a platform with an X/Open gettext), dnl but we keep it in order not to force irrelevant filename changes on the dnl maintainers. dnl AC_DEFUN([AM_GNU_GETTEXT], [ dnl Argument checking. ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT ])])])])]) ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT ])])]) define(gt_included_intl, ifelse([$1], [external], [no], [yes])) define(gt_libtool_suffix_prefix, ifelse([$1], [use-libtool], [l], [])) AC_REQUIRE([AM_PO_SUBDIRS])dnl ifelse(gt_included_intl, yes, [ AC_REQUIRE([AM_INTL_SUBDIR])dnl ]) dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) AC_MSG_CHECKING([whether NLS is requested]) dnl Default is enabled NLS AC_ARG_ENABLE(nls, [ --disable-nls do not use Native Language Support], USE_NLS=$enableval, USE_NLS=yes) AC_MSG_RESULT($USE_NLS) AC_SUBST(USE_NLS) ifelse(gt_included_intl, yes, [ BUILD_INCLUDED_LIBINTL=no USE_INCLUDED_LIBINTL=no ]) LIBINTL= LTLIBINTL= POSUB= dnl If we use NLS figure out what method if test "$USE_NLS" = "yes"; then gt_use_preinstalled_gnugettext=no ifelse(gt_included_intl, yes, [ AC_MSG_CHECKING([whether included gettext is requested]) AC_ARG_WITH(included-gettext, [ --with-included-gettext use the GNU gettext library included here], nls_cv_force_use_gnu_gettext=$withval, nls_cv_force_use_gnu_gettext=no) AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" if test "$nls_cv_force_use_gnu_gettext" != "yes"; then ]) dnl User does not insist on using GNU NLS library. Figure out what dnl to use. If GNU gettext is available we use this. Else we have dnl to fall back to GNU NLS library. dnl Add a version number to the cache macros. define([gt_api_version], ifelse([$2], [need-ngettext], 2, 1)) define([gt_cv_func_gnugettext_libc], [gt_cv_func_gnugettext]gt_api_version[_libc]) define([gt_cv_func_gnugettext_libintl], [gt_cv_func_gnugettext]gt_api_version[_libintl]) AC_CACHE_CHECK([for GNU gettext in libc], gt_cv_func_gnugettext_libc, [AC_TRY_LINK([#include extern int _nl_msg_cat_cntr;], [bindtextdomain ("", ""); return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr], gt_cv_func_gnugettext_libc=yes, gt_cv_func_gnugettext_libc=no)]) if test "$gt_cv_func_gnugettext_libc" != "yes"; then dnl Sometimes libintl requires libiconv, so first search for libiconv. ifelse(gt_included_intl, yes, , [ AM_ICONV_LINK ]) dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) dnl because that would add "-liconv" to LIBINTL and LTLIBINTL dnl even if libiconv doesn't exist. AC_LIB_LINKFLAGS_BODY([intl]) AC_CACHE_CHECK([for GNU gettext in libintl], gt_cv_func_gnugettext_libintl, [gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $INCINTL" gt_save_LIBS="$LIBS" LIBS="$LIBS $LIBINTL" dnl Now see whether libintl exists and does not depend on libiconv. AC_TRY_LINK([#include extern int _nl_msg_cat_cntr;], [bindtextdomain ("", ""); return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr], gt_cv_func_gnugettext_libintl=yes, gt_cv_func_gnugettext_libintl=no) dnl Now see whether libintl exists and depends on libiconv. if test "$gt_cv_func_gnugettext_libintl" != yes && test -n "$LIBICONV"; then LIBS="$LIBS $LIBICONV" AC_TRY_LINK([#include extern int _nl_msg_cat_cntr;], [bindtextdomain ("", ""); return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr], [LIBINTL="$LIBINTL $LIBICONV" LTLIBINTL="$LTLIBINTL $LTLIBICONV" gt_cv_func_gnugettext_libintl=yes ]) fi CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS"]) fi dnl If an already present or preinstalled GNU gettext() is found, dnl use it. But if this macro is used in GNU gettext, and GNU dnl gettext is already preinstalled in libintl, we update this dnl libintl. (Cf. the install rule in intl/Makefile.in.) if test "$gt_cv_func_gnugettext_libc" = "yes" \ || { test "$gt_cv_func_gnugettext_libintl" = "yes" \ && test "$PACKAGE" != gettext; }; then gt_use_preinstalled_gnugettext=yes fi ifelse(gt_included_intl, yes, [ if test "$gt_use_preinstalled_gnugettext" != "yes"; then dnl GNU gettext is not found in the C library. dnl Fall back on included GNU gettext library. nls_cv_use_gnu_gettext=yes fi fi if test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Mark actions used to generate GNU NLS library. INTLOBJS="\$(GETTOBJS)" BUILD_INCLUDED_LIBINTL=yes USE_INCLUDED_LIBINTL=yes LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV" LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV" LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Mark actions to use GNU gettext tools. CATOBJEXT=.gmo fi ]) if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then AC_DEFINE(ENABLE_NLS, 1, [Define to 1 if translation of program messages to the user's native language is requested.]) else USE_NLS=no fi fi if test "$USE_NLS" = "yes"; then if test "$gt_use_preinstalled_gnugettext" = "yes"; then if test "$gt_cv_func_gnugettext_libintl" = "yes"; then AC_MSG_CHECKING([how to link with libintl]) AC_MSG_RESULT([$LIBINTL]) AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) fi dnl For backward compatibility. Some packages may be using this. AC_DEFINE(HAVE_GETTEXT, 1, [Define if the GNU gettext() function is already present or preinstalled.]) AC_DEFINE(HAVE_DCGETTEXT, 1, [Define if the GNU dcgettext() function is already present or preinstalled.]) fi dnl We need to process the po/ directory. POSUB=po fi ifelse(gt_included_intl, yes, [ dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL dnl to 'yes' because some of the testsuite requires it. if test "$PACKAGE" = gettext; then BUILD_INCLUDED_LIBINTL=yes fi dnl Make all variables we use known to autoconf. AC_SUBST(BUILD_INCLUDED_LIBINTL) AC_SUBST(USE_INCLUDED_LIBINTL) AC_SUBST(CATOBJEXT) AC_SUBST(INTLOBJS) dnl For backward compatibility. Some configure.ins may be using this. nls_cv_header_intl= nls_cv_header_libgt= dnl For backward compatibility. Some Makefiles may be using this. DATADIRNAME=share AC_SUBST(DATADIRNAME) dnl For backward compatibility. Some Makefiles may be using this. INSTOBJEXT=.mo AC_SUBST(INSTOBJEXT) dnl For backward compatibility. Some Makefiles may be using this. GENCAT=gencat AC_SUBST(GENCAT) dnl Enable libtool support if the surrounding package wishes it. INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX) ]) dnl For backward compatibility. Some Makefiles may be using this. INTLLIBS="$LIBINTL" AC_SUBST(INTLLIBS) dnl Make all documented variables known to autoconf. AC_SUBST(LIBINTL) AC_SUBST(LTLIBINTL) AC_SUBST(POSUB) ]) dnl Checks for all prerequisites of the po subdirectory, dnl except for USE_NLS. AC_DEFUN([AM_PO_SUBDIRS], [ AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl AC_REQUIRE([AM_MKINSTALLDIRS])dnl dnl Perform the following tests also if --disable-nls has been given, dnl because they are needed for "make dist" to work. dnl Search for GNU msgfmt in the PATH. dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. dnl The second test excludes FreeBSD msgfmt. AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, [$ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], :) AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) dnl Search for GNU xgettext 0.11 or newer in the PATH. dnl The first test excludes Solaris xgettext and early GNU xgettext versions. dnl The second test excludes FreeBSD xgettext. AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, [$ac_dir/$ac_word --omit-header --copyright-holder= /dev/null >/dev/null 2>&1 && (if $ac_dir/$ac_word --omit-header --copyright-holder= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], :) dnl Remove leftover from FreeBSD xgettext call. rm -f messages.po dnl Search for GNU msgmerge 0.11 or newer in the PATH. AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, [$ac_dir/$ac_word --update -q /dev/null /dev/null >/dev/null 2>&1], :) dnl This could go away some day; the PATH_PROG_WITH_TEST already does it. dnl Test whether we really found GNU msgfmt. if test "$GMSGFMT" != ":"; then dnl If it is no GNU msgfmt we define it as : so that the dnl Makefiles still can work. if $GMSGFMT --statistics /dev/null >/dev/null 2>&1 && (if $GMSGFMT --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then : ; else GMSGFMT=`echo "$GMSGFMT" | sed -e 's,^.*/,,'` AC_MSG_RESULT( [found $GMSGFMT program is not GNU msgfmt; ignore it]) GMSGFMT=":" fi fi dnl This could go away some day; the PATH_PROG_WITH_TEST already does it. dnl Test whether we really found GNU xgettext. if test "$XGETTEXT" != ":"; then dnl If it is no GNU xgettext we define it as : so that the dnl Makefiles still can work. if $XGETTEXT --omit-header --copyright-holder= /dev/null >/dev/null 2>&1 && (if $XGETTEXT --omit-header --copyright-holder= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then : ; else AC_MSG_RESULT( [found xgettext program is not GNU xgettext; ignore it]) XGETTEXT=":" fi dnl Remove leftover from FreeBSD xgettext call. rm -f messages.po fi AC_OUTPUT_COMMANDS([ for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" case "$ac_file" in *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; esac # PO directories have a Makefile.in generated from Makefile.in.in. case "$ac_file" in */Makefile.in) # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" # ALL_LINGUAS, POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES depend # on $ac_dir but don't depend on user-specified configuration # parameters. if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then # The LINGUAS file contains the set of available languages. if test -n "$ALL_LINGUAS"; then test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" "$ac_given_srcdir/$ac_dir/LINGUAS"` # Hide the ALL_LINGUAS assigment from automake. eval 'ALL_LINGUAS''=$ALL_LINGUAS_' fi case "$ac_given_srcdir" in .) srcdirpre= ;; *) srcdirpre='$(srcdir)/' ;; esac POFILES= GMOFILES= UPDATEPOFILES= DUMMYPOFILES= for lang in $ALL_LINGUAS; do POFILES="$POFILES $srcdirpre$lang.po" GMOFILES="$GMOFILES $srcdirpre$lang.gmo" UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" DUMMYPOFILES="$DUMMYPOFILES $lang.nop" done # CATALOGS depends on both $ac_dir and the user's LINGUAS # environment variable. INST_LINGUAS= if test -n "$ALL_LINGUAS"; then for presentlang in $ALL_LINGUAS; do useit=no if test "%UNSET%" != "$LINGUAS"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then INST_LINGUAS="$INST_LINGUAS $presentlang" fi done fi CATALOGS= if test -n "$INST_LINGUAS"; then for lang in $INST_LINGUAS; do CATALOGS="$CATALOGS $lang.gmo" done fi test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do if test -f "$f"; then case "$f" in *.orig | *.bak | *~) ;; *) cat "$f" >> "$ac_dir/Makefile" ;; esac fi done fi ;; esac done], [# Capture the value of obsolete $ALL_LINGUAS because we need it to compute # POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES, CATALOGS. But hide it # from automake. eval 'ALL_LINGUAS''="$ALL_LINGUAS"' # Capture the value of LINGUAS because we need it to compute CATALOGS. LINGUAS="${LINGUAS-%UNSET%}" ]) ]) dnl Checks for all prerequisites of the intl subdirectory, dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. AC_DEFUN([AM_INTL_SUBDIR], [ AC_REQUIRE([AC_PROG_INSTALL])dnl AC_REQUIRE([AM_MKINSTALLDIRS])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_RANLIB])dnl AC_REQUIRE([AC_ISC_POSIX])dnl AC_REQUIRE([AC_HEADER_STDC])dnl AC_REQUIRE([AC_C_CONST])dnl AC_REQUIRE([AC_C_INLINE])dnl AC_REQUIRE([AC_TYPE_OFF_T])dnl AC_REQUIRE([AC_TYPE_SIZE_T])dnl AC_REQUIRE([AC_FUNC_ALLOCA])dnl AC_REQUIRE([AC_FUNC_MMAP])dnl AC_REQUIRE([jm_GLIBC21])dnl AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h stddef.h \ stdlib.h string.h unistd.h sys/param.h]) AC_CHECK_FUNCS([feof_unlocked fgets_unlocked getc_unlocked getcwd getegid \ geteuid getgid getuid mempcpy munmap putenv setenv setlocale stpcpy \ strcasecmp strdup strtoul tsearch __argz_count __argz_stringify __argz_next]) AM_ICONV AM_LANGINFO_CODESET AM_LC_MESSAGES dnl intl/plural.c is generated from intl/plural.y. It requires bison, dnl because plural.y uses bison specific features. It requires at least dnl bison-1.26 because earlier versions generate a plural.c that doesn't dnl compile. dnl bison is only needed for the maintainer (who touches plural.y). But in dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put dnl the rule in general Makefile. Now, some people carelessly touch the dnl files or have a broken "make" program, hence the plural.c rule will dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not dnl present or too old. AC_CHECK_PROGS([INTLBISON], [bison]) if test -z "$INTLBISON"; then ac_verc_fail=yes else dnl Found it, now check the version. AC_MSG_CHECKING([version of bison]) changequote(<<,>>)dnl ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` case $ac_prog_version in '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) changequote([,])dnl ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; esac AC_MSG_RESULT([$ac_prog_version]) fi if test $ac_verc_fail = yes; then INTLBISON=: fi ]) AC_DEFUN([AM_MKINSTALLDIRS], [ dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly dnl find the mkinstalldirs script in another subdir but $(top_srcdir). dnl Try to locate is. MKINSTALLDIRS= if test -n "$ac_aux_dir"; then MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" fi if test -z "$MKINSTALLDIRS"; then MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" fi AC_SUBST(MKINSTALLDIRS) ]) kbuild-3686/src/oldsed/Makefile.in0000664000175000017500000005274215053010105017022 0ustar locutuslocutus# Makefile.in generated by automake 1.9.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = . am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = README $(am__configure_deps) $(noinst_HEADERS) \ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/bootstrap.sh.in $(srcdir)/config_h.in \ $(top_srcdir)/configure $(top_srcdir)/intl/Makefile.in \ ABOUT-NLS AUTHORS COPYING COPYING.DOC ChangeLog INSTALL NEWS \ README-alpha THANKS config/config.guess config/config.rpath \ config/config.sub config/depcomp config/install-sh \ config/mdate-sh config/missing config/texinfo.tex subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/codeset.m4 \ $(top_srcdir)/config/getline.m4 \ $(top_srcdir)/config/gettext-ver.m4 \ $(top_srcdir)/config/gettext.m4 \ $(top_srcdir)/config/glibc21.m4 $(top_srcdir)/config/iconv.m4 \ $(top_srcdir)/config/lcmessage.m4 \ $(top_srcdir)/config/lib-ld.m4 \ $(top_srcdir)/config/lib-link.m4 \ $(top_srcdir)/config/lib-prefix.m4 \ $(top_srcdir)/config/progtest.m4 \ $(top_srcdir)/config/stdbool.m4 \ $(top_srcdir)/config/strverscmp.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno configure.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = bootstrap.sh intl/Makefile SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-exec-recursive install-info-recursive \ install-recursive installcheck-recursive installdirs-recursive \ pdf-recursive ps-recursive uninstall-info-recursive \ uninstall-recursive DATA = $(noinst_DATA) HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ { test ! -d $(distdir) \ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr $(distdir); }; } DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_HTML_FALSE = @BUILD_HTML_FALSE@ BUILD_HTML_TRUE = @BUILD_HTML_TRUE@ BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GENCAT = @GENCAT@ GLIBC21 = @GLIBC21@ GMSGFMT = @GMSGFMT@ HAVE__BOOL = @HAVE__BOOL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLBISON = @INTLBISON@ INTLLIBS = @INTLLIBS@ INTLOBJS = @INTLOBJS@ INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MAKEINFO_HTML_FALSE = @MAKEINFO_HTML_FALSE@ MAKEINFO_HTML_TRUE = @MAKEINFO_HTML_TRUE@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = sed PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ RANLIB = @RANLIB@ SED_FEATURE_VERSION = @SED_FEATURE_VERSION@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TEST_REGEX_FALSE = @TEST_REGEX_FALSE@ TEST_REGEX_TRUE = @TEST_REGEX_TRUE@ TEXI2HTML = @TEXI2HTML@ TEXI2HTML_HTML_FALSE = @TEXI2HTML_HTML_FALSE@ TEXI2HTML_HTML_TRUE = @TEXI2HTML_HTML_TRUE@ USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ # Automake requirements AUTOMAKE_OPTIONS = gnits 1.8 ACLOCAL_AMFLAGS = -I config SUBDIRS = intl lib po sed doc testsuite noinst_DATA = bootstrap.sh noinst_HEADERS = basicdefs.h EXTRA_DIST = BUGS THANKS COPYING.DOC README.boot bootstrap.sh \ config/texi2dvi config/help2man DISTCHECK_CONFIGURE_FLAGS = XGETTEXT='$(SHELL) -c : dummy' $(EXTRA_DC_FLAGS) EXTRA_DC_FLAGS = all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnits '; \ cd $(srcdir) && $(AUTOMAKE) --gnits \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnits Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) config.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ $(MAKE) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/config_h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config_h.in: $(am__configure_deps) cd $(top_srcdir) && $(AUTOHEADER) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 bootstrap.sh: $(top_builddir)/config.status $(srcdir)/bootstrap.sh.in cd $(top_builddir) && $(SHELL) ./config.status $@ intl/Makefile: $(top_builddir)/config.status $(top_srcdir)/intl/Makefile.in cd $(top_builddir) && $(SHELL) ./config.status $@ uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) config_h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) config_h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config_h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) config_h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @case `sed 15q $(srcdir)/NEWS` in \ *"$(VERSION)"*) : ;; \ *) \ echo "NEWS not updated; not releasing" 1>&2; \ exit 1;; \ esac $(am__remove_distdir) mkdir $(distdir) $(mkdir_p) $(distdir)/. $(distdir)/config $(distdir)/intl $(distdir)/lib $(distdir)/po @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(mkdir_p) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ distdir) \ || exit 1; \ fi; \ done -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r $(distdir) dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && cd $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ --with-included-gettext \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' distuninstallcheck: @cd $(distuninstallcheck_dir) \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) $(HEADERS) config.h installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr distclean-tags dvi: dvi-recursive dvi-am: info: info-recursive info-am: install-data-am: install-exec-am: install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \ check-am clean clean-generic clean-recursive ctags \ ctags-recursive dist dist-all dist-bzip2 dist-gzip dist-shar \ dist-tarZ dist-zip distcheck distclean distclean-generic \ distclean-hdr distclean-recursive distclean-tags \ distcleancheck distdir distuninstallcheck dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic maintainer-clean-recursive \ mostlyclean mostlyclean-generic mostlyclean-recursive pdf \ pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ uninstall-info-am html: cd doc && make html full-distcheck: make distcheck EXTRA_DC_FLAGS='--enable-html' make distcheck EXTRA_DC_FLAGS='--disable-i18n' make distcheck EXTRA_DC_FLAGS='--disable-nls' make distcheck EXTRA_DC_FLAGS='--without-included-regex' make distcheck EXTRA_DC_FLAGS='--without-included-gettext' update-regex: HOST=sources.redhat.com && \ BASEURL="http://$$HOST/cgi-bin/cvsweb.cgi/~checkout~/libc/posix" && \ QUERY='cvsroot=glibc&content-type=text/plain' && \ wget -O lib/regcomp.c "$$BASEURL/regcomp.c?$$QUERY" && \ wget -O lib/regexec.c "$$BASEURL/regexec.c?$$QUERY" && \ wget -O lib/regex.c "$$BASEURL/regex.c?$$QUERY" && \ wget -O lib/regex_.h "$$BASEURL/regex.h?$$QUERY" && \ wget -O lib/regex_internal.c "$$BASEURL/regex_internal.c?$$QUERY" && \ wget -O lib/regex_internal.h "$$BASEURL/regex_internal.h?$$QUERY" && \ wget -O testsuite/BOOST.tests "$$BASEURL/BOOST.tests?$$QUERY" && \ wget -O testsuite/PCRE.tests "$$BASEURL/PCRE.tests?$$QUERY" && \ wget -O testsuite/SPENCER.tests "$$BASEURL/rxspencer/tests?$$QUERY" # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: kbuild-3686/src/oldsed/NEWS0000664000175000017500000004045615053010105015453 0ustar locutuslocutusSed 4.1.5 * fix parsing of a negative character class not including a closed bracket, like [^]] or [^]a-z]. * fix parsing of [ inside an y command, like y/[/A/. * output the result of commands a, r, R when a q command is found. ---------------------------------------------------------------------------- Sed 4.1.4 * \B correctly means "not on a word boundary" rather than "inside a word" * bugfixes for platform without internationalization * more thorough testing framework for tarballs (`make full-distcheck') ---------------------------------------------------------------------------- Sed 4.1.3 * regex addresses do not use leftmost-longest matching. In other words, /.\+/ only looks for a single character, and does not try to find as many of them as possible like it used to do. * added a note to BUGS and the manual about changed interpretation of `s|abc\|def||', and about localization issues. * fixed --disable-nls build problems on Solaris. * fixed `make check' in non-English locales. * `make check' tests the regex library by default if the included regex is used (regex tests had to be enabled separately up to now). ---------------------------------------------------------------------------- Sed 4.1.2 * fix bug in 'y' command in multi-byte character sets * fix severe bug in parsing of ranges with an embedded open bracket * fix off-by-one error when printing a "bad command" error ---------------------------------------------------------------------------- Sed 4.1.1 * preserve permissions of in-place edited files * yield an error when running -i on terminals or other non regular files * do not interpret - as stdin when running in in-place editing mode * fix bug that prevented 's' command modifiers from working ---------------------------------------------------------------------------- Sed 4.1 * // matches the last regular expression even in POSIXLY_CORRECT mode. * change the way we treat lines which are not terminated by a newline. Such lines are printed without the terminating newline (as before) but as soon as more text is sent to the same output stream, the missing newline is printed, so that the two lines don't concatenate. The behavior is now independent from POSIXLY_CORRECT because POSIX actually has undefined behavior in this case, and the new implementation arguably gives the ``least expected surprise''. Thanks to Stepan Kasal for the implementation. * documentation improvements, with updated references to the POSIX.2 specification * error messages on I/O errors are better, and -i does not leave temporary files around (e.g. when running ``sed -i'' on a directory). * escapes are accepted in the y command (for example: y/o/\n/ transforms o's into newlines) * -i option tries to set the owner and group to the same as the input file * `L' command is deprecated and will be removed in sed 4.2. * line number addresses are processed differently -- this is supposedly conformant to POSIX and surely more idiot-proof. Line number addresses are not affected by jumping around them: they are activated and deactivated exactly where the script says, while previously 5,8b 1,5d would actually delete lines 1,2,3,4 and 9 (!). * multibyte characters are taken in consideration to compute the operands of s and y, provided you set LC_CTYPE correctly. They are also considered by \l, \L, \u, \U, \E. * [\n] matches either backslash or 'n' when POSIXLY_CORRECT. * new option --posix, disables all GNU extensions. POSIXLY_CORRECT only disables GNU extensions that violate the POSIX standard. * options -h and -V are not supported anymore, use --help and --version. * removed documentation for \s and \S which worked incorrectly * restored correct behavior for \w and \W: match [[:alnum:]_] and [^[:alnum:]_] (they used to match [[:alpha:]_] and [^[:alpha:]_] * the special address 0 can only be used in 0,/RE/ or 0~STEP addresses; other cases give an error (you are hindering portability for no reason if specifying 0,N and you are giving a dead command if specifying 0 alone). * when a \ is used to escape the character that would terminate an operand of the s or y commands, the backslash is removed before the regex is compiled. This is left undefined by POSIX; this behavior makes `s+x\+++g' remove occurrences of `x+', consistently with `s/x\///g'. (However, if you enjoy yourself trying `s*x\***g', sed will use the `x*' regex, and you won't be able to pass down `x\*' while using * as the delimiter; ideas on how to simplify the parser in this respect, and/or gain more coherent semantics, are welcome). ---------------------------------------------------------------------------- Sed 4.0.9 * 0 address behaves correctly in single-file (-i and -s) mode. * documentation improvements. * tested with many hosts and compilers. * updated regex matcher from upstream, with many bugfixes and speedups. * the `N' command's feature that is detailed in the BUGS file was disabled by the first change below in sed 4.0.8. The behavior has now been restored, and is only enabled if POSIXLY_CORRECT behavior is not requested. ---------------------------------------------------------------------------- Sed 4.0.8 * fix `sed n' printing the last line twice. * fix incorrect error message for invalid character classes. * fix segmentation violation with repeated empty subexpressions. * fix incorrect parsing of ^ after escaped (. * more comprehensive test suite (and with many expected failures...) ---------------------------------------------------------------------------- Sed 4.0.7 * VPATH builds working on non-glibc machines * fixed bug in s///Np: was printing even if less than N matches were found. * fixed infinite loop on s///N when LHS matched a null string and there were not enough matches in pattern space * behavior of s///N is consistent with s///g when the LHS can match a null string (and the infinite loop did not happen :-) * updated some translations ---------------------------------------------------------------------------- Sed 4.0.6 * added parameter to `v' for the version of sed that is expected. * configure switch --without-included-regex to use the system regex matcher * fix for -i option under Cygwin ---------------------------------------------------------------------------- Sed 4.0.5 * portability fixes * improvements to some error messages (e.g. y/abc/defg/ incorrectly said `excess characters after command' instead of `y arguments have different lengths') * `a', `i', `l', `L', `r' accept two addresses except in POSIXLY_CORRECT mode. Only `q' and `Q' do not accept two addresses in standard (GNU) mode. ---------------------------------------------------------------------------- Sed 4.0.4 * documentation fixes * update regex matcher ---------------------------------------------------------------------------- Sed 4.0.3 * fix packaging problem (two missing translation catalogs) ---------------------------------------------------------------------------- Sed 4.0.2 * more translations * fix build problems (vpath builds and bootstrap builds) ---------------------------------------------------------------------------- Sed 4.0.1 * Remove last vestiges of super-sed * man page automatically built * more translations provided * portability improvements ---------------------------------------------------------------------------- Sed 4.0 * Update regex matcher ---------------------------------------------------------------------------- Sed 3.96 * `y' command supports multibyte character sets * Update regex matcher ---------------------------------------------------------------------------- Sed 3.95 * `R' command reads a single line from a file. * CR-LF pairs are always ignored under Windows, even if (under Cygwin) a disk is mounted as binary. * More attention to errors on stdout * New `W' command to write first line of pattern space to a file * Can customize line wrap width on single `l' commands * `L' command formats and reflows paragraphs like `fmt' does. * The test suite makefiles are better organized (this change is transparent however). * Compiles and bootstraps out-of-the-box under MinGW32 and Cygwin. * Optimizes cases when pattern space is truncated at its start or at its end by `D' or by a substitution command with an empty RHS. For example scripts like this, seq 1 10000 | tr \\n \ | ./sed ':a; s/^[0-9][0-9]* //; ta' whose behavior was quadratic with previous versions of sed, have now linear behavior. * New command `e' to pipe the output of a command into the output of sed. * New option `e' to pass the output of the `s' command through the Bourne shell and get the result into pattern space. * Switched to obstacks in the parser -- less memory-related bugs (there were none AFAIK but you never know) and less memory usage. * New option -i, to support in-place editing a la Perl. Usually one had to use ed or, for more complex tasks, resort to Perl; this is not necessary anymore. * Dumped buffering code. The performance loss is 10%, but it caused bugs in systems with CRLF termination. The current solution is not definitive, though. * Bug fix: Made the behavior of s/A*/x/g (i.e. `s' command with a possibly empty LHS) more consistent: pattern GNU sed 3.x GNU sed 4.x B xBx xBx BC xBxCx xBxCx BAC xBxxCx xBxCx BAAC xBxxCx xBxCx * Bug fix: the // empty regular expressions now refers to the last regular expression that was matched, rather than to the last regular expression that was compiled. This richer behavior seems to be the correct one (albeit neither one is POSIXLY_CORRECT). * Check for invalid backreferences in the RHS of the `s' command (e.g. s/1234/\1/) * Support for \[lLuUE] in the RHS of the `s' command like in Perl. * New regular expression matcher * Bug fix: if a file was redirected to be stdin, sed did not consume it. So (sed d; sed G) < TESTFILE double-spaced TESTFILE, while the equivalent `useless use of cat' cat TESTFILE | (sed d; sed G) printed nothing (which is the correct behavior). A test for this bug was added to the test suite. * The documentation is now much better, with a few examples provided, and a thorough description of regular expressions. The manual often refers to "GNU extensions", but if they are described here they are specific to this version. * Documented command-line option: -r, --regexp-extended Use extended regexps -- e.g. (abc+) instead of \(abc\+\) * Added feature to the `w' command and to the `w' option of the `s' command: if the file name is /dev/stderr, it means the standard error (inspired by awk); and similarly for /dev/stdout. This is disabled if POSIXLY_CORRECT is set. * Added `m' and `M' modifiers to `s' command for multi-line matching (Perl-style); in addresses, only `M' works. * Added `Q' command for `silent quit'; added ability to pass an exit code from a sed script to the caller. * Added `T' command for `branch if failed'. * Added `v' command, which is a do-nothing intended to fail on seds that do not support GNU sed 4.0's extensions. ---------------------------------------------------------------------------- Sed 3.02.80 * Started new version nomenclature for pre-3.03 releases. (I'm being pessimistic in assuming that .90 won't give me enough breathing room.) * Bug fixes: the regncomp()/regnexec() interfaces proved to be inadequate to properly handle expressions such as "s/\ after a, i, and c commands). Also, conditionally (on NO_INPUT_INDENT) added experimental support for skipping leading whitespace on each {a,i,c} input line. * Added addressing of the form: /foo/,+5 p (print from foo to 5th line following) /foo/,~5 p (print from foo to next line whose line number is a multiple of 5) The first address of these can be any of the previously existing addressing types; the +N and ~N forms are only allowed as the second address of a range. * Added support for pseudo-address "0" as the first address in an address-range, simplifying scripts which happen to match the end address on the first line of input. For example, a script which deletes all lines from the beginning of the file to the first line which contains "foo" is now simply "sed 0,/foo/d", whereas before one had to go through contortions to deal with the possibility that "foo" might appear on the first line of the input. * Made NUL characters in regexps work "correctly" --- i.e., a NUL in a RE matches a NUL; it does not prematurely terminate the RE. (This only works in -f scripts, as the POSIX.1 exec*() interface only passes NUL-terminated strings, and so sed will only be able to see up to the first NUL in any -e scriptlet.) * Wherever a `;' is accepted as a command terminator, also allow a `}' or a `#' to appear. (This allows for less cluttered-looking scripts.) * Lots of internal changes that are only relevant to source junkies and development testing. Some of which might cause imperceptible performance improvements. ---------------------------------------------------------------------------- Sed 3.02 * Fixed a bug in the parsing of character classes (e.g., /[[:space:]]/). Corrected an omission in djgpp/Makefile.am and an improper dependency in testsuite/Makefile.am. ---------------------------------------------------------------------------- Sed 3.01 * This version of sed mainly contains bug fixes and portability enhancements, plus performance enhancements related to sed's handling of input files. Due to excess performance penalties, I have reverted (relative to 3.00) to using regex.c instead of the rx package for regular expression handling, at the expense of losing true POSIX.2 BRE compatibility. However, performance related to regular expression handling *still* needs a fair bit of work. * One new feature has been added: regular expressions may be followed with an "I" directive ("i" was taken [the "i"nsert command]) to indicate that the regexp should be matched in a case-insensitive manner. Also of note are a new organization to the source code, new documentation, and a new maintainer. ---------------------------------------------------------------------------- Sed 3.0 * This version of sed passes the new test-suite donated by Jason Molenda. * Overall performance has been improved in the following sense: Sed 3.0 is often slightly slower than sed 2.05. On a few scripts, though, sed 2.05 was so slow as to be nearly useless or to use up unreasonable amounts of memory. These problems have been fixed and in such cases, sed 3.0 should have acceptable performance. kbuild-3686/src/oldsed/config.h.os20000664000175000017500000002437515053010105017076 0ustar locutuslocutus/* config.h. Generated by configure. */ /* config_h.in. Generated from configure.ac by autoheader. */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if translation of program messages to the user's native language is requested. */ /* #undef ENABLE_NLS */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ #define HAVE_ALLOCA_H 1 /* Define to 1 if you have the header file. */ #define HAVE_ARGZ_H 1 /* Define to 1 if you have the `bcopy' function. */ #define HAVE_BCOPY 1 /* Define to 1 if you have the `btowc' function. */ #define HAVE_BTOWC 1 /* Define to 1 if you have the `bzero' function. */ #define HAVE_BZERO 1 /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* #undef HAVE_DCGETTEXT */ /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ /* #undef HAVE_DOPRNT */ /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H 1 /* Define to 1 if you have the `fchmod' function. */ #define HAVE_FCHMOD 1 /* Define to 1 if you have the `fchown' function. */ #define HAVE_FCHOWN 1 /* Define to 1 if you have the `feof_unlocked' function. */ #define HAVE_FEOF_UNLOCKED 1 /* Define to 1 if you have the `fgets_unlocked' function. */ #define HAVE_FGETS_UNLOCKED 1 /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getc_unlocked' function. */ #define HAVE_GETC_UNLOCKED 1 /* Define to 1 if you have the `getegid' function. */ #define HAVE_GETEGID 1 /* Define to 1 if you have the `geteuid' function. */ #define HAVE_GETEUID 1 /* Define to 1 if you have the `getgid' function. */ #define HAVE_GETGID 1 /* Define to 1 if you have the `getpagesize' function. */ #define HAVE_GETPAGESIZE 1 /* Define if the GNU gettext() function is already present or preinstalled. */ /* #undef HAVE_GETTEXT */ /* Define to 1 if you have the `getuid' function. */ #define HAVE_GETUID 1 /* Define if you have the iconv() function. */ #define HAVE_ICONV 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_IO_H 1 /* Define to 1 if you have the `isascii' function. */ #define HAVE_ISASCII 1 /* Define to 1 if you have the `isatty' function. */ #define HAVE_ISATTY 1 /* Define to 1 if you have the `isblank' function. */ #define HAVE_ISBLANK 1 /* Define if you have and nl_langinfo(CODESET). */ #define HAVE_LANGINFO_CODESET 1 /* Define if your file defines LC_MESSAGES. */ #define HAVE_LC_MESSAGES 1 /* Define to 1 if you have the `regex' library (-lregex). */ /* #undef HAVE_LIBREGEX */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you support file names longer than 14 characters. */ #define HAVE_LONG_FILE_NAMES 1 /* Define to 1 if you have the header file. */ #define HAVE_MALLOC_H 1 /* Define to 1 if mbrtowc and mbstate_t are properly declared. */ #define HAVE_MBRTOWC 1 /* Define to 1 if declares mbstate_t. */ #define HAVE_MBSTATE_T 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MCHECK_H */ /* Define to 1 if you have the `memchr' function. */ #define HAVE_MEMCHR 1 /* Define to 1 if you have the `memcmp' function. */ #define HAVE_MEMCMP 1 /* Define to 1 if you have the `memcpy' function. */ #define HAVE_MEMCPY 1 /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mempcpy' function. */ #define HAVE_MEMPCPY 1 /* Define to 1 if you have the `memset' function. */ #define HAVE_MEMSET 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have a working `mmap' system call. */ /* #undef HAVE_MMAP */ /* Define to 1 if you have the `munmap' function. */ /* #undef HAVE_MUNMAP */ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_NL_TYPES_H 1 /* Define to 1 if libc includes obstacks. */ #define HAVE_OBSTACK 1 /* Define to 1 if you have the `pathconf' function. */ #define HAVE_PATHCONF 1 /* Define to 1 if you have the `popen' function. */ #define HAVE_POPEN 1 /* Define to 1 if you have the `putenv' function. */ #define HAVE_PUTENV 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_REGEX_H */ /* Define to 1 if you have the `setenv' function. */ #define HAVE_SETENV 1 /* Define to 1 if you have the `setlocale' function. */ #define HAVE_SETLOCALE 1 /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if stdbool.h conforms to C99. */ #define HAVE_STDBOOL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `stpcpy' function. */ #define HAVE_STPCPY 1 /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strtoul' function. */ #define HAVE_STRTOUL 1 /* Define to 1 if you have the `strverscmp' function. */ #define HAVE_STRVERSCMP 1 /* 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. */ #define HAVE_SYS_FILE_H 1 /* 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. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the `tsearch' function. */ #define HAVE_TSEARCH 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_WCHAR_H 1 /* Define to 1 if you have the `wcrtomb' function. */ #define HAVE_WCRTOMB 1 /* Define to 1 if you have the `wcscoll' function. */ #define HAVE_WCSCOLL 1 /* Define to 1 if you have the header file. */ #define HAVE_WCTYPE_H 1 /* Define to 1 if the system has the type `_Bool'. */ #define HAVE__BOOL 1 /* Define to 1 if you have the `__argz_count' function. */ #define HAVE___ARGZ_COUNT 1 /* Define to 1 if you have the `__argz_next' function. */ #define HAVE___ARGZ_NEXT 1 /* Define to 1 if you have the `__argz_stringify' function. */ #define HAVE___ARGZ_STRINGIFY 1 /* Define as const if the declaration of iconv() needs const. */ #define ICONV_CONST const /* Name of package */ #define PACKAGE "sed" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bonzini@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "sed" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "sed 4.1.5" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "sed" /* Define to the version of this package. */ #define PACKAGE_VERSION "4.1.5" /* Define to the version of GNU sed whose features are supported by this sed. */ #define SED_FEATURE_VERSION "4.1" /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ #define VERSION "4.1.5" /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* # undef _ALL_SOURCE */ #endif /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Include BSD functions in regex, used by the testsuite */ #define _REGEX_RE_COMP 1 /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to a type if does not define. */ /* #undef mbstate_t */ /* Define to `long' if does not define. */ /* #undef off_t */ /* Define to `unsigned' if does not define. */ /* #undef size_t */ /* Define to `int' if does not define. */ /* #undef ssize_t */ kbuild-3686/src/oldsed/AUTHORS0000664000175000017500000000031515053010105016012 0ustar locutuslocutusGNU Sed was first authored by Jay Fenlason (hack@gnu.org) and later modified by Tom Lord (lord@gnu.org). It is currently being maintained by Ken Pizzini (ken@gnu.org) and Paolo Bonzini (bonzini@gnu.org). kbuild-3686/src/oldsed/testsuite/0000775000175000017500000000000015053010105016774 5ustar locutuslocutuskbuild-3686/src/oldsed/testsuite/numsub3.good0000664000175000017500000000000015053010105021230 0ustar locutuslocutuskbuild-3686/src/oldsed/testsuite/xabcx.good0000664000175000017500000000010215053010105020744 0ustar locutuslocutusroses are red violets are blue my feet are cold your feet are too kbuild-3686/src/oldsed/testsuite/bug-regex16.c0000664000175000017500000000162615053010105021201 0ustar locutuslocutus/* Test re_compile_pattern error messages. */ #include #include #include int main (void) { struct re_pattern_buffer re; const char *s; int ret = 0; re_set_syntax (RE_SYNTAX_POSIX_EGREP); memset (&re, 0, sizeof (re)); s = re_compile_pattern ("[[.invalid_collating_symbol.]]", 30, &re); if (s == NULL || strcmp (s, "Invalid collation character")) { printf ("re_compile_pattern returned %s\n", s); ret = 1; } s = re_compile_pattern ("[[=invalid_equivalence_class=]]", 31, &re); if (s == NULL || strcmp (s, "Invalid collation character")) { printf ("re_compile_pattern returned %s\n", s); ret = 1; } s = re_compile_pattern ("[[:invalid_character_class:]]", 29, &re); if (s == NULL || strcmp (s, "Invalid character class name")) { printf ("re_compile_pattern returned %s\n", s); ret = 1; } return ret; } kbuild-3686/src/oldsed/testsuite/bug-regex8.c0000664000175000017500000000443215053010105021120 0ustar locutuslocutus/* Test for the STOP parameter of re_match_2 and re_search_2. Copyright (C) 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Stepan Kasal , 2002. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include int main (void) { struct re_pattern_buffer regex; const char *s; int match[4]; memset (®ex, '\0', sizeof (regex)); s = re_compile_pattern ("xy$", 3, ®ex); if (s != NULL) { puts ("failed to compile pattern \"xy$\""); return 1; } else match[0] = re_match_2(®ex,"xyz",3,NULL,0,0,NULL,2); free (regex.buffer); memset (®ex, '\0', sizeof (regex)); s = re_compile_pattern ("xy\\>", 4, ®ex); if (s != NULL) { puts ("failed to compile pattern \"xy\\>\""); return 1; } else match[1] = re_search_2(®ex,"xyz",3,NULL,0,0,2,NULL,2); free (regex.buffer); memset (®ex, '\0', sizeof (regex)); s = re_compile_pattern ("xy \\<", 5, ®ex); if (s != NULL) { puts ("failed to compile pattern \"xy \\<\""); return 1; } else { match[2] = re_match_2(®ex,"xy ",4,NULL,0,0,NULL,3); match[3] = re_match_2(®ex,"xy z",4,NULL,0,0,NULL,3); } if (match[0] != -1 || match[1] != -1 || match[2] != -1 || match[3] != 3) { printf ("re_{match,search}_2 returned %d,%d,%d,%d, expected -1,-1,-1,3\n", match[0], match[1], match[2], match[3]); return 1; } puts (" -> OK"); return 0; } kbuild-3686/src/oldsed/testsuite/bug-regex21.c0000664000175000017500000000257115053010105021175 0ustar locutuslocutus/* Test for memory leaks in regcomp. Copyright (C) 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2003. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #ifdef HAVE_MCHECK_H #include #endif #include #include int main (void) { regex_t re; int i; int ret = 0; #ifdef HAVE_MCHECK_H mtrace (); #endif for (i = 0; i < 32; ++i) { if (regcomp (&re, "X-.+:.+Y=\".*\\.(A|B|C|D|E|F|G|H|I", REG_EXTENDED | REG_ICASE) == 0) { puts ("regcomp unexpectedly succeeded"); ret = 1; } else regfree (&re); } return ret; } kbuild-3686/src/oldsed/testsuite/factor.good0000664000175000017500000000004115053010105021117 0ustar locutuslocutus2 3 2 2 5 2 2 2 11 2 2 2 2 13 11 kbuild-3686/src/oldsed/testsuite/binary.good0000664000175000017500000000003215053010105021125 0ustar locutuslocutus192 168 1 0 192 168 1 255 kbuild-3686/src/oldsed/testsuite/recall.good0000664000175000017500000000006115053010105021105 0ustar locutuslocutuseeefff Xeefff XYefff XYeYff XYeYYf XYeYYY XYeYYY kbuild-3686/src/oldsed/testsuite/0range.inp0000664000175000017500000000002015053010105020650 0ustar locutuslocutus1 2 3 4 aaa yes kbuild-3686/src/oldsed/testsuite/khadafy.inp0000664000175000017500000000133115053010105021111 0ustar locutuslocutus1) Muammar Qaddafi 2) Mo'ammar Gadhafi 3) Muammar Kaddafi 4) Muammar Qadhafi 5) Moammar El Kadhafi 6) Muammar Gadafi 7) Mu'ammar al-Qadafi 8) Moamer El Kazzafi 9) Moamar al-Gaddafi 10) Mu'ammar Al Qathafi 11) Muammar Al Qathafi 12) Mo'ammar el-Gadhafi 13) Moamar El Kadhafi 14) Muammar al-Qadhafi 15) Mu'ammar al-Qadhdhafi 16) Mu'ammar Qadafi 17) Moamar Gaddafi 18) Mu'ammar Qadhdhafi 19) Muammar Khaddafi 20) Muammar al-Khaddafi 21) Mu'amar al-Kadafi 22) Muammar Ghaddafy 23) Muammar Ghadafi 24) Muammar Ghaddafi 25) Muamar Kaddafi 26) Muammar Quathafi 27) Muammar Gheddafi 28) Muamar Al-Kaddafi 29) Moammar Khadafy 30) Moammar Qudhafi 31) Mu'ammar al-Qaddafi 32) Mulazim Awwal Mu'ammar Muhammad Abu Minyar al-Qadhafi kbuild-3686/src/oldsed/testsuite/ptestcases.h0000664000175000017500000003206015053010105021324 0ustar locutuslocutus { 0, 0, "2.8.2 Regular Expression General Requirement", NULL, }, { 2, 4, "bb*", "abbbc", }, { 2, 2, "bb*", "ababbbc", }, { 7, 9, "A#*::", "A:A#:qA::qA#::qA##::q", }, { 1, 5, "A#*::", "A##::A#::qA::qA#:q", }, { 0, 0, "2.8.3.1.2 BRE Special Characters", NULL, }, { 0, 0, "GA108", NULL, }, { 2, 2, "\\.", "a.c", }, { 2, 2, "\\[", "a[c", }, { 2, 2, "\\\\", "a\\c", }, { 2, 2, "\\*", "a*c", }, { 2, 2, "\\^", "a^c", }, { 2, 2, "\\$", "a$c", }, { 7, 11, "X\\*Y\\*8", "Y*8X*8X*Y*8", }, { 0, 0, "GA109", NULL, }, { 2, 2, "[.]", "a.c", }, { 2, 2, "[[]", "a[c", }, { -1, -1, "[[]", "ac", }, { 2, 2, "[\\]", "a\\c", }, { 1, 1, "[\\a]", "abc", }, { 2, 2, "[\\.]", "a\\.c", }, { 2, 2, "[\\.]", "a.\\c", }, { 2, 2, "[*]", "a*c", }, { 2, 2, "[$]", "a$c", }, { 2, 2, "[X*Y8]", "7*8YX", }, { 0, 0, "GA110", NULL, }, { 2, 2, "*", "a*c", }, { 3, 4, "*a", "*b*a*c", }, { 1, 5, "**9=", "***9=9", }, { 0, 0, "GA111", NULL, }, { 1, 1, "^*", "*bc", }, { -1, -1, "^*", "a*c", }, { -1, -1, "^*", "^*ab", }, { 1, 5, "^**9=", "***9=", }, { -1, -1, "^*5<*9", "5<9*5<*9", }, { 0, 0, "GA112", NULL, }, { 2, 3, "\\(*b\\)", "a*b", }, { -1, -1, "\\(*b\\)", "ac", }, { 1, 6, "A\\(**9\\)=", "A***9=79", }, { 0, 0, "GA113(1)", NULL, }, { 1, 3, "\\(^*ab\\)", "*ab", }, { -1, -1, "\\(^*ab\\)", "^*ab", }, { -1, -1, "\\(^*b\\)", "a*b", }, { -1, -1, "\\(^*b\\)", "^*b", }, { 0, 0, "GA114", NULL, }, { 1, 3, "a^b", "a^b", }, { 1, 3, "a\\^b", "a^b", }, { 1, 1, "^^", "^bc", }, { 2, 2, "\\^", "a^c", }, { 1, 1, "[c^b]", "^abc", }, { 1, 1, "[\\^ab]", "^ab", }, { 2, 2, "[\\^ab]", "c\\d", }, { -1, -1, "[^^]", "^", }, { 1, 3, "\\(a^b\\)", "a^b", }, { 1, 3, "\\(a\\^b\\)", "a^b", }, { 2, 2, "\\(\\^\\)", "a^b", }, { 0, 0, "GA115", NULL, }, { 3, 3, "$$", "ab$", }, { -1, -1, "$$", "$ab", }, { 2, 3, "$c", "a$c", }, { 2, 2, "[$]", "a$c", }, { 1, 2, "\\$a", "$a", }, { 3, 3, "\\$$", "ab$", }, { 2, 6, "A\\([34]$[34]\\)B", "XA4$3BY", }, { 0, 0, "2.8.3.1.3 Periods in BREs", NULL, }, { 0, 0, "GA116", NULL, }, { 1, 1, ".", "abc", }, { -1, -1, ".ab", "abc", }, { 1, 3, "ab.", "abc", }, { 1, 3, "a.b", "a,b", }, { -1, -1, ".......", "PqRs6", }, { 1, 7, ".......", "PqRs6T8", }, { 0, 0, "2.8.3.2 RE Bracket Expression", NULL, }, { 0, 0, "GA118", NULL, }, { 2, 2, "[abc]", "xbyz", }, { -1, -1, "[abc]", "xyz", }, { 2, 2, "[abc]", "xbay", }, { 0, 0, "GA119", NULL, }, { 2, 2, "[^a]", "abc", }, { 4, 4, "[^]cd]", "cd]ef", }, { 2, 2, "[^abc]", "axyz", }, { -1, -1, "[^abc]", "abc", }, { 3, 3, "[^[.a.]b]", "abc", }, { 3, 3, "[^[=a=]b]", "abc", }, { 2, 2, "[^-ac]", "abcde-", }, { 2, 2, "[^ac-]", "abcde-", }, { 3, 3, "[^a-b]", "abcde", }, { 3, 3, "[^a-bd-e]", "dec", }, { 2, 2, "[^---]", "-ab", }, { 16, 16, "[^a-zA-Z0-9]", "pqrstVWXYZ23579#", }, { 0, 0, "GA120(1)", NULL, }, { 3, 3, "[]a]", "cd]ef", }, { 1, 1, "[]-a]", "a_b", }, { 3, 3, "[][.-.]-0]", "ab0-]", }, { 1, 1, "[]^a-z]", "string", }, { 0, 0, "GA120(2)", NULL, }, { 4, 4, "[^]cd]", "cd]ef", }, { 0, 0, "[^]]*", "]]]]]]]]X", }, { 0, 0, "[^]]*", "]]]]]]]]", }, { 9, 9, "[^]]\\{1,\\}", "]]]]]]]]X", }, { -1, -1, "[^]]\\{1,\\}", "]]]]]]]]", }, { 0, 0, "GA120(3)", NULL, }, { 3, 3, "[c[.].]d]", "ab]cd", }, { 2, 8, "[a-z]*[[.].]][A-Z]*", "Abcd]DEFg", }, { 0, 0, "GA121", NULL, }, { 2, 2, "[[.a.]b]", "Abc", }, { 1, 1, "[[.a.]b]", "aBc", }, { -1, -1, "[[.a.]b]", "ABc", }, { 3, 3, "[^[.a.]b]", "abc", }, { 3, 3, "[][.-.]-0]", "ab0-]", }, { 3, 3, "[A-[.].]c]", "ab]!", }, { 0, 0, "GA122", NULL, }, { -2, -2, "[[.ch.]]", "abc", }, { -2, -2, "[[.ab.][.CD.][.EF.]]", "yZabCDEFQ9", }, { 0, 0, "GA125", NULL, }, { 2, 2, "[[=a=]b]", "Abc", }, { 1, 1, "[[=a=]b]", "aBc", }, { -1, -1, "[[=a=]b]", "ABc", }, { 3, 3, "[^[=a=]b]", "abc", }, { 0, 0, "GA126", NULL, }, { 0, 0, NULL, "the expected result for [[:alnum:]]* is 2-7 which is wrong" }, { 0, 0, "[[:alnum:]]*", " aB28gH", }, { 2, 7, "[[:alnum:]][[:alnum:]]*", " aB28gH", }, { 0, 0, NULL, "the expected result for [^[:alnum:]]* is 2-5 which is wrong" }, { 0, 0, "[^[:alnum:]]*", "2 ,a", }, { 2, 5, "[^[:alnum:]][^[:alnum:]]*", "2 ,a", }, { 0, 0, NULL, "the expected result for [[:alpha:]]* is 2-5 which is wrong" }, { 0, 0, "[[:alpha:]]*", " aBgH2", }, { 2, 5, "[[:alpha:]][[:alpha:]]*", " aBgH2", }, { 1, 6, "[^[:alpha:]]*", "2 8,a", }, { 1, 2, "[[:blank:]]*", " \r", }, { 1, 8, "[^[:blank:]]*", "aB28gH, ", }, { 1, 2, "[[:cntrl:]]*", "  ", }, { 1, 8, "[^[:cntrl:]]*", "aB2 8gh,", }, { 0, 0, NULL, "the expected result for [[:digit:]]* is 2-3 which is wrong" }, { 0, 0, "[[:digit:]]*", "a28", }, { 2, 3, "[[:digit:]][[:digit:]]*", "a28", }, { 1, 8, "[^[:digit:]]*", "aB gH,", }, { 1, 7, "[[:graph:]]*", "aB28gH, ", }, { 1, 3, "[^[:graph:]]*", " ,", }, { 1, 2, "[[:lower:]]*", "agB", }, { 1, 8, "[^[:lower:]]*", "B2 8H,a", }, { 1, 8, "[[:print:]]*", "aB2 8gH, ", }, { 1, 2, "[^[:print:]]*", "  ", }, { 0, 0, NULL, "the expected result for [[:punct:]]* is 2-2 which is wrong" }, { 0, 0, "[[:punct:]]*", "a,2", }, { 2, 3, "[[:punct:]][[:punct:]]*", "a,,2", }, { 1, 9, "[^[:punct:]]*", "aB2 8gH", }, { 1, 3, "[[:space:]]*", " \r", }, { 0, 0, NULL, "the expected result for [^[:space:]]* is 2-9 which is wrong" }, { 0, 0, "[^[:space:]]*", " aB28gH, ", }, { 2, 9, "[^[:space:]][^[:space:]]*", " aB28gH, ", }, { 0, 0, NULL, "the expected result for [[:upper:]]* is 2-3 which is wrong" }, { 0, 0, "[[:upper:]]*", "aBH2", }, { 2, 3, "[[:upper:]][[:upper:]]*", "aBH2", }, { 1, 8, "[^[:upper:]]*", "a2 8g,B", }, { 0, 0, NULL, "the expected result for [[:xdigit:]]* is 2-5 which is wrong" }, { 0, 0, "[[:xdigit:]]*", "gaB28h", }, { 2, 5, "[[:xdigit:]][[:xdigit:]]*", "gaB28h", }, { 0, 0, NULL, "the expected result for [^[:xdigit:]]* is 2-7 which is wrong" }, { 2, 7, "[^[:xdigit:]][^[:xdigit:]]*", "a gH,2", }, { 0, 0, "GA127", NULL, }, { -2, -2, "[b-a]", "abc", }, { 1, 1, "[a-c]", "bbccde", }, { 2, 2, "[a-b]", "-bc", }, { 3, 3, "[a-z0-9]", "AB0", }, { 3, 3, "[^a-b]", "abcde", }, { 3, 3, "[^a-bd-e]", "dec", }, { 1, 1, "[]-a]", "a_b", }, { 2, 2, "[+--]", "a,b", }, { 2, 2, "[--/]", "a.b", }, { 2, 2, "[^---]", "-ab", }, { 3, 3, "[][.-.]-0]", "ab0-]", }, { 3, 3, "[A-[.].]c]", "ab]!", }, { 2, 6, "bc[d-w]xy", "abchxyz", }, { 0, 0, "GA129", NULL, }, { 1, 1, "[a-cd-f]", "dbccde", }, { -1, -1, "[a-ce-f]", "dBCCdE", }, { 2, 4, "b[n-zA-M]Y", "absY9Z", }, { 2, 4, "b[n-zA-M]Y", "abGY9Z", }, { 0, 0, "GA130", NULL, }, { 3, 3, "[-xy]", "ac-", }, { 2, 4, "c[-xy]D", "ac-D+", }, { 2, 2, "[--/]", "a.b", }, { 2, 4, "c[--/]D", "ac.D+b", }, { 2, 2, "[^-ac]", "abcde-", }, { 1, 3, "a[^-ac]c", "abcde-", }, { 3, 3, "[xy-]", "zc-", }, { 2, 4, "c[xy-]7", "zc-786", }, { 2, 2, "[^ac-]", "abcde-", }, { 2, 4, "a[^ac-]c", "5abcde-", }, { 2, 2, "[+--]", "a,b", }, { 2, 4, "a[+--]B", "Xa,By", }, { 2, 2, "[^---]", "-ab", }, { 4, 6, "X[^---]Y", "X-YXaYXbY", }, { 0, 0, "2.8.3.3 BREs Matching Multiple Characters", NULL, }, { 0, 0, "GA131", NULL, }, { 3, 4, "cd", "abcdeabcde", }, { 1, 2, "ag*b", "abcde", }, { -1, -1, "[a-c][e-f]", "abcdef", }, { 3, 4, "[a-c][e-f]", "acbedf", }, { 4, 8, "abc*XYZ", "890abXYZ#*", }, { 4, 9, "abc*XYZ", "890abcXYZ#*", }, { 4, 15, "abc*XYZ", "890abcccccccXYZ#*", }, { -1, -1, "abc*XYZ", "890abc*XYZ#*", }, { 0, 0, "GA132", NULL, }, { 2, 4, "\\(*bc\\)", "a*bc", }, { 1, 2, "\\(ab\\)", "abcde", }, { 1, 10, "\\(a\\(b\\(c\\(d\\(e\\(f\\(g\\)h\\(i\\(j\\)\\)\\)\\)\\)\\)\\)\\)", "abcdefghijk", }, { 3, 8, "43\\(2\\(6\\)*0\\)AB", "654320ABCD", }, { 3, 9, "43\\(2\\(7\\)*0\\)AB", "6543270ABCD", }, { 3, 12, "43\\(2\\(7\\)*0\\)AB", "6543277770ABCD", }, { 0, 0, "GA133", NULL, }, { 1, 10, "\\(a\\(b\\(c\\(d\\(e\\(f\\(g\\)h\\(i\\(j\\)\\)\\)\\)\\)\\)\\)\\)", "abcdefghijk", }, { -1, -1, "\\(a\\(b\\(c\\(d\\(e\\(f\\(g\\)h\\(i\\(k\\)\\)\\)\\)\\)\\)\\)\\)", "abcdefghijk", }, { 0, 0, "GA134", NULL, }, { 2, 4, "\\(bb*\\)", "abbbc", }, { 2, 2, "\\(bb*\\)", "ababbbc", }, { 1, 6, "a\\(.*b\\)", "ababbbc", }, { 1, 2, "a\\(b*\\)", "ababbbc", }, { 1, 20, "a\\(.*b\\)c", "axcaxbbbcsxbbbbbbbbc", }, { 0, 0, "GA135", NULL, }, { 1, 7, "\\(a\\(b\\(c\\(d\\(e\\)\\)\\)\\)\\)\\4", "abcdededede", }, { 0, 0, NULL, "POSIX does not really specify whether a\\(b\\)*c\\1 matches acb." }, { 0, 0, NULL, "back references are supposed to expand to the last match, but what" }, { 0, 0, NULL, "if there never was a match as in this case?" }, { -1, -1, "a\\(b\\)*c\\1", "acb", }, { 1, 11, "\\(a\\(b\\(c\\(d\\(e\\(f\\(g\\)h\\(i\\(j\\)\\)\\)\\)\\)\\)\\)\\)\\9", "abcdefghijjk", }, { 0, 0, "GA136", NULL, }, { 0, 0, NULL, "These two tests have the same problem as the test in GA135. No match" }, { 0, 0, NULL, "of a subexpression, why should the back reference be usable?" }, { 0, 0, NULL, "1 2 a\\(b\\)*c\\1 acb" }, { 0, 0, NULL, "4 7 a\\(b\\(c\\(d\\(f\\)*\\)\\)\\)\\4¦xYzabcdePQRST" }, { -1, -1, "a\\(b\\)*c\\1", "acb", }, { -1, -1, "a\\(b\\(c\\(d\\(f\\)*\\)\\)\\)\\4", "xYzabcdePQRST", }, { 0, 0, "GA137", NULL, }, { -2, -2, "\\(a\\(b\\)\\)\\3", "foo", }, { -2, -2, "\\(a\\(b\\)\\)\\(a\\(b\\)\\)\\5", "foo", }, { 0, 0, "GA138", NULL, }, { 1, 2, "ag*b", "abcde", }, { 1, 10, "a.*b", "abababvbabc", }, { 2, 5, "b*c", "abbbcdeabbbbbbcde", }, { 2, 5, "bbb*c", "abbbcdeabbbbbbcde", }, { 1, 5, "a\\(b\\)*c\\1", "abbcbbb", }, { -1, -1, "a\\(b\\)*c\\1", "abbdbd", }, { 0, 0, "\\([a-c]*\\)\\1", "abcacdef", }, { 1, 6, "\\([a-c]*\\)\\1", "abcabcabcd", }, { 1, 2, "a^*b", "ab", }, { 1, 5, "a^*b", "a^^^b", }, { 0, 0, "GA139", NULL, }, { 1, 2, "a\\{2\\}", "aaaa", }, { 1, 7, "\\([a-c]*\\)\\{0,\\}", "aabcaab", }, { 1, 2, "\\(a\\)\\1\\{1,2\\}", "aabc", }, { 1, 3, "\\(a\\)\\1\\{1,2\\}", "aaaabc", }, { 0, 0, NULL, "the expression \\(\\(a\\)\\1\\)\\{1,2\\} is ill-formed, using \\2" }, { 1, 4, "\\(\\(a\\)\\2\\)\\{1,2\\}", "aaaabc", }, { 0, 0, "GA140", NULL, }, { 1, 2, "a\\{2\\}", "aaaa", }, { -1, -1, "a\\{2\\}", "abcd", }, { 0, 0, "a\\{0\\}", "aaaa", }, { 1, 64, "a\\{64\\}", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, { 0, 0, "GA141", NULL, }, { 1, 7, "\\([a-c]*\\)\\{0,\\}", "aabcaab", }, { 0, 0, NULL, "the expected result for \\([a-c]*\\)\\{2,\\} is failure which isn't correct" }, { 1, 3, "\\([a-c]*\\)\\{2,\\}", "abcdefg", }, { 1, 3, "\\([a-c]*\\)\\{1,\\}", "abcdefg", }, { -1, -1, "a\\{64,\\}", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, { 0, 0, "GA142", NULL, }, { 1, 3, "a\\{2,3\\}", "aaaa", }, { -1, -1, "a\\{2,3\\}", "abcd", }, { 0, 0, "\\([a-c]*\\)\\{0,0\\}", "foo", }, { 1, 63, "a\\{1,63\\}", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, { 0, 0, "2.8.3.4 BRE Precedence", NULL, }, { 0, 0, "GA143", NULL, }, { 0, 0, NULL, "There are numerous bugs in the original version." }, { 2, 19, "\\^\\[[[.].]]\\\\(\\\\1\\\\)\\*\\\\{1,2\\\\}\\$", "a^[]\\(\\1\\)*\\{1,2\\}$b", }, { 1, 6, "[[=*=]][[=\\=]][[=]=]][[===]][[...]][[:punct:]]", "*\\]=.;", }, { 1, 6, "[$\\(*\\)^]*", "$\\()*^", }, { 1, 1, "[\\1]", "1", }, { 1, 1, "[\\{1,2\\}]", "{", }, { 0, 0, NULL, "the expected result for \\(*\\)*\\1* is 2-2 which isn't correct" }, { 0, 0, "\\(*\\)*\\1*", "a*b*11", }, { 2, 3, "\\(*\\)*\\1*b", "a*b*11", }, { 0, 0, NULL, "the expected result for \\(a\\(b\\{1,2\\}\\)\\{1,2\\}\\) is 1-5 which isn't correct" }, { 1, 3, "\\(a\\(b\\{1,2\\}\\)\\{1,2\\}\\)", "abbab", }, { 1, 5, "\\(a\\(b\\{1,2\\}\\)\\)\\{1,2\\}", "abbab", }, { 1, 1, "^\\(^\\(^a$\\)$\\)$", "a", }, { 1, 2, "\\(a\\)\\1$", "aa", }, { 1, 3, "ab*", "abb", }, { 1, 4, "ab\\{2,4\\}", "abbbc", }, { 0, 0, "2.8.3.5 BRE Expression Anchoring", NULL, }, { 0, 0, "GA144", NULL, }, { 1, 1, "^a", "abc", }, { -1, -1, "^b", "abc", }, { -1, -1, "^[a-zA-Z]", "99Nine", }, { 1, 4, "^[a-zA-Z]*", "Nine99", }, { 0, 0, "GA145(1)", NULL, }, { 1, 2, "\\(^a\\)\\1", "aabc", }, { -1, -1, "\\(^a\\)\\1", "^a^abc", }, { 1, 2, "\\(^^a\\)", "^a", }, { 1, 1, "\\(^^\\)", "^^", }, { 1, 3, "\\(^abc\\)", "abcdef", }, { -1, -1, "\\(^def\\)", "abcdef", }, { 0, 0, "GA146", NULL, }, { 3, 3, "a$", "cba", }, { -1, -1, "a$", "abc", }, { 5, 7, "[a-z]*$", "99ZZxyz", }, { 0, 0, NULL, "the expected result for [a-z]*$ is failure which isn't correct" }, { 10, 9, "[a-z]*$", "99ZZxyz99", }, { 3, 3, "$$", "ab$", }, { -1, -1, "$$", "$ab", }, { 3, 3, "\\$$", "ab$", }, { 0, 0, "GA147(1)", NULL, }, { -1, -1, "\\(a$\\)\\1", "bcaa", }, { -1, -1, "\\(a$\\)\\1", "ba$", }, { -1, -1, "\\(ab$\\)", "ab$", }, { 1, 2, "\\(ab$\\)", "ab", }, { 4, 6, "\\(def$\\)", "abcdef", }, { -1, -1, "\\(abc$\\)", "abcdef", }, { 0, 0, "GA148", NULL, }, { 0, 0, "^$", "", }, { 1, 3, "^abc$", "abc", }, { -1, -1, "^xyz$", "^xyz^", }, { -1, -1, "^234$", "^234$", }, { 1, 9, "^[a-zA-Z0-9]*$", "2aA3bB9zZ", }, { -1, -1, "^[a-z0-9]*$", "2aA3b#B9zZ", }, kbuild-3686/src/oldsed/testsuite/bug-regex10.c0000664000175000017500000000334015053010105021166 0ustar locutuslocutus/* Test for re_match with non-zero start. Copyright (C) 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2002. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include int main (void) { struct re_pattern_buffer regex; struct re_registers regs; const char *s; int match; int result = 0; regs.num_regs = 1; memset (®ex, '\0', sizeof (regex)); s = re_compile_pattern ("[abc]*d", 7, ®ex); if (s != NULL) { puts ("re_compile_pattern return non-NULL value"); result = 1; } else { match = re_match (®ex, "foacabdxy", 9, 2, ®s); if (match != 5) { printf ("re_match returned %d, expected 5\n", match); result = 1; } else if (regs.start[0] != 2 || regs.end[0] != 7) { printf ("re_match returned %d..%d, expected 2..7\n", regs.start[0], regs.end[0]); result = 1; } puts (" -> OK"); } return result; } kbuild-3686/src/oldsed/testsuite/numsub2.sed0000664000175000017500000000001115053010105021054 0ustar locutuslocutuss/a*/b/2 kbuild-3686/src/oldsed/testsuite/recall2.inp0000664000175000017500000000002115053010105021021 0ustar locutuslocutusababb||abbbabbbb kbuild-3686/src/oldsed/testsuite/runptests.c0000664000175000017500000000563015053010105021213 0ustar locutuslocutus/* POSIX regex testsuite from IEEE 2003.2. Copyright (C) 1998, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1998. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include /* Data structure to describe the tests. */ struct test { int start; int end; const char *reg; const char *str; int options; } tests[] = { #include "ptestcases.h" }; int main (int argc, char *argv[]) { size_t cnt; int errors = 0; for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt) if (tests[cnt].str == NULL) { printf ("\n%s\n%.*s\n", tests[cnt].reg, (int) strlen (tests[cnt].reg), "-----------------------------------------------------"); } else if (tests[cnt].reg == NULL) printf ("!!! %s\n", tests[cnt].str); else { regex_t re; regmatch_t match[20]; int err; printf ("regexp: \"%s\", string: \"%s\" -> ", tests[cnt].reg, tests[cnt].str); /* Compile the expression. */ err = regcomp (&re, tests[cnt].reg, tests[cnt].options); if (err != 0) { if (tests[cnt].start == -2) puts ("compiling failed, OK"); else { char buf[100]; regerror (err, &re, buf, sizeof (buf)); printf ("FAIL: %s\n", buf); ++errors; } continue; } else if (tests[cnt].start == -2) { puts ("compiling suceeds, FAIL"); errors++; continue; } /* Run the actual test. */ err = regexec (&re, tests[cnt].str, 20, match, 0); if (err != 0) { if (tests[cnt].start == -1) puts ("no match, OK"); else { puts ("no match, FAIL"); ++errors; } } else { if (match[0].rm_so == 0 && tests[cnt].start == 0 && match[0].rm_eo == 0 && tests[cnt].end == 0) puts ("match, OK"); else if (match[0].rm_so + 1 == tests[cnt].start && match[0].rm_eo == tests[cnt].end) puts ("match, OK"); else { printf ("wrong match (%d to %d): FAIL\n", match[0].rm_so, match[0].rm_eo); ++errors; } } /* Free all resources. */ regfree (&re); } printf ("\n%Zu tests, %d errors\n", cnt, errors); return errors != 0; } kbuild-3686/src/oldsed/testsuite/numsub4.good0000664000175000017500000000000015053010105021231 0ustar locutuslocutuskbuild-3686/src/oldsed/testsuite/bug-regex11.c0000664000175000017500000001274115053010105021174 0ustar locutuslocutus/* Regular expression tests. Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2002. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #ifdef HAVE_MCHECK_H #include #endif #include #include #include /* Tests supposed to match. */ struct { const char *pattern; const char *string; int flags, nmatch; regmatch_t rm[5]; } tests[] = { /* Test for newline handling in regex. */ { "[^~]*~", "\nx~y", 0, 2, { { 0, 3 }, { -1, -1 } } }, /* Other tests. */ { "a(.*)b", "a b", REG_EXTENDED, 2, { { 0, 3 }, { 1, 2 } } }, { ".*|\\([KIO]\\)\\([^|]*\\).*|?[KIO]", "10~.~|P|K0|I10|O16|?KSb", 0, 3, { { 0, 21 }, { 15, 16 }, { 16, 18 } } }, { ".*|\\([KIO]\\)\\([^|]*\\).*|?\\1", "10~.~|P|K0|I10|O16|?KSb", 0, 3, { { 0, 21 }, { 8, 9 }, { 9, 10 } } }, { "^\\(a*\\)\\1\\{9\\}\\(a\\{0,9\\}\\)\\([0-9]*;.*[^a]\\2\\([0-9]\\)\\)", "a1;;0a1aa2aaa3aaaa4aaaaa5aaaaaa6aaaaaaa7aaaaaaaa8aaaaaaaaa9aa2aa1a0", 0, 5, { { 0, 67 }, { 0, 0 }, { 0, 1 }, { 1, 67 }, { 66, 67 } } }, /* Test for BRE expression anchoring. POSIX says just that this may match; in glibc regex it always matched, so avoid changing it. */ { "\\(^\\|foo\\)bar", "bar", 0, 2, { { 0, 3 }, { -1, -1 } } }, { "\\(foo\\|^\\)bar", "bar", 0, 2, { { 0, 3 }, { -1, -1 } } }, /* In ERE this must be treated as an anchor. */ { "(^|foo)bar", "bar", REG_EXTENDED, 2, { { 0, 3 }, { -1, -1 } } }, { "(foo|^)bar", "bar", REG_EXTENDED, 2, { { 0, 3 }, { -1, -1 } } }, /* Here ^ cannot be treated as an anchor according to POSIX. */ { "(^|foo)bar", "(^|foo)bar", 0, 2, { { 0, 10 }, { -1, -1 } } }, { "(foo|^)bar", "(foo|^)bar", 0, 2, { { 0, 10 }, { -1, -1 } } }, /* More tests on backreferences. */ { "()\\1", "x", REG_EXTENDED, 2, { { 0, 0 }, { 0, 0 } } }, { "()x\\1", "x", REG_EXTENDED, 2, { { 0, 1 }, { 0, 0 } } }, { "()\\1*\\1*", "", REG_EXTENDED, 2, { { 0, 0 }, { 0, 0 } } }, { "([0-9]).*\\1(a*)", "7;7a6", REG_EXTENDED, 3, { { 0, 4 }, { 0, 1 }, { 3, 4 } } }, { "([0-9]).*\\1(a*)", "7;7a", REG_EXTENDED, 3, { { 0, 4 }, { 0, 1 }, { 3, 4 } } }, { "(b)()c\\1", "bcb", REG_EXTENDED, 3, { { 0, 3 }, { 0, 1 }, { 1, 1 } } }, { "()(b)c\\2", "bcb", REG_EXTENDED, 3, { { 0, 3 }, { 0, 0 }, { 0, 1 } } }, { "a(b)()c\\1", "abcb", REG_EXTENDED, 3, { { 0, 4 }, { 1, 2 }, { 2, 2 } } }, { "a()(b)c\\2", "abcb", REG_EXTENDED, 3, { { 0, 4 }, { 1, 1 }, { 1, 2 } } }, { "()(b)\\1c\\2", "bcb", REG_EXTENDED, 3, { { 0, 3 }, { 0, 0 }, { 0, 1 } } }, { "(b())\\2\\1", "bbbb", REG_EXTENDED, 3, { { 0, 2 }, { 0, 1 }, { 1, 1 } } }, { "a()(b)\\1c\\2", "abcb", REG_EXTENDED, 3, { { 0, 4 }, { 1, 1 }, { 1, 2 } } }, { "a()d(b)\\1c\\2", "adbcb", REG_EXTENDED, 3, { { 0, 5 }, { 1, 1 }, { 2, 3 } } }, { "a(b())\\2\\1", "abbbb", REG_EXTENDED, 3, { { 0, 3 }, { 1, 2 }, { 2, 2 } } }, { "(bb())\\2\\1", "bbbb", REG_EXTENDED, 3, { { 0, 4 }, { 0, 2 }, { 2, 2 } } }, { "^(.?)(.?)(.?)(.?)(.?).?\\5\\4\\3\\2\\1$", "level", REG_NOSUB | REG_EXTENDED, 0, { { -1, -1 } } }, { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$|^.?$", "level", REG_NOSUB | REG_EXTENDED, 0, { { -1, -1 } } }, { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$|^.?$", "abcdedcba", REG_EXTENDED, 1, { { 0, 9 } } }, #if 0 /* XXX Not used since they fail so far. */ { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$|^.?$", "ababababa", REG_EXTENDED, 1, { { 0, 9 } } }, { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$", "level", REG_NOSUB | REG_EXTENDED, 0, { { -1, -1 } } }, { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$", "ababababa", REG_EXTENDED, 1, { { 0, 9 } } }, #endif }; int main (void) { regex_t re; regmatch_t rm[5]; size_t i; int n, ret = 0; #ifdef HAVE_MCHECK_H mtrace (); #endif for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i) { n = regcomp (&re, tests[i].pattern, tests[i].flags); if (n != 0) { char buf[500]; regerror (n, &re, buf, sizeof (buf)); printf ("%s: regcomp %lu failed: %s\n", tests[i].pattern, i, buf); ret = 1; continue; } if (regexec (&re, tests[i].string, tests[i].nmatch, rm, 0)) { printf ("%s: regexec %lu failed\n", tests[i].pattern, i); ret = 1; regfree (&re); continue; } for (n = 0; n < tests[i].nmatch; ++n) if (rm[n].rm_so != tests[i].rm[n].rm_so || rm[n].rm_eo != tests[i].rm[n].rm_eo) { if (tests[i].rm[n].rm_so == -1 && tests[i].rm[n].rm_eo == -1) break; printf ("%s: regexec %lu match failure rm[%d] %d..%d\n", tests[i].pattern, i, n, rm[n].rm_so, rm[n].rm_eo); ret = 1; break; } regfree (&re); } return ret; } kbuild-3686/src/oldsed/testsuite/factor.sed0000664000175000017500000000242615053010105020753 0ustar locutuslocutus#! /bin/sed -nf s/.*/&;9aaaaaaaaa8aaaaaaaa7aaaaaaa6aaaaaa5aaaaa4aaaa3aaa2aa1a0/ :encode s/\(a*\)\([0-9]\)\([0-9]*;.*\2\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4\3/ tencode s/;.*// # Compute a few common factors for speed. Clear the subst flag t7a # These are placed here to make the flow harder to understand :-) :2 a\ 2 b2a :3 a\ 3 b3a :5 a\ 5 b5a :7 a\ 7 :7a s/^\(aa*\)\1\{6\}$/\1/ t7 :5a s/^\(aa*\)\1\{4\}$/\1/ t5 :3a s/^\(aa*\)\1\1$/\1/ t3 :2a s/^\(aa*\)\1$/\1/ t2 /^a$/b # The quotient of dividing by 11 is a limit to the remaining prime factors s/^\(aa*\)\1\{10\}/\1=&/ # Pattern space looks like CANDIDATE\nNUMBER. When a candidate is valid, # the number is divided and the candidate is tried again :factor /^\(a\{7,\}\)=\1\1*$/! { # Decrement CANDIDATE, and search again if it is still >1 s/^a// /^aa/b factor # Print the last remaining factor: since it is stored in the NUMBER # rather than in the CANDIDATE, swap 'em: now NUMBER=1 s/\(.*\)=\(.*\)/\2=\1/ } # We have a prime factor in CANDIDATE! Print it h s/=.*/;;0a1aa2aaa3aaaa4aaaaa5aaaaaa6aaaaaaa7aaaaaaaa8aaaaaaaaa9/ :decode s/^\(a*\)\1\{9\}\(a\{0,9\}\)\([0-9]*;.*[^a]\2\([0-9]\)\)/\1\4\3/ /^a/tdecode s/;.*//p g :divide s/^\(a*\)\(=b*\)\1/\1\2b/ tdivide y/b/a/ # If NUMBER = 1, we don't have any more factors /aa$/bfactor kbuild-3686/src/oldsed/testsuite/xbxcx3.sed0000664000175000017500000000001115053010105020700 0ustar locutuslocutuss/a*/x/3 kbuild-3686/src/oldsed/testsuite/xbxcx3.good0000664000175000017500000000004115053010105021060 0ustar locutuslocutus b bcx bacx baacx baaacx baaaacx kbuild-3686/src/oldsed/testsuite/dollar.sed0000664000175000017500000000001515053010105020742 0ustar locutuslocutus$s/^/space / kbuild-3686/src/oldsed/testsuite/classes.sed0000664000175000017500000000021315053010105021122 0ustar locutuslocutus# inspired by an autoconf generated configure script. s/^\([/[:lower:]A-Z0-9]*_cv_[[:lower:][:upper:]/[:digit:]]*\)=\(.*\)/: \${\1='\2'}/p kbuild-3686/src/oldsed/testsuite/bug-regex12.c0000664000175000017500000000401115053010105021164 0ustar locutuslocutus/* Regular expression tests. Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2002. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #ifdef HAVE_MCHECK_H #include #endif #include #include #include /* Tests supposed to not match. */ struct { const char *pattern; const char *string; int flags, nmatch; } tests[] = { { "^<\\([^~]*\\)\\([^~]\\)[^~]*~\\1\\(.\\).*|=.*\\3.*\\2", "<,.8~2,~so-|=-~.0,123456789<><", REG_NOSUB, 0 }, /* In ERE, all carets must be treated as anchors. */ { "a^b", "a^b", REG_EXTENDED, 0 } }; int main (void) { regex_t re; regmatch_t rm[4]; size_t i; int n, ret = 0; #ifdef HAVE_MCHECK_H mtrace (); #endif for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i) { n = regcomp (&re, tests[i].pattern, tests[i].flags); if (n != 0) { char buf[500]; regerror (n, &re, buf, sizeof (buf)); printf ("regcomp %lu failed: %s\n", i, buf); ret = 1; continue; } if (! regexec (&re, tests[i].string, tests[i].nmatch, tests[i].nmatch ? rm : NULL, 0)) { printf ("regexec %lu incorrectly matched\n", i); ret = 1; } regfree (&re); } return ret; } kbuild-3686/src/oldsed/testsuite/space.sed0000664000175000017500000000002415053010105020560 0ustar locutuslocutuss/_\S/XX/g;s/\s/_/g kbuild-3686/src/oldsed/testsuite/BOOST.tests0000664000175000017500000004552115053010105020755 0ustar locutuslocutus; ; ; this file contains a script of tests to run through regress.exe ; ; comments start with a semicolon and proceed to the end of the line ; ; changes to regular expression compile flags start with a "-" as the first ; non-whitespace character and consist of a list of the printable names ; of the flags, for example "match_default" ; ; Other lines contain a test to perform using the current flag status ; the first token contains the expression to compile, the second the string ; to match it against. If the second string is "!" then the expression should ; not compile, that is the first string is an invalid regular expression. ; This is then followed by a list of integers that specify what should match, ; each pair represents the starting and ending positions of a subexpression ; starting with the zeroth subexpression (the whole match). ; A value of -1 indicates that the subexpression should not take part in the ; match at all, if the first value is -1 then no part of the expression should ; match the string. ; ; Tests taken from BOOST testsuite and adapted to glibc regex. ; ; Boost Software License - Version 1.0 - August 17th, 2003 ; ; Permission is hereby granted, free of charge, to any person or organization ; obtaining a copy of the software and accompanying documentation covered by ; this license (the "Software") to use, reproduce, display, distribute, ; execute, and transmit the Software, and to prepare derivative works of the ; Software, and to permit third-parties to whom the Software is furnished to ; do so, all subject to the following: ; ; The copyright notices in the Software and this entire statement, including ; the above license grant, this restriction and the following disclaimer, ; must be included in all copies of the Software, in whole or in part, and ; all derivative works of the Software, unless such copies or derivative ; works are solely in the form of machine-executable object code generated by ; a source language processor. ; ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ; FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT ; SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE ; FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ; ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ; DEALINGS IN THE SOFTWARE. ; - match_default normal REG_EXTENDED ; ; try some really simple literals: a a 0 1 Z Z 0 1 Z aaa -1 -1 Z xxxxZZxxx 4 5 ; and some simple brackets: (a) zzzaazz 3 4 3 4 () zzz 0 0 0 0 () "" 0 0 0 0 ( ! ) ) 0 1 (aa ! aa) baa)b 1 4 a b -1 -1 \(\) () 0 2 \(a\) (a) 0 3 \() () 0 2 (\) ! p(a)rameter ABCparameterXYZ 3 12 4 5 [pq](a)rameter ABCparameterXYZ 3 12 4 5 ; now try escaped brackets: - match_default bk_parens REG_BASIC \(a\) zzzaazz 3 4 3 4 \(\) zzz 0 0 0 0 \(\) "" 0 0 0 0 \( ! \) ! \(aa ! aa\) ! () () 0 2 (a) (a) 0 3 (\) ! \() ! ; now move on to "." wildcards - match_default normal REG_EXTENDED REG_STARTEND . a 0 1 . \n 0 1 . \r 0 1 . \0 0 1 ; ; now move on to the repetion ops, ; starting with operator * - match_default normal REG_EXTENDED a* b 0 0 ab* a 0 1 ab* ab 0 2 ab* sssabbbbbbsss 3 10 ab*c* a 0 1 ab*c* abbb 0 4 ab*c* accc 0 4 ab*c* abbcc 0 5 *a ! \<* ! \>* ! \n* \n\n 0 2 \** ** 0 2 \* * 0 1 ; now try operator + ab+ a -1 -1 ab+ ab 0 2 ab+ sssabbbbbbsss 3 10 ab+c+ a -1 -1 ab+c+ abbb -1 -1 ab+c+ accc -1 -1 ab+c+ abbcc 0 5 +a ! \<+ ! \>+ ! \n+ \n\n 0 2 \+ + 0 1 \+ ++ 0 1 \++ ++ 0 2 ; now try operator ? - match_default normal REG_EXTENDED a? b 0 0 ab? a 0 1 ab? ab 0 2 ab? sssabbbbbbsss 3 5 ab?c? a 0 1 ab?c? abbb 0 2 ab?c? accc 0 2 ab?c? abcc 0 3 ?a ! \? ! \n? \n\n 0 1 \? ? 0 1 \? ?? 0 1 \?? ?? 0 1 ; now try operator {} - match_default normal REG_EXTENDED a{2} a -1 -1 a{2} aa 0 2 a{2} aaa 0 2 a{2,} a -1 -1 a{2,} aa 0 2 a{2,} aaaaa 0 5 a{2,4} a -1 -1 a{2,4} aa 0 2 a{2,4} aaa 0 3 a{2,4} aaaa 0 4 a{2,4} aaaaa 0 4 a{} ! a{2 ! a} a} 0 2 \{\} {} 0 2 - match_default normal REG_BASIC a\{2\} a -1 -1 a\{2\} aa 0 2 a\{2\} aaa 0 2 a\{2,\} a -1 -1 a\{2,\} aa 0 2 a\{2,\} aaaaa 0 5 a\{2,4\} a -1 -1 a\{2,4\} aa 0 2 a\{2,4\} aaa 0 3 a\{2,4\} aaaa 0 4 a\{2,4\} aaaaa 0 4 {} {} 0 2 ; now test the alternation operator | - match_default normal REG_EXTENDED a|b a 0 1 a|b b 0 1 a(b|c) ab 0 2 1 2 a(b|c) ac 0 2 1 2 a(b|c) ad -1 -1 -1 -1 a\| a| 0 2 ; now test the set operator [] - match_default normal REG_EXTENDED ; try some literals first [abc] a 0 1 [abc] b 0 1 [abc] c 0 1 [abc] d -1 -1 [^bcd] a 0 1 [^bcd] b -1 -1 [^bcd] d -1 -1 [^bcd] e 0 1 a[b]c abc 0 3 a[ab]c abc 0 3 a[^ab]c adc 0 3 a[]b]c a]c 0 3 a[[b]c a[c 0 3 a[-b]c a-c 0 3 a[^]b]c adc 0 3 a[^-b]c adc 0 3 a[b-]c a-c 0 3 a[b ! a[] ! ; then some ranges [b-e] a -1 -1 [b-e] b 0 1 [b-e] e 0 1 [b-e] f -1 -1 [^b-e] a 0 1 [^b-e] b -1 -1 [^b-e] e -1 -1 [^b-e] f 0 1 a[1-3]c a2c 0 3 a[3-1]c ! a[1-3-5]c ! a[1- ! ; and some classes a[[:alpha:]]c abc 0 3 a[[:unknown:]]c ! a[[: ! a[[:alpha ! a[[:alpha:] ! a[[:alpha,:] ! a[[:]:]]b ! a[[:-:]]b ! a[[:alph:]] ! a[[:alphabet:]] ! [[:alnum:]]+ -%@a0X_- 3 6 [[:alpha:]]+ -%@aX_0- 3 5 [[:blank:]]+ "a \tb" 1 4 [[:cntrl:]]+ a\n\tb 1 3 [[:digit:]]+ a019b 1 4 [[:graph:]]+ " a%b " 1 4 [[:lower:]]+ AabC 1 3 ; This test fails with STLPort, disable for now as this is a corner case anyway... ;[[:print:]]+ "\na b\n" 1 4 [[:punct:]]+ " %-&\t" 1 4 [[:space:]]+ "a \n\t\rb" 1 5 [[:upper:]]+ aBCd 1 3 [[:xdigit:]]+ p0f3Cx 1 5 ; now test flag settings: - escape_in_lists REG_NO_POSIX_TEST [\n] \n 0 1 - REG_NO_POSIX_TEST ; line anchors - match_default normal REG_EXTENDED ^ab ab 0 2 ^ab xxabxx -1 -1 ab$ ab 0 2 ab$ abxx -1 -1 - match_default match_not_bol match_not_eol normal REG_EXTENDED REG_NOTBOL REG_NOTEOL ^ab ab -1 -1 ^ab xxabxx -1 -1 ab$ ab -1 -1 ab$ abxx -1 -1 ; back references - match_default normal REG_PERL a(b)\2c ! a(b\1)c ! a(b*)c\1d abbcbbd 0 7 1 3 a(b*)c\1d abbcbd -1 -1 a(b*)c\1d abbcbbbd -1 -1 ^(.)\1 abc -1 -1 a([bc])\1d abcdabbd 4 8 5 6 ; strictly speaking this is at best ambiguous, at worst wrong, this is what most ; re implimentations will match though. a(([bc])\2)*d abbccd 0 6 3 5 3 4 a(([bc])\2)*d abbcbd -1 -1 a((b)*\2)*d abbbd 0 5 1 4 2 3 ; perl only: (ab*)[ab]*\1 ababaaa 0 7 0 1 (a)\1bcd aabcd 0 5 0 1 (a)\1bc*d aabcd 0 5 0 1 (a)\1bc*d aabd 0 4 0 1 (a)\1bc*d aabcccd 0 7 0 1 (a)\1bc*[ce]d aabcccd 0 7 0 1 ^(a)\1b(c)*cd$ aabcccd 0 7 0 1 4 5 ; posix only: - match_default extended REG_EXTENDED (ab*)[ab]*\1 ababaaa 0 7 0 1 ; ; word operators: \w a 0 1 \w z 0 1 \w A 0 1 \w Z 0 1 \w _ 0 1 \w } -1 -1 \w ` -1 -1 \w [ -1 -1 \w @ -1 -1 ; non-word: \W a -1 -1 \W z -1 -1 \W A -1 -1 \W Z -1 -1 \W _ -1 -1 \W } 0 1 \W ` 0 1 \W [ 0 1 \W @ 0 1 ; word start: \ abc 0 3 abc\> abcd -1 -1 abc\> abc\n 0 3 abc\> abc:: 0 3 ; word boundary: \babcd " abcd" 2 6 \bab cab -1 -1 \bab "\nab" 1 3 \btag ::tag 2 5 abc\b abc 0 3 abc\b abcd -1 -1 abc\b abc\n 0 3 abc\b abc:: 0 3 ; within word: \B ab 1 1 a\Bb ab 0 2 a\B ab 0 1 a\B a -1 -1 a\B "a " -1 -1 ; ; buffer operators: \`abc abc 0 3 \`abc \nabc -1 -1 \`abc " abc" -1 -1 abc\' abc 0 3 abc\' abc\n -1 -1 abc\' "abc " -1 -1 ; ; now follows various complex expressions designed to try and bust the matcher: a(((b)))c abc 0 3 1 2 1 2 1 2 a(b|(c))d abd 0 3 1 2 -1 -1 a(b|(c))d acd 0 3 1 2 1 2 a(b*|c)d abbd 0 4 1 3 ; just gotta have one DFA-buster, of course a[ab]{20} aaaaabaaaabaaaabaaaab 0 21 ; and an inline expansion in case somebody gets tricky a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab] aaaaabaaaabaaaabaaaab 0 21 ; and in case somebody just slips in an NFA... a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night) aaaaabaaaabaaaabaaaabweeknights 0 31 21 24 24 31 ; one really big one 1234567890123456789012345678901234567890123456789012345678901234567890 a1234567890123456789012345678901234567890123456789012345678901234567890b 1 71 ; fish for problems as brackets go past 8 [ab][cd][ef][gh][ij][kl][mn] xacegikmoq 1 8 [ab][cd][ef][gh][ij][kl][mn][op] xacegikmoq 1 9 [ab][cd][ef][gh][ij][kl][mn][op][qr] xacegikmoqy 1 10 [ab][cd][ef][gh][ij][kl][mn][op][q] xacegikmoqy 1 10 ; and as parenthesis go past 9: (a)(b)(c)(d)(e)(f)(g)(h) zabcdefghi 1 9 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 (a)(b)(c)(d)(e)(f)(g)(h)(i) zabcdefghij 1 10 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 (a)(b)(c)(d)(e)(f)(g)(h)(i)(j) zabcdefghijk 1 11 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 (a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k) zabcdefghijkl 1 12 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 (a)d|(b)c abc 1 3 -1 -1 1 2 _+((www)|(ftp)|(mailto)):_* "_wwwnocolon _mailto:" 12 20 13 19 -1 -1 -1 -1 13 19 ; subtleties of matching ;a(b)?c\1d acd 0 3 -1 -1 ; POSIX is about the following test: a(b)?c\1d acd -1 -1 -1 -1 a(b?c)+d accd 0 4 2 3 (wee|week)(knights|night) weeknights 0 10 0 3 3 10 .* abc 0 3 a(b|(c))d abd 0 3 1 2 -1 -1 a(b|(c))d acd 0 3 1 2 1 2 a(b*|c|e)d abbd 0 4 1 3 a(b*|c|e)d acd 0 3 1 2 a(b*|c|e)d ad 0 2 1 1 a(b?)c abc 0 3 1 2 a(b?)c ac 0 2 1 1 a(b+)c abc 0 3 1 2 a(b+)c abbbc 0 5 1 4 a(b*)c ac 0 2 1 1 (a|ab)(bc([de]+)f|cde) abcdef 0 6 0 1 1 6 3 5 a([bc]?)c abc 0 3 1 2 a([bc]?)c ac 0 2 1 1 a([bc]+)c abc 0 3 1 2 a([bc]+)c abcc 0 4 1 3 a([bc]+)bc abcbc 0 5 1 3 a(bb+|b)b abb 0 3 1 2 a(bbb+|bb+|b)b abb 0 3 1 2 a(bbb+|bb+|b)b abbb 0 4 1 3 a(bbb+|bb+|b)bb abbb 0 4 1 2 (.*).* abcdef 0 6 0 6 (a*)* bc 0 0 0 0 xyx*xz xyxxxxyxxxz 5 11 ; do we get the right subexpression when it is used more than once? a(b|c)*d ad 0 2 -1 -1 a(b|c)*d abcd 0 4 2 3 a(b|c)+d abd 0 3 1 2 a(b|c)+d abcd 0 4 2 3 a(b|c?)+d ad 0 2 1 1 a(b|c){0,0}d ad 0 2 -1 -1 a(b|c){0,1}d ad 0 2 -1 -1 a(b|c){0,1}d abd 0 3 1 2 a(b|c){0,2}d ad 0 2 -1 -1 a(b|c){0,2}d abcd 0 4 2 3 a(b|c){0,}d ad 0 2 -1 -1 a(b|c){0,}d abcd 0 4 2 3 a(b|c){1,1}d abd 0 3 1 2 a(b|c){1,2}d abd 0 3 1 2 a(b|c){1,2}d abcd 0 4 2 3 a(b|c){1,}d abd 0 3 1 2 a(b|c){1,}d abcd 0 4 2 3 a(b|c){2,2}d acbd 0 4 2 3 a(b|c){2,2}d abcd 0 4 2 3 a(b|c){2,4}d abcd 0 4 2 3 a(b|c){2,4}d abcbd 0 5 3 4 a(b|c){2,4}d abcbcd 0 6 4 5 a(b|c){2,}d abcd 0 4 2 3 a(b|c){2,}d abcbd 0 5 3 4 ; perl only: these conflict with the POSIX test below ;a(b|c?)+d abcd 0 4 3 3 ;a(b+|((c)*))+d abd 0 3 2 2 2 2 -1 -1 ;a(b+|((c)*))+d abcd 0 4 3 3 3 3 2 3 ; posix only: - match_default extended REG_EXTENDED REG_STARTEND a(b|c?)+d abcd 0 4 2 3 a(b|((c)*))+d abcd 0 4 2 3 2 3 2 3 a(b+|((c)*))+d abd 0 3 1 2 -1 -1 -1 -1 a(b+|((c)*))+d abcd 0 4 2 3 2 3 2 3 a(b|((c)*))+d ad 0 2 1 1 1 1 -1 -1 a(b|((c)*))*d abcd 0 4 2 3 2 3 2 3 a(b+|((c)*))*d abd 0 3 1 2 -1 -1 -1 -1 a(b+|((c)*))*d abcd 0 4 2 3 2 3 2 3 a(b|((c)*))*d ad 0 2 1 1 1 1 -1 -1 - match_default normal REG_PERL ; try to match C++ syntax elements: ; line comment: //[^\n]* "++i //here is a line comment\n" 4 28 ; block comment: /\*([^*]|\*+[^*/])*\*+/ "/* here is a block comment */" 0 29 26 27 /\*([^*]|\*+[^*/])*\*+/ "/**/" 0 4 -1 -1 /\*([^*]|\*+[^*/])*\*+/ "/***/" 0 5 -1 -1 /\*([^*]|\*+[^*/])*\*+/ "/****/" 0 6 -1 -1 /\*([^*]|\*+[^*/])*\*+/ "/*****/" 0 7 -1 -1 /\*([^*]|\*+[^*/])*\*+/ "/*****/*/" 0 7 -1 -1 ; preprossor directives: ^[[:blank:]]*#([^\n]*\\[[:space:]]+)*[^\n]* "#define some_symbol" 0 19 -1 -1 ^[[:blank:]]*#([^\n]*\\[[:space:]]+)*[^\n]* "#define some_symbol(x) #x" 0 25 -1 -1 ; perl only: ^[[:blank:]]*#([^\n]*\\[[:space:]]+)*[^\n]* "#define some_symbol(x) \\ \r\n foo();\\\r\n printf(#x);" 0 53 30 42 ; literals: ((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 0xFF 0 4 0 4 0 4 -1 -1 -1 -1 -1 -1 -1 -1 ((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 35 0 2 0 2 -1 -1 0 2 -1 -1 -1 -1 -1 -1 ((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 0xFFu 0 5 0 4 0 4 -1 -1 -1 -1 -1 -1 -1 -1 ((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 0xFFL 0 5 0 4 0 4 -1 -1 4 5 -1 -1 -1 -1 ((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 0xFFFFFFFFFFFFFFFFuint64 0 24 0 18 0 18 -1 -1 19 24 19 24 22 24 ; strings: '([^\\']|\\.)*' '\\x3A' 0 6 4 5 '([^\\']|\\.)*' '\\'' 0 4 1 3 '([^\\']|\\.)*' '\\n' 0 4 1 3 ; finally try some case insensitive matches: - match_default normal REG_EXTENDED REG_ICASE ; upper and lower have no meaning here so they fail, however these ; may compile with other libraries... ;[[:lower:]] ! ;[[:upper:]] ! 0123456789@abcdefghijklmnopqrstuvwxyz\[\\\]\^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ\{\|\} 0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]\^_`abcdefghijklmnopqrstuvwxyz\{\|\} 0 72 ; known and suspected bugs: - match_default normal REG_EXTENDED \( ( 0 1 \) ) 0 1 \$ $ 0 1 \^ ^ 0 1 \. . 0 1 \* * 0 1 \+ + 0 1 \? ? 0 1 \[ [ 0 1 \] ] 0 1 \| | 0 1 \\ \\ 0 1 # # 0 1 \# # 0 1 a- a- 0 2 \- - 0 1 \{ { 0 1 \} } 0 1 0 0 0 1 1 1 0 1 9 9 0 1 b b 0 1 B B 0 1 < < 0 1 > > 0 1 w w 0 1 W W 0 1 ` ` 0 1 ' ' 0 1 \n \n 0 1 , , 0 1 a a 0 1 f f 0 1 n n 0 1 r r 0 1 t t 0 1 v v 0 1 c c 0 1 x x 0 1 : : 0 1 (\.[[:alnum:]]+){2} "w.a.b " 1 5 3 5 - match_default normal REG_EXTENDED REG_ICASE a A 0 1 A a 0 1 [abc]+ abcABC 0 6 [ABC]+ abcABC 0 6 [a-z]+ abcABC 0 6 [A-Z]+ abzANZ 0 6 [a-Z]+ abzABZ 0 6 [A-z]+ abzABZ 0 6 [[:lower:]]+ abyzABYZ 0 8 [[:upper:]]+ abzABZ 0 6 [[:alpha:]]+ abyzABYZ 0 8 [[:alnum:]]+ 09abyzABYZ 0 10 ; word start: \ abc 0 3 abc\> abcd -1 -1 abc\> abc\n 0 3 abc\> abc:: 0 3 ; collating elements and rewritten set code: - match_default normal REG_EXTENDED REG_STARTEND ;[[.zero.]] 0 0 1 ;[[.one.]] 1 0 1 ;[[.two.]] 2 0 1 ;[[.three.]] 3 0 1 [[.a.]] baa 1 2 ;[[.right-curly-bracket.]] } 0 1 ;[[.NUL.]] \0 0 1 [[:<:]z] ! [a[:>:]] ! [[=a=]] a 0 1 ;[[=right-curly-bracket=]] } 0 1 - match_default normal REG_EXTENDED REG_STARTEND REG_ICASE [[.A.]] A 0 1 [[.A.]] a 0 1 [[.A.]-b]+ AaBb 0 4 [A-[.b.]]+ AaBb 0 4 [[.a.]-B]+ AaBb 0 4 [a-[.B.]]+ AaBb 0 4 - match_default normal REG_EXTENDED REG_STARTEND [[.a.]-c]+ abcd 0 3 [a-[.c.]]+ abcd 0 3 [[:alpha:]-a] ! [a-[:alpha:]] ! ; try mutli-character ligatures: ;[[.ae.]] ae 0 2 ;[[.ae.]] aE -1 -1 ;[[.AE.]] AE 0 2 ;[[.Ae.]] Ae 0 2 ;[[.ae.]-b] a -1 -1 ;[[.ae.]-b] b 0 1 ;[[.ae.]-b] ae 0 2 ;[a-[.ae.]] a 0 1 ;[a-[.ae.]] b -1 -1 ;[a-[.ae.]] ae 0 2 - match_default normal REG_EXTENDED REG_STARTEND REG_ICASE ;[[.ae.]] AE 0 2 ;[[.ae.]] Ae 0 2 ;[[.AE.]] Ae 0 2 ;[[.Ae.]] aE 0 2 ;[[.AE.]-B] a -1 -1 ;[[.Ae.]-b] b 0 1 ;[[.Ae.]-b] B 0 1 ;[[.ae.]-b] AE 0 2 - match_default normal REG_EXTENDED REG_STARTEND REG_NO_POSIX_TEST \s+ "ab ab" 2 5 \S+ " abc " 2 5 - match_default normal REG_EXTENDED REG_STARTEND \`abc abc 0 3 \`abc aabc -1 -1 abc\' abc 0 3 abc\' abcd -1 -1 abc\' abc\n\n -1 -1 abc\' abc 0 3 ; extended repeat checking to exercise new algorithms: ab.*xy abxy_ 0 4 ab.*xy ab_xy_ 0 5 ab.*xy abxy 0 4 ab.*xy ab_xy 0 5 ab.* ab 0 2 ab.* ab__ 0 4 ab.{2,5}xy ab__xy_ 0 6 ab.{2,5}xy ab____xy_ 0 8 ab.{2,5}xy ab_____xy_ 0 9 ab.{2,5}xy ab__xy 0 6 ab.{2,5}xy ab_____xy 0 9 ab.{2,5} ab__ 0 4 ab.{2,5} ab_______ 0 7 ab.{2,5}xy ab______xy -1 -1 ab.{2,5}xy ab_xy -1 -1 ab.*?xy abxy_ 0 4 ab.*?xy ab_xy_ 0 5 ab.*?xy abxy 0 4 ab.*?xy ab_xy 0 5 ab.*? ab 0 2 ab.*? ab__ 0 4 ab.{2,5}?xy ab__xy_ 0 6 ab.{2,5}?xy ab____xy_ 0 8 ab.{2,5}?xy ab_____xy_ 0 9 ab.{2,5}?xy ab__xy 0 6 ab.{2,5}?xy ab_____xy 0 9 ab.{2,5}? ab__ 0 4 ab.{2,5}? ab_______ 0 7 ab.{2,5}?xy ab______xy -1 -1 ab.{2,5}xy ab_xy -1 -1 ; again but with slower algorithm variant: - match_default REG_EXTENDED ; now again for single character repeats: ab_*xy abxy_ 0 4 ab_*xy ab_xy_ 0 5 ab_*xy abxy 0 4 ab_*xy ab_xy 0 5 ab_* ab 0 2 ab_* ab__ 0 4 ab_{2,5}xy ab__xy_ 0 6 ab_{2,5}xy ab____xy_ 0 8 ab_{2,5}xy ab_____xy_ 0 9 ab_{2,5}xy ab__xy 0 6 ab_{2,5}xy ab_____xy 0 9 ab_{2,5} ab__ 0 4 ab_{2,5} ab_______ 0 7 ab_{2,5}xy ab______xy -1 -1 ab_{2,5}xy ab_xy -1 -1 ab_*?xy abxy_ 0 4 ab_*?xy ab_xy_ 0 5 ab_*?xy abxy 0 4 ab_*?xy ab_xy 0 5 ab_*? ab 0 2 ab_*? ab__ 0 4 ab_{2,5}?xy ab__xy_ 0 6 ab_{2,5}?xy ab____xy_ 0 8 ab_{2,5}?xy ab_____xy_ 0 9 ab_{2,5}?xy ab__xy 0 6 ab_{2,5}?xy ab_____xy 0 9 ab_{2,5}? ab__ 0 4 ab_{2,5}? ab_______ 0 7 ab_{2,5}?xy ab______xy -1 -1 ab_{2,5}xy ab_xy -1 -1 ; and again for sets: ab[_,;]*xy abxy_ 0 4 ab[_,;]*xy ab_xy_ 0 5 ab[_,;]*xy abxy 0 4 ab[_,;]*xy ab_xy 0 5 ab[_,;]* ab 0 2 ab[_,;]* ab__ 0 4 ab[_,;]{2,5}xy ab__xy_ 0 6 ab[_,;]{2,5}xy ab____xy_ 0 8 ab[_,;]{2,5}xy ab_____xy_ 0 9 ab[_,;]{2,5}xy ab__xy 0 6 ab[_,;]{2,5}xy ab_____xy 0 9 ab[_,;]{2,5} ab__ 0 4 ab[_,;]{2,5} ab_______ 0 7 ab[_,;]{2,5}xy ab______xy -1 -1 ab[_,;]{2,5}xy ab_xy -1 -1 ab[_,;]*?xy abxy_ 0 4 ab[_,;]*?xy ab_xy_ 0 5 ab[_,;]*?xy abxy 0 4 ab[_,;]*?xy ab_xy 0 5 ab[_,;]*? ab 0 2 ab[_,;]*? ab__ 0 4 ab[_,;]{2,5}?xy ab__xy_ 0 6 ab[_,;]{2,5}?xy ab____xy_ 0 8 ab[_,;]{2,5}?xy ab_____xy_ 0 9 ab[_,;]{2,5}?xy ab__xy 0 6 ab[_,;]{2,5}?xy ab_____xy 0 9 ab[_,;]{2,5}? ab__ 0 4 ab[_,;]{2,5}? ab_______ 0 7 ab[_,;]{2,5}?xy ab______xy -1 -1 ab[_,;]{2,5}xy ab_xy -1 -1 ; and again for tricky sets with digraphs: ;ab[_[.ae.]]*xy abxy_ 0 4 ;ab[_[.ae.]]*xy ab_xy_ 0 5 ;ab[_[.ae.]]*xy abxy 0 4 ;ab[_[.ae.]]*xy ab_xy 0 5 ;ab[_[.ae.]]* ab 0 2 ;ab[_[.ae.]]* ab__ 0 4 ;ab[_[.ae.]]{2,5}xy ab__xy_ 0 6 ;ab[_[.ae.]]{2,5}xy ab____xy_ 0 8 ;ab[_[.ae.]]{2,5}xy ab_____xy_ 0 9 ;ab[_[.ae.]]{2,5}xy ab__xy 0 6 ;ab[_[.ae.]]{2,5}xy ab_____xy 0 9 ;ab[_[.ae.]]{2,5} ab__ 0 4 ;ab[_[.ae.]]{2,5} ab_______ 0 7 ;ab[_[.ae.]]{2,5}xy ab______xy -1 -1 ;ab[_[.ae.]]{2,5}xy ab_xy -1 -1 ;ab[_[.ae.]]*?xy abxy_ 0 4 ;ab[_[.ae.]]*?xy ab_xy_ 0 5 ;ab[_[.ae.]]*?xy abxy 0 4 ;ab[_[.ae.]]*?xy ab_xy 0 5 ;ab[_[.ae.]]*? ab 0 2 ;ab[_[.ae.]]*? ab__ 0 2 ;ab[_[.ae.]]{2,5}?xy ab__xy_ 0 6 ;ab[_[.ae.]]{2,5}?xy ab____xy_ 0 8 ;ab[_[.ae.]]{2,5}?xy ab_____xy_ 0 9 ;ab[_[.ae.]]{2,5}?xy ab__xy 0 6 ;ab[_[.ae.]]{2,5}?xy ab_____xy 0 9 ;ab[_[.ae.]]{2,5}? ab__ 0 4 ;ab[_[.ae.]]{2,5}? ab_______ 0 4 ;ab[_[.ae.]]{2,5}?xy ab______xy -1 -1 ;ab[_[.ae.]]{2,5}xy ab_xy -1 -1 ; new bugs detected in spring 2003: - normal match_continuous REG_NO_POSIX_TEST b abc 1 2 () abc 0 0 0 0 ^() abc 0 0 0 0 ^()+ abc 0 0 0 0 ^(){1} abc 0 0 0 0 ^(){2} abc 0 0 0 0 ^((){2}) abc 0 0 0 0 0 0 () "" 0 0 0 0 ()\1 "" 0 0 0 0 ()\1 a 0 0 0 0 a()\1b ab 0 2 1 1 a()b\1 ab 0 2 1 1 ; subtleties of matching with no sub-expressions marked - normal match_nosubs REG_NO_POSIX_TEST a(b?c)+d accd 0 4 (wee|week)(knights|night) weeknights 0 10 .* abc 0 3 a(b|(c))d abd 0 3 a(b|(c))d acd 0 3 a(b*|c|e)d abbd 0 4 a(b*|c|e)d acd 0 3 a(b*|c|e)d ad 0 2 a(b?)c abc 0 3 a(b?)c ac 0 2 a(b+)c abc 0 3 a(b+)c abbbc 0 5 a(b*)c ac 0 2 (a|ab)(bc([de]+)f|cde) abcdef 0 6 a([bc]?)c abc 0 3 a([bc]?)c ac 0 2 a([bc]+)c abc 0 3 a([bc]+)c abcc 0 4 a([bc]+)bc abcbc 0 5 a(bb+|b)b abb 0 3 a(bbb+|bb+|b)b abb 0 3 a(bbb+|bb+|b)b abbb 0 4 a(bbb+|bb+|b)bb abbb 0 4 (.*).* abcdef 0 6 (a*)* bc 0 0 - normal nosubs REG_NO_POSIX_TEST a(b?c)+d accd 0 4 (wee|week)(knights|night) weeknights 0 10 .* abc 0 3 a(b|(c))d abd 0 3 a(b|(c))d acd 0 3 a(b*|c|e)d abbd 0 4 a(b*|c|e)d acd 0 3 a(b*|c|e)d ad 0 2 a(b?)c abc 0 3 a(b?)c ac 0 2 a(b+)c abc 0 3 a(b+)c abbbc 0 5 a(b*)c ac 0 2 (a|ab)(bc([de]+)f|cde) abcdef 0 6 a([bc]?)c abc 0 3 a([bc]?)c ac 0 2 a([bc]+)c abc 0 3 a([bc]+)c abcc 0 4 a([bc]+)bc abcbc 0 5 a(bb+|b)b abb 0 3 a(bbb+|bb+|b)b abb 0 3 a(bbb+|bb+|b)b abbb 0 4 a(bbb+|bb+|b)bb abbb 0 4 (.*).* abcdef 0 6 (a*)* bc 0 0 kbuild-3686/src/oldsed/testsuite/empty.good0000664000175000017500000000000315053010105020775 0ustar locutuslocutusx kbuild-3686/src/oldsed/testsuite/8to7.inp0000664000175000017500000000026015053010105020303 0ustar locutuslocutus䯤â¤è ¤ß䯻ý¤Á ·¡¶ú¤â¤è ¤ß·¡¶ú»ý¤Á ¤³¤ÎµÖ¤Ë ºÚŦ¤Þ¤¹»ù ²È´Ö¤«¤Ê ¹ð¤é¤µ¤Í ¤½¤é¤ß¤Ä ÂçϤιñ¤Ï ¤ª¤·¤ã¤Ê¤Ù¤Æ ¤ï¤ì¤³¤½µï¤ì ¤·¤­¤Ê¤Ù¤Æ ¤ï¤ì¤³¤½ ºÂ¤» ¤ï¤Ë¤³¤½¤Ï ¹ð¤é¤á ²È¤ò¤â̾¤ò¤â kbuild-3686/src/oldsed/testsuite/space.good0000664000175000017500000000004415053010105020737 0ustar locutuslocutusHello_World_! SecondXXine__of_tests kbuild-3686/src/oldsed/testsuite/flipcase.sed0000664000175000017500000000005015053010105021252 0ustar locutuslocutuss,\([^A-Za-z]*\)\([A-Za-z]*\),\1\L\u\2,gkbuild-3686/src/oldsed/testsuite/binary2.sed0000664000175000017500000001172015053010105021040 0ustar locutuslocutus# A kind of clone of dc geared towards binary operations. # by Paolo Bonzini # # commands available: # conversion commands # b convert decimal to binary # d convert binary to decimal # # arithmetic commands # < shift left binary by decimal number of bits (11 3< gives 11000) # > shift right binary by decimal number of bits (1011 2> gives 10) # & binary AND (between two binary operands) # | binary OR (between two binary operands) # ^ binary XOR (between two binary operands) # ~ binary NOT (between one binary operand) # # stack manipulation commands # c clear stack # P pop stack top # D duplicate stack top # x exchange top two elements # r rotate stack counter-clockwise (second element becomes first) # R rotate stack clockwise (last element becomes first) # # other commands # l print stack (stack top is first) # p print stack top # q quit, print stack top if any (cq is quiet quit) # # The only shortcoming is that you'd better not attempt conversions of # values above 1000 or so. # # This version keeps the stack in hold space and the command in pattern # space; it is the fastest one (though the gap with binary3.sed is small). # -------------------------------------------------------------------------- # This was actually used in a one-disk distribution of Linux to compute # netmasks as follows (1 parameter => compute netmask e.g. 24 becomes # 255.255.255.0; 2 parameters => given host address and netmask compute # network and broadcast addresses): # # if [ $# = 1 ]; then # OUTPUT='$1.$2.$3.$4' # set 255.255.255.255 $1 # else # OUTPUT='$1.$2.$3.$4 $5.$6.$7.$8' # fi # # if [ `expr $2 : ".*\\."` -gt 0 ]; then # MASK="$2 br b8dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP # | DDD 24>dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP # " | sed -f binary.sed` # # eval echo $OUTPUT # -------------------------------------------------------------------------- :cmd s/^[\n\t ]*// s/^#.*// /^$/ { $b quit N t cmd } /^[0-9][0-9]*/ { G h s/^[0-9][0-9]* *\([^\n]*\).*/\1/ x s/^\([0-9][0-9]*\)[^\n]*/\1/ x t cmd } /^[^DPxrRcplqbd&|^~<>]/b bad /^D/ { x s/^[^\n]*\n/&&/ } /^P/ { x s/^[^\n]*\n// } /^x/ { x s/^\([^\n]*\n\)\([^\n]*\n\)/\2\1/ } /^r/ { x s/^\([^\n]*\n\)\(.*\)/\2\1/ } /^R/ { x s/^\(.*\n\)\([^\n]*\n\)/\2\1/ } /^c/ { x s/.*// } /^p/ { x P } /^l/ { x p } /^q/ { :quit x /./P d } /^b/ { # Decimal to binary via analog form x s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/ :d2bloop1 s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/ t d2bloop1 s/-;9876543210aaaaaaaaa/;a01!/ :d2bloop2 s/\(a*\)\1\(a\{0,1\}\)\(;\2.\(.\)[^!]*!\)/\1\3\4/ /^a/b d2bloop2 s/[^!]*!// } /^d/ { # Binary to decimal via analog form x s/^\([^\n]*\)/-&;10a/ :b2dloop1 s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\(a*\)\)/\1\1\4-\3/ t b2dloop1 s/-;10a/;aaaaaaaaa0123456789!/ :b2dloop2 s/\(a*\)\1\1\1\1\1\1\1\1\1\(a\{0,9\}\)\(;\2.\{9\}\(.\)[^!]*!\)/\1\3\4/ /^a/b b2dloop2 s/[^!]*!// } /^&/ { # Binary AND x s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-111 01000/ :andloop s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/ t andloop s/^0*\([^-]*\)-[^\n]*/\1/ s/^\n/0&/ } /^\^/ { # Binary XOR x s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 01101/ b orloop } /^|/ { # Binary OR x s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 10111/ :orloop s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/ t orloop s/\([^-]*\)-\([^-]*\)-\([^-]*\)-[^\n]*/\2\3\1/ } /^~/ { # Binary NOT x s/^\(.\)\([^\n]*\n\)/\1-010-\2/ :notloop s/\(.\)-0\{0,1\}\1\(.\)0\{0,1\}-\([01\n]\)/\2\3-010-/ t notloop # If result is 00001..., \3 does not match (it looks for -10) and we just # remove the table and leading zeros. If result is 0000...0, \3 matches # (it looks for -0), \4 is a zero and we leave a lone zero as top of the # stack. s/0*\(1\{0,1\}\)\([^-]*\)-\(\1\(0\)\)\{0,1\}[^-]*-/\4\1\2/ } /^/ { # Right shift, convert to analog and remove a binary digit for each analog digit x s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/ :rshloop1 s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/ t rshloop1 s/^\(a*\)-;9876543210aaaaaaaaa\n\([^\n]*\)/\2\1/ :rshloop2 s/.a// s/^aa*/0/ /a\n/b rshloop2 } x :bad s/^.// tcmd kbuild-3686/src/oldsed/testsuite/eval.sed0000664000175000017500000000073215053010105020422 0ustar locutuslocutus1d #Try eval command /cpu/!b2 e../sed/sed 1q eval.in2 :2 p i--- h #Try eval option s,.* *cpu *,../sed/sed 1q eval.in2; echo "&",e :3 p g i--- h #Try eval option with print s,.* *cpu.*,../sed/sed 1q eval.in2,ep g :4 p i--- $!d #Do some more tests s/.*/Doing some more tests -----------------------/p s,.*,../sed/sed 1q eval.in2,ep i--- s,.*,../sed/sed 1q eval.in2,pe i--- s,.*,../sed/sed 1q eval.in2, h e p g i--- s/^/echo /ep i--- s/^fubar$/echo wozthis/e kbuild-3686/src/oldsed/testsuite/wrtout2.good0000664000175000017500000000011215053010105021266 0ustar locutuslocutusFacts are simple and facts are straight Facts are lazy and facts are late kbuild-3686/src/oldsed/testsuite/8to7.sed0000664000175000017500000000000415053010105020264 0ustar locutuslocutusl;d kbuild-3686/src/oldsed/testsuite/head.inp0000664000175000017500000000072215053010105020406 0ustar locutuslocutus "...by imposing a tiny bit of order in a communication you are translating, you are carving out a little bit of order in the universe. You will never succeed. Everything will fail and come to an end finally. But you have a chance to carve a little bit of order and maybe even beauty out of the raw materials that surround you everywhere, and I think there is no greater meaning in life." Donald L. Philippi, Oct 1930 - Jan 1993 kbuild-3686/src/oldsed/testsuite/y-bracket.sed0000664000175000017500000000000715053010105021347 0ustar locutuslocutusy/[/ / kbuild-3686/src/oldsed/testsuite/version.gin0000664000175000017500000000040315053010105021155 0ustar locutuslocutusGNU sed version @VERSION@ Copyright (C) 2003 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, to the extent permitted by law. kbuild-3686/src/oldsed/testsuite/uniq.good0000664000175000017500000011004615053010105020624 0ustar locutuslocutus #define DPRINTF(p) /*nothing */ #define DPRINTF(p) printf p #define GETCHAR(c, eptr) c = *eptr; #define GETCHARINC(c, eptr) c = *eptr++; #define class pcre_class #define match_condassert 0x01 /* Called to check a condition assertion */ #define match_isgroup 0x02 /* Set if start of bracketed group */ #else #endif #ifdef DEBUG /* Sigh. Some compilers never learn. */ #ifdef DEBUG #ifdef __cplusplus #include "internal.h" && length - re->max_match_size > start_offset) ((*ecode++ == OP_BEG_WORD) ? prev_is_word : cur_is_word)) ((md->ctypes[*eptr] & ctype_word) != 0); ((md->ctypes[eptr[-1]] & ctype_word) != 0); (eptr == md->end_subject - 1 && *eptr != '\n')) (i.e. keep it out of the loop). Also we can test that there are at least (md->ctypes[*eptr++] & ctype_digit) != 0) (md->ctypes[*eptr++] & ctype_digit) == 0) (md->ctypes[*eptr++] & ctype_space) != 0) (md->ctypes[*eptr++] & ctype_space) == 0) (md->ctypes[*eptr++] & ctype_word) != 0) (md->ctypes[*eptr++] & ctype_word) == 0) (offsetcount - 2) * sizeof (int)); (offsets == NULL && offsetcount > 0)) (pcre_free) (match_block.offset_vector); (pcre_free) (save); (re->tables + fcc_offset)[req_char] : req_char; * Match a back-reference * * Execute a Regular Expression * * Match from current position * * Debugging function to print chars * * Perl-Compatible Regular Expressions * * Macros and tables for character handling * *************************************************/ */ *iptr = -1; *iptr++ = -1; *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT || *prev == OP_ONCE) ----------------------------------------------------------------------------- -1 => failed to match /* /* "Once" brackets are like assertion brackets except that after a match, /* ... else fall through */ /* Advance to a possible match for an initial string after study */ /* Allow compilation as C++ source code, should anybody want to do that. */ /* Always fail if not enough characters left */ /* An alternation is the end of a branch; scan along to find the end of the /* Assert before internal newline if multiline, or before a terminating /* Assertion brackets. Check the alternative branches in turn - the /* At the start of a bracketed group, add the current subject pointer to the /* BRAZERO and BRAMINZERO occur just before a bracket group, indicating /* Caseful comparisons */ /* Change option settings */ /* Common code for all repeated single character type matches */ /* Common code for all repeated single-character matches. We can give /* Compute the minimum number of offsets that we need to reset each time. Doing /* Conditional group: compilation checked that there are no more than /* Continue as from after the assertion, updating the offsets high water /* Continue from after the assertion, updating the offsets high water /* Control never gets here */ /* Control never reaches here */ /* Copy the offset information from temporary store if necessary */ /* Do a single test if no case difference is set up */ /* Do not stick any code in here without much thought; it is assumed /* End of a group, repeated or non-repeating. If we are at the end of /* End of subject assertion (\z) */ /* End of subject or ending \n assertion (\Z) */ /* End of the pattern. If PCRE_NOTEMPTY is set, fail if we have matched /* First, ensure the minimum number of matches are present. */ /* First, ensure the minimum number of matches are present. Use inline /* First, ensure the minimum number of matches are present. We get back /* Flag bits for the match() function */ /* For a non-repeating ket, just continue at this level. This also /* For anchored or unanchored matches, there may be a "last known required /* For extended extraction brackets (large number), we have to fish out /* For extended extraction brackets (large number), we have to fish out the /* For matches anchored to the end of the pattern, we can often avoid /* If a back reference hasn't been set, the length that is passed is greater /* If checking an assertion for a condition, return TRUE. */ /* If hit the end of the group (which could be repeated), fail */ /* If max == min we can continue with the main loop without the /* If maximizing it is worth using inline code for speed, doing the type /* If maximizing, find the longest possible run, then work backwards. */ /* If maximizing, find the longest string and work backwards */ /* If min = max, continue at the same level without recursing */ /* If min = max, continue at the same level without recursion. /* If minimizing, keep testing the rest of the expression and advancing /* If minimizing, keep trying and advancing the pointer */ /* If minimizing, we have to test the rest of the pattern before each /* If req_char is set, we know that that character must appear in the subject /* If the expression has got more back references than the offsets supplied can /* If the length of the reference is zero, just continue with the /* If the reference is unset, set the length to be longer than the amount /* If we can't find the required character, break the matching loop */ /* If we have found the required character, save the point where we /* In all other cases except a conditional group we have to check the /* In case the recursion has set more capturing values, save the final /* Include the internals header, which itself includes Standard C headers plus /* Insufficient room for saving captured contents */ /* Loop for handling unanchored repeated matching attempts; for anchored regexs /* Match a back reference, possibly repeatedly. Look past the end of the /* Match a character class, possibly repeatedly. Look past the end of the /* Match a negated single character */ /* Match a negated single character repeatedly. This is almost a repeat of /* Match a run of characters */ /* Match a single character repeatedly; different opcodes share code. */ /* Match a single character type repeatedly; several different opcodes /* Match a single character type; inline for speed */ /* Min and max values for the common repeats; for the maxima, 0 => infinity */ /* Move the subject pointer back. This occurs only at the start of /* Negative assertion: all branches must fail to match */ /* Now start processing the operations. */ /* OP_KETRMAX */ /* On entry ecode points to the first opcode, and eptr to the first character /* Opening capturing bracket. If there is space in the offset vector, save /* Or to a non-unique first char after study */ /* Or to a unique first char if possible */ /* Or to just after \n for a multiline match if possible */ /* Other types of node can be handled by a switch */ /* Otherwise test for either case */ /* Print a sequence of chars in printable format, stopping at the end of the /* Recursion matches the current regex, nested. If there are any capturing /* Reset the maximum number of extractions we might see. */ /* Reset the value of the ims flags, in case they got changed during /* Reset the working variable associated with each extraction. These should /* Separate the caselesss case for speed */ /* Set up for repetition, or handle the non-repeated case */ /* Set up the first character to match, if available. The first_char value is /* Skip over conditional reference data or large extraction number data if /* Start of subject assertion */ /* Start of subject unless notbol, or after internal newline if multiline */ /* Structure for building a chain of data that actually lives on the /* The code is duplicated for the caseless and caseful cases, for speed, /* The condition is an assertion. Call match() to evaluate it - setting /* The ims options can vary during the matching as a result of the presence /* The repeating kets try the rest of the pattern or restart from the /* There's been some horrible disaster. */ /* This "while" is the end of the "do" above */ /* This function applies a compiled re to a subject string and picks out /* Use a macro for debugging printing, 'cause that limits the use of #ifdef /* We don't need to repeat the search if we haven't yet reached the /* When a match occurs, substrings will be set for all internal extractions; /* Word boundary assertions */ /************************************************* 1. This software is distributed in the hope that it will be useful, 2. The origin of this software must not be misrepresented, either by 3. Altered versions must be plainly marked as such, and must not be 4. If PCRE is embedded in any software that is released under the GNU 5.005. If there is an options reset, it will get obeyed in the normal 6 : 3 + (ecode[1] << 8) + ecode[2]), < -1 => some kind of unexpected problem = 0 => success, but offsets is not big enough Arguments: BOOL anchored; BOOL cur_is_word = (eptr < md->end_subject) && BOOL is_subject; BOOL minimize = FALSE; BOOL prev_is_word = (eptr != md->start_subject) && BOOL rc; BOOL startline; BOOL using_temporary_offsets = FALSE; Copyright (c) 1997-2000 University of Cambridge DPRINTF ((">>>> returning %d\n", match_block.errorcode)); DPRINTF ((">>>> returning %d\n", rc)); DPRINTF (("Copied offsets from temporary memory\n")); DPRINTF (("Freeing temporary memory\n")); DPRINTF (("Got memory to hold back references\n")); DPRINTF (("Unknown opcode %d\n", *ecode)); DPRINTF (("bracket %d failed\n", number)); DPRINTF (("bracket 0 failed\n")); DPRINTF (("ims reset to %02lx\n", ims)); DPRINTF (("ims set to %02lx at group repeat\n", ims)); DPRINTF (("ims set to %02lx\n", ims)); DPRINTF (("matching %c{%d,%d} against subject %.*s\n", c, min, max, DPRINTF (("negative matching %c{%d,%d} against subject %.*s\n", c, min, max, DPRINTF (("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); DPRINTF (("start bracket 0\n")); GETCHAR (c, eptr) /* Get character */ GETCHARINC (c, eptr) /* Get character; increment eptr */ General Purpose Licence (GPL), then the terms of that licence shall However, if the referenced string is the empty string, always treat If the bracket fails to match, we need to restore this value and also the If there isn't enough space in the offset vector, treat this as if it were a MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Otherwise, we can use the vector supplied, rounding down its size to a multiple Permission is granted to anyone to use this software for any purpose on any REPEATCHAR: REPEATNOTCHAR: REPEATTYPE: Returns: > 0 => success; value is the number of elements filled in Returns: TRUE if matched Returns: TRUE if matched Returns: nothing They are not both allowed to be zero. */ This is a library of functions to support regular expressions whose syntax This is the forcible breaking of infinite loops as implemented in Perl Writing separate code makes it go faster, as does using an autoincrement and Written by: Philip Hazel a move back into the brackets. Check the alternative branches in turn - the address of eptr, so that eptr can be a register variable. */ an assertion "group", stop matching and return TRUE, but record the an empty string - recursion will then try other alternatives, if any. */ an error. Save the top 15 values on the stack, and accept that the rest an unanchored pattern, of course. If there's no first char and the pattern was analyzing most of the pattern. length > re->max_match_size is anchored = ((re->options | options) & PCRE_ANCHORED) != 0; and advance one byte in the pattern code. */ and reinstate them after the recursion. However, we don't know how many and semantics are as close as possible to those of the Perl 5 language. See and the required character in fact is caseful. */ at run time, so we have to test for anchoring. The first char may be unset for avoid duplicate testing (which takes significant time). This covers the vast backing off on a match. */ bmtable = extra->data.bmtable; both cases of the character. Otherwise set the two values the same, which will bracketed group and go to there. */ brackets - for testing for empty matches brackets started but not finished, we have to save their starting points break; but WITHOUT ANY WARRANTY; without even the implied warranty of c != md->lcc[*eptr++]) c = *ecode++ - OP_CRSTAR; c = *ecode++ - OP_NOTSTAR; c = *ecode++ - OP_STAR; c = *ecode++ - OP_TYPESTAR; c = *ecode++; c = *eptr++; c = 15; c = max - min; c = md->end_subject - eptr; c = md->lcc[c]; c = md->offset_max; c == md->lcc[*eptr++]) can't just fail here, because of the possibility of quantifiers with zero case OP_ALT: case OP_ANY: case OP_ASSERT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ASSERT_NOT: case OP_BEG_WORD: case OP_BRA: /* Non-capturing bracket: optimized */ case OP_BRAMINZERO: case OP_BRANUMBER: case OP_BRAZERO: case OP_CHARS: case OP_CIRC: case OP_CLASS: case OP_COND: case OP_CREF: case OP_CRMINPLUS: case OP_CRMINQUERY: case OP_CRMINRANGE: case OP_CRMINSTAR: case OP_CRPLUS: case OP_CRQUERY: case OP_CRRANGE: case OP_CRSTAR: case OP_DIGIT: case OP_DOLL: case OP_END: case OP_END_WORD: case OP_EOD: case OP_EODN: case OP_EXACT: case OP_KET: case OP_KETRMAX: case OP_KETRMIN: case OP_MINPLUS: case OP_MINQUERY: case OP_MINSTAR: case OP_MINUPTO: case OP_NOT: case OP_NOTEXACT: case OP_NOTMINPLUS: case OP_NOTMINQUERY: case OP_NOTMINSTAR: case OP_NOTMINUPTO: case OP_NOTPLUS: case OP_NOTQUERY: case OP_NOTSTAR: case OP_NOTUPTO: case OP_NOT_DIGIT: case OP_NOT_WHITESPACE: case OP_NOT_WORDCHAR: case OP_NOT_WORD_BOUNDARY: case OP_ONCE: case OP_OPT: case OP_PLUS: case OP_QUERY: case OP_RECURSE: case OP_REF: case OP_REVERSE: case OP_SOD: case OP_STAR: case OP_TYPEEXACT: case OP_TYPEMINPLUS: case OP_TYPEMINQUERY: case OP_TYPEMINSTAR: case OP_TYPEMINUPTO: case OP_TYPEPLUS: case OP_TYPEQUERY: case OP_TYPESTAR: case OP_TYPEUPTO: case OP_UPTO: case OP_WHITESPACE: case OP_WORDCHAR: case OP_WORD_BOUNDARY: case matching may be when this character is hit, so test for it in both its caselessly, or if there are any changes of this flag within the regex, set up cases if necessary. However, the different cased versions will not be set up character" set. If the PCRE_CASELESS is set, implying that the match starts characters and work backwards. */ code for maximizing the speed, and do the type test once at the start code to character type repeats - written out again for speed. */ commoning these up that doesn't require a test of the positive/negative computer system, and to redistribute it freely, subject to the following const char *subject; const pcre *re; const pcre_extra *extra; const uschar *bmtable = NULL; const uschar *data = ecode + 1; /* Save for matching */ const uschar *end_subject; const uschar *next = ecode + 1; const uschar *p = md->start_subject + md->offset_vector[offset]; const uschar *p; const uschar *pp = eptr; const uschar *prev = ecode - (ecode[1] << 8) - ecode[2]; const uschar *prev = ecode; const uschar *req_char_ptr = start_match - 1; const uschar *saved_eptr = eptr; const uschar *saved_eptr = eptrb->saved_eptr; const uschar *saved_eptr; const uschar *start_bits = NULL; const uschar *start_match = (const uschar *) subject + start_offset; continue; /* With the main loop */ continue; course of events. */ ctype = *ecode++; /* Code for the character type */ cur_is_word == prev_is_word : cur_is_word != prev_is_word) current high water mark for use by positive assertions. Do this also default: /* No repeat follows */ default: do each branch of a lookbehind assertion. If we are too close to the start to each substring: the offsets to the start and end of the substring. ecode position in code ecode + ((offset < offset_top && md->offset_vector[offset] >= 0) ? ecode += (ecode[1] << 8) + ecode[2]; ecode += 2; ecode += 3 + (ecode[4] << 8) + ecode[5]; ecode += 33; /* Advance past the item */ ecode += 3; /* Advance past the item */ ecode += 3; ecode += 5; ecode = next + 3; ecode++; else else if ((extra->options & PCRE_STUDY_BM) != 0) else if (first_char >= 0) else if (start_bits != NULL) else if (startline) encountered */ end_subject = match_block.end_subject; eptr pointer in subject eptr points into the subject eptr += c; eptr += length; eptr += min; eptr -= (ecode[1] << 8) + ecode[2]; eptr -= length; eptr = md->end_match_ptr; eptr++; eptrb pointer to chain of blocks containing eptr at start of eptrb = &newptrb; eptrb = eptrb->prev; /* Back up the stack of bracket start pointers */ eptrblock *eptrb; eptrblock newptrb; eptrblock; exactly what going to the ket would do. */ explicit claim or by omission. external_extra points to "hints" from pcre_study() or is NULL external_re points to the compiled expression extraction by setting the offsets and bumping the high water mark. */ first_char = match_block.lcc[first_char]; first_char = re->first_char; flags can contain for (;;) for (i = 1; i <= c; i++) for (i = 1; i <= min; i++) for (i = min; i < max; i++) for (i = min;; i++) for the "once" (not-backup up) groups. */ for the match to succeed. If the first character is set, req_char must be found it, so that we don't search again next time round the loop if from a previous iteration of this group, and be referred to by a reference goto REPEATCHAR; goto REPEATNOTCHAR; goto REPEATTYPE; group number back at the start and if necessary complete handling an happens for a repeating ket if no characters were matched in the group. here; that is handled in the code for KET. */ hold, we get a temporary bit of working store to use during the matching. i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper if (!anchored) if (!match (start_match, re->code, 2, &match_block, ims, NULL, match_isgroup)) if (!match_ref (offset, eptr, length, md, ims)) if (!md->endonly) if (!rc) if (!startline && extra != NULL) if ((*ecode++ == OP_WORD_BOUNDARY) ? if ((data[c / 8] & (1 << (c & 7))) != 0) if ((data[c / 8] & (1 << (c & 7))) == 0) if ((extra->options & PCRE_STUDY_MAPPED) != 0) if ((flags & match_condassert) != 0) if ((flags & match_isgroup) != 0) if ((ims & PCRE_CASELESS) != 0) if ((ims & PCRE_DOTALL) == 0 && c == '\n') if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == '\n') if ((ims & PCRE_DOTALL) == 0) if ((ims & PCRE_MULTILINE) != 0) if ((md->ctypes[*eptr++] & ctype_digit) != 0) if ((md->ctypes[*eptr++] & ctype_digit) == 0) if ((md->ctypes[*eptr++] & ctype_space) != 0) if ((md->ctypes[*eptr++] & ctype_space) == 0) if ((md->ctypes[*eptr++] & ctype_word) != 0) if ((md->ctypes[*eptr++] & ctype_word) == 0) if ((md->ctypes[c] & ctype_digit) != 0) if ((md->ctypes[c] & ctype_digit) == 0) if ((md->ctypes[c] & ctype_space) != 0) if ((md->ctypes[c] & ctype_space) == 0) if ((md->ctypes[c] & ctype_word) != 0) if ((md->ctypes[c] & ctype_word) == 0) if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) if ((re->options & PCRE_FIRSTSET) != 0) if ((re->options & PCRE_REQCHSET) != 0) if ((start_bits[c / 8] & (1 << (c & 7))) == 0) if (*ecode != OP_ONCE && *ecode != OP_ALT) if (*ecode == OP_KET || eptr == saved_eptr) if (*ecode == OP_KET) if (*ecode == OP_KETRMIN) if (*ecode++ != *eptr++) if (*ecode++ == *eptr++) if (*eptr != '\n') if (*eptr++ == '\n') if (*p++ != *eptr++) if (*p++ == req_char) if (*prev != OP_COND) if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT || if (bmtable != NULL) if (bmtable[*start_match]) if (c != *eptr++) if (c != md->lcc[*eptr++]) if (c < 16) if (c == *eptr++) if (c == md->lcc[*eptr++]) if (c > md->end_subject - eptr) if (cur_is_word == prev_is_word || if (ecode[3] == OP_CREF) /* Condition is extraction test */ if (ecode[3] == OP_OPT) if (eptr != md->start_subject && eptr[-1] != '\n') if (eptr != md->start_subject) if (eptr < md->end_subject - 1 || if (eptr < md->end_subject) if (eptr < md->start_subject) if (eptr >= md->end_subject || if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0) if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0) if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0) if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0) if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0) if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0) if (eptr >= md->end_subject || *eptr == '\n') if (eptr >= md->end_subject || c != *eptr) if (eptr >= md->end_subject || c != md->lcc[*eptr]) if (eptr >= md->end_subject || c == *eptr) if (eptr >= md->end_subject || c == md->lcc[*eptr]) if (eptr >= md->end_subject) if (eptr++ >= md->end_subject) if (i >= max || !match_ref (offset, eptr, length, md, ims)) if (i >= max || eptr >= md->end_subject || if (i >= max || eptr >= md->end_subject || c != *eptr++) if (i >= max || eptr >= md->end_subject || c == *eptr++) if (i >= max || eptr >= md->end_subject) if (is_subject && length > md->end_subject - p) if (isprint (c = *(p++))) if (length == 0) if (length > md->end_subject - eptr) if (match (eptr, ecode + 3, offset_top, md, ims, NULL, if (match (eptr, ecode + 3, offset_top, md, ims, NULL, match_isgroup)) if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, 0) || if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, match_isgroup)) if (match (eptr, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr, next + 3, offset_top, md, ims, eptrb, match_isgroup)) if (match (eptr, next, offset_top, md, ims, eptrb, match_isgroup)) if (match (eptr, prev, offset_top, md, ims, eptrb, match_isgroup) || if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0)) if (match_block.end_offset_top > offsetcount) if (match_block.offset_vector != NULL) if (match_block.offset_vector == NULL) if (max == 0) if (md->lcc[*ecode++] != md->lcc[*eptr++]) if (md->lcc[*ecode++] == md->lcc[*eptr++]) if (md->lcc[*p++] != md->lcc[*eptr++]) if (md->notbol && eptr == md->start_subject) if (md->notempty && eptr == md->start_match) if (md->noteol) if (min == max) if (min > 0) if (min > md->end_subject - eptr) if (minimize) if (number > 0) if (number > EXTRACT_BASIC_MAX) if (offset < md->offset_max) if (offset >= md->offset_max) if (offset_top <= offset) if (offsetcount < 2) if (offsetcount >= 4) if (op > OP_BRA) if (p > req_char_ptr) if (p >= end_subject) if (pp == req_char || pp == req_char2) if (re == NULL || subject == NULL || if (re->magic_number != MAGIC_NUMBER) if (re->max_match_size >= 0 if (re->top_backref > 0 && re->top_backref >= ocount / 3) if (req_char == req_char2) if (req_char >= 0) if (resetcount > offsetcount) if (save != stacksave) if (save == NULL) if (skipped_chars) if (start_match + bmtable[256] > end_subject) if (start_match > match_block.start_subject + start_offset) if (using_temporary_offsets) if certain parts of the pattern were not used. */ if the malloc fails ... there is no way of returning to the top level with implied in the second condition, because start_offset > 0. */ ims current /i, /m, and /s options ims the ims flags ims = (ims & ~PCRE_IMS) | ecode[4]; ims = ecode[1]; ims = original_ims; ims = re->options & (PCRE_CASELESS | PCRE_MULTILINE | PCRE_DOTALL); in the pattern. */ in the subject string, while eptrb holds the value of eptr at the start of the initialize them to avoid reading uninitialized locations. */ inline, and there are *still* stupid compilers about that don't like indented inside the group. int int *offsets; int *save; int c; int first_char = -1; int flags; int length; int min, max, ctype; int number = *prev - OP_BRA; int number = op - OP_BRA; int offset = (ecode[1] << 9) | (ecode[2] << 1); /* Doubled reference number */ int offset = (ecode[4] << 9) | (ecode[5] << 1); /* Doubled reference number */ int offset; int offset_top; int offsetcount; int op = (int) *ecode; int options; int rc; int req_char = -1; int req_char2 = -1; int resetcount, ocount; 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 skipped_chars = 0; int stacksave[15]; int start_offset; is a bit large to put on the stack, but using malloc for small numbers is_subject TRUE if printing from within md->start_subject it as matched, any number of times (otherwise there could be infinite item to see if there is repeat information following. The code is similar item to see if there is repeat information following. Then obey similar last bracketed group - used for breaking infinite loops matching zero-length later in the subject; otherwise the test starts at the match point. This length length of subject string (may contain binary zeros) length length to be matched length number to print length = (offset >= offset_top || md->offset_vector[offset] < 0) ? length = md->end_subject - p; level without recursing. Otherwise, if minimizing, keep trying the rest of loop. */ loops). */ main loop. */ majority of cases. It will be suboptimal when the case flag changes in a regex mark, since extracts may have been taken during the assertion. */ mark, since extracts may have been taken. */ match (eptr, ecode + 3, offset_top, md, ims, eptrb, 0)) match (eptr, ecode, offset_top, md, ims, eptrb, flags) match (eptr, prev, offset_top, md, ims, eptrb, match_isgroup)) match_block.ctypes = re->tables + ctypes_offset; match_block.end_subject = match_block.start_subject + length; match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; match_block.errorcode = PCRE_ERROR_NOMATCH; /* Default error */ match_block.errorcode == PCRE_ERROR_NOMATCH && match_block.lcc = re->tables + lcc_offset; match_block.lcc[*start_match] != first_char) match_block.notbol = (options & PCRE_NOTBOL) != 0; match_block.notempty = (options & PCRE_NOTEMPTY) != 0; match_block.noteol = (options & PCRE_NOTEOL) != 0; match_block.offset_end = ocount; match_block.offset_max = (2 * ocount) / 3; match_block.offset_overflow = FALSE; match_block.offset_overflow = TRUE; match_block.offset_vector = (int *) (pcre_malloc) (ocount * sizeof (int)); match_block.offset_vector = offsets; match_block.start_match = start_match; match_block.start_pattern = re->code; match_block.start_subject = (const uschar *) subject; match_condassert - this is an assertion condition match_condassert | match_isgroup)) match_data *md; match_data match_block; match_isgroup - this is the start of a bracketed group match_isgroup); match_ref (offset, eptr, length, md, ims) matches, we carry on as at the end of a normal bracket, leaving the subject matching won't pass the KET for an assertion. If any one branch matches, matching won't pass the KET for this kind of subpattern. If any one branch max = (ecode[1] << 8) + ecode[2]; max = (ecode[3] << 8) + ecode[4]; max = INT_MAX; max = rep_max[c]; /* zero for max => infinity */ max, eptr)); maximum. Alternatively, if maximizing, find the maximum number of may be wrong. */ md pointer to "static" info for the match md pointer to matching data block, if is_subject is TRUE md points to match data block md->end_match_ptr = eptr; /* For ONCE */ md->end_match_ptr = eptr; /* Record where we ended */ md->end_offset_top = offset_top; /* and how many extracts were taken */ md->end_offset_top = offset_top; md->end_subject - eptr + 1 : md->errorcode = PCRE_ERROR_UNKNOWN_NODE; md->offset_overflow = TRUE; md->offset_vector[md->offset_end - i] = save[i]; md->offset_vector[md->offset_end - number] = eptr - md->start_subject; md->offset_vector[md->offset_end - number] = save_offset3; md->offset_vector[md->offset_end - number]; md->offset_vector[offset + 1] - md->offset_vector[offset]; md->offset_vector[offset + 1] = eptr - md->start_subject; md->offset_vector[offset + 1] = save_offset2; md->offset_vector[offset] = md->offset_vector[offset] = save_offset1; memcpy (offsets + 2, match_block.offset_vector + 2, min = (ecode[1] << 8) + ecode[2]; min = 0; min = max = (ecode[1] << 8) + ecode[2]; min = max = 1; min = rep_min[c]; /* Pick up values from tables; */ minima. */ minimize = (*ecode == OP_CRMINRANGE); minimize = (c & 1) != 0; minimize = *ecode == OP_MINUPTO; minimize = *ecode == OP_NOTMINUPTO; minimize = *ecode == OP_TYPEMINUPTO; minimize = TRUE; minimum number of matches are present. If min = max, continue at the same misrepresented as being the original software. move back, this match function fails. */ mustn't change the current values of the data slot, because they may be set need to recurse. */ never be used unless previously set, but they get saved and restored, and so we never set for an anchored regular expression, but the anchoring may be forced newline unless endonly is set, else end of subject unless noteol is set. */ newptrb.prev = eptrb; newptrb.saved_eptr = eptr; next += (next[1] << 8) + next[2]; non-capturing bracket. Don't worry about setting the flag for the error case number = (ecode[4] << 8) | ecode[5]; number = (prev[4] << 8) | prev[5]; number from a dummy opcode at the start. */ number, then move along the subject till after the recursive match, ocount = offsetcount - (offsetcount % 3); ocount = re->top_backref * 3 + 3; of (?ims) items in the pattern. They are kept in a local variable so that of 3. */ of subject left; this ensures that every attempt at a match fails. We offset index into the offset vector offset = number << 1; offset_top current top pointer offset_top = md->end_offset_top; offset_top = offset + 2; offset_top, md, ims, eptrb, match_isgroup); offsetcount the number of elements in the vector offsets points to a vector of ints to be filled in with offsets offsets[0] = start_match - match_block.start_subject; offsets[1] = match_block.end_match_ptr - match_block.start_subject; op = OP_BRA; opcode. */ optimization can save a huge amount of backtracking in patterns with nested option for each character match. Maybe that wouldn't add very much to the options option bits p points to characters p--; past the end if there is only one branch, but that's OK because that is pchars (ecode, length, FALSE, md); pchars (eptr, 16, TRUE, md); pchars (eptr, length, TRUE, md); pchars (p, length, FALSE, md); pchars (p, length, is_subject, md) pchars (start_match, end_subject - start_match, TRUE, &match_block); pcre_exec (re, extra, subject, length, start_offset, options, offsets, offsetcount) place we found it at last time. */ pointer. */ portions of the string if it matches. Two elements in the vector are set for pre-processor statements. I suppose it's only been 10 years... */ preceded by BRAZERO or BRAMINZERO. */ preceding bracket, in the appropriate order. */ preceding bracket, in the appropriate order. We need to reset any options printf (" against backref "); printf (" against pattern "); printf ("%c", c); printf (">>>> Match against: "); printf (">>>>> Skipped %d chars to reach first character\n", printf ("\\x%02x", c); printf ("\n"); printf ("end bracket %d", number); printf ("matching subject "); printf ("matching subject against pattern "); printf ("matching subject "); printf ("start bracket %d subject=", number); rc = 0; rc = match (eptr, md->start_pattern, offset_top, md, ims, eptrb, rc = match_block.offset_overflow ? 0 : match_block.end_offset_top / 2; register const uschar *ecode; register const uschar *eptr; register const uschar *p = start_match + ((first_char >= 0) ? 1 : 0); register int *iend = iptr + resetcount; register int *iend = iptr - resetcount / 2 + 1; register int *iptr = match_block.offset_vector + ocount; register int *iptr = match_block.offset_vector; register int c = *start_match; register int c; register int i; register int length = ecode[1]; register int pp = *p++; repeat it in the interests of efficiency. */ repeat limits are compiled as a number of copies, with the optional ones req_char = re->req_char; req_char2 = ((re->options & (PCRE_CASELESS | PCRE_ICHANGED)) != 0) ? req_char_ptr = p; resetcount = 2 + re->top_bracket * 2; resetcount = ocount; restoring at the exit of a group is easy. */ restrictions: return FALSE; return PCRE_ERROR_BADMAGIC; return PCRE_ERROR_BADOPTION; return PCRE_ERROR_NOMATCH; return PCRE_ERROR_NOMEMORY; return PCRE_ERROR_NULL; return TRUE; return match (eptr, return match (eptr, ecode + 3, offset_top, md, ims, eptrb, match_isgroup); return match_block.errorcode; return rc; save = (int *) (pcre_malloc) ((c + 1) * sizeof (int)); save = stacksave; save[i] = md->offset_vector[md->offset_end - i]; seems expensive. As a compromise, the stack is used when there are fewer share code. This is very similar to the code for single characters, but we similar code to character type repeats - written out again for speed. since matching characters is likely to be quite common. First, ensure the skipped_chars += bmtable[*start_match], skipped_chars += bmtable[256] - 1; skipped_chars -= bmtable[256] - 1; skipped_chars); skipped_chars++, stack of such pointers, to be re-instated at the end of the group when we hit stack, for holding the values of the subject pointer at the start of each start of each branch to move the current point backwards, so the code at start_bits = extra->data.start_bits; start_match += bmtable[*start_match]; start_match += bmtable[256] - 1; start_match -= bmtable[256] - 1; start_match = (const uschar *) subject + length - re->max_match_size; start_match++ < end_subject); start_match++; start_offset where to start in the subject string startline = (re->options & PCRE_STARTLINE) != 0; static BOOL static const char rep_max[] = static const char rep_min[] = static void strings. struct eptrblock *prev; studied, there may be a bitmap of possible first characters. */ subject points to the subject string subject if the requested. subpattern - to break infinite loops. */ subpattern, so as to detect when an empty string has been matched by a subsequent match. */ such there are (offset_top records the completed total) so we just have supersede any condition above with which it is incompatible. switch (*ecode) switch (ctype) switch (op) test once at the start (i.e. keep it out of the loop). */ than 16 values to store; otherwise malloc is used. A problem is what to do than the number of characters left in the string, so the match fails. that "continue" in the code above comes out to here to repeat the main that changed within the bracket before re-running it, so check the next that it may occur zero times. It may repeat infinitely, or not at all - the assertion is true. Lookbehind assertions have an OP_REVERSE item at the the closing ket. When match() is called in other circumstances, we don't add to the code for a repeated single character, but I haven't found a nice way of the current subject position in the working slot at the top of the vector. We the expression and advancing one matching character if failing, up to the the external pcre header. */ the file Tech.Notes for some information on the internals. the final argument TRUE causes it to stop at the end of an assertion. */ the group. */ the length of the reference string explicitly rather than passing the the loop runs just once. */ the minimum number of bytes before we start. */ the number from a dummy opcode at the start. */ the point in the subject string is not moved back. Thus there can never be the pointer while it matches the class. */ the same bracket. the stack. */ the start hasn't passed this character yet. */ the subject. */ there were too many extractions, set the return code to zero. In the case this level is identical to the lookahead case. */ this makes a huge difference to execution time when there aren't many brackets those back references that we can. In this case there need not be overflow time taken, but character matching *is* what this is all about... */ to save all the potential data. There may be up to 99 such values, which to that for character classes, but repeated for efficiency. Then obey two branches. If the condition is false, skipping the first branch takes us typedef struct eptrblock unless PCRE_CASELESS was given or the casing state changes within the regex. unlimited repeats that aren't going to match. We don't know what the state of unsigned long int ims = 0; unsigned long int ims; unsigned long int original_ims = ims; /* Save for resetting on ')' */ up quickly if there are fewer than the minimum number of characters left in using_temporary_offsets = TRUE; values of the final offsets, in case they were set by a previous iteration of we just need to set up the whole thing as substring 0 before returning. If where we had to get some local store to hold offsets for backreferences, copy while (!anchored && while (*ecode == OP_ALT) while (*ecode == OP_ALT); while (*next == OP_ALT); while (--iptr >= iend) while (eptr >= pp) while (iptr < iend) while (length-- > 0) while (p < end_subject) while (start_match < end_subject && while (start_match < end_subject && *start_match != first_char) while (start_match < end_subject && start_match[-1] != '\n') while (start_match < end_subject) { {0, 0, 0, 0, 1, 1}; {0, 0, 1, 1, 0, 0}; } /* End of main loop */ } kbuild-3686/src/oldsed/testsuite/tst-regex2.c0000664000175000017500000001044115053010105021144 0ustar locutuslocutus#include #include #include #include #include #include #include #include int main (int argc, char *argv[]) { struct stat st; static const char *pat[] = { ".?.?.?.?.?.?.?argc", "(.?)(.?)(.?)(.?)(.?)(.?)(.?)argc", "((((((((((.?))))))))))((((((((((.?))))))))))((((((((((.?))))))))))" "((((((((((.?))))))))))((((((((((.?))))))))))((((((((((.?))))))))))" "((((((((((.?))))))))))argc" }; size_t len; int fd; int testno, i, j, k, l; char *string; char *buf; if (argc < 2) abort (); fd = open (argv[1], O_RDONLY); if (fd < 0) { printf ("Couldn't open %s: %s\n", argv[1], strerror (errno)); abort (); } if (fstat (fd, &st) < 0) { printf ("Couldn't fstat %s: %s\n", argv[1], strerror (errno)); abort (); } buf = malloc (st.st_size + 1); if (buf == NULL) { printf ("Couldn't allocate buffer: %s\n", strerror (errno)); abort (); } if (read (fd, buf, st.st_size) != (ssize_t) st.st_size) { printf ("Couldn't read %s", argv[1]); abort (); } close (fd); buf[st.st_size] = '\0'; string = buf; len = st.st_size; for (testno = 0; testno < 4; ++testno) for (i = 0; i < sizeof (pat) / sizeof (pat[0]); ++i) { regex_t rbuf; struct re_pattern_buffer rpbuf; int err; printf ("test %d pattern %d", testno, i); if (testno < 2) { err = regcomp (&rbuf, pat[i], REG_EXTENDED | (testno ? REG_NOSUB : 0)); if (err != 0) { char errstr[300]; putchar ('\n'); regerror (err, &rbuf, errstr, sizeof (errstr)); puts (errstr); return err; } } else { const char *s; re_set_syntax (RE_SYNTAX_POSIX_EGREP | (testno == 3 ? RE_NO_SUB : 0)); memset (&rpbuf, 0, sizeof (rpbuf)); s = re_compile_pattern (pat[i], strlen (pat[i]), &rpbuf); if (s != NULL) { printf ("\n%s\n", s); abort (); } /* Just so that this can be tested with earlier glibc as well. */ if (testno == 3) rpbuf.no_sub = 1; } if (testno < 2) { regmatch_t pmatch[71]; err = regexec (&rbuf, string, 71, pmatch, 0); if (err == REG_NOMATCH) { puts ("\nregexec failed"); abort (); } if (testno == 0) { if (pmatch[0].rm_eo != pmatch[0].rm_so + 11 || pmatch[0].rm_eo > len || string + pmatch[0].rm_so >= strchr (string, 'R') || strncmp (string + pmatch[0].rm_so, "n (int argc", sizeof "n (int argc" - 1) != 0) { puts ("\nregexec without REG_NOSUB did not find the correct match"); abort (); } if (i > 0) for (j = 0, l = 1; j < 7; ++j) for (k = 0; k < (i == 1 ? 1 : 10); ++k, ++l) if (pmatch[l].rm_so != pmatch[0].rm_so + j || pmatch[l].rm_eo != pmatch[l].rm_so + 1) { printf ("\npmatch[%d] incorrect\n", l); abort (); } } } else { struct re_registers regs; int match; memset (®s, 0, sizeof (regs)); match = re_search (&rpbuf, string, len, 0, len, ®s); if (match < 0) { puts ("\nre_search failed"); abort (); } if (match + 11 > len || string + match >= strchr (string, 'R') || strncmp (string + match, "n (int argc", sizeof "n (int argc" - 1) != 0) { puts ("\nre_search did not find the correct match"); abort (); } if (testno == 2) { if (regs.num_regs != 2 + (i == 0 ? 0 : i == 1 ? 7 : 70)) { printf ("\nincorrect num_regs %d\n", regs.num_regs); abort (); } if (regs.start[0] != match || regs.end[0] != match + 11) { printf ("\nincorrect regs.{start,end}[0] = { %d, %d}\n", regs.start[0], regs.end[0]); abort (); } if (regs.start[regs.num_regs - 1] != -1 || regs.end[regs.num_regs - 1] != -1) { puts ("\nincorrect regs.{start,end}[num_regs - 1]"); abort (); } if (i > 0) for (j = 0, l = 1; j < 7; ++j) for (k = 0; k < (i == 1 ? 1 : 10); ++k, ++l) if (regs.start[l] != match + j || regs.end[l] != regs.start[l] + 1) { printf ("\nregs.{start,end}[%d] incorrect\n", l); abort (); } } } putchar ('\n'); if (testno < 2) regfree (&rbuf); else regfree (&rpbuf); } exit (0); } kbuild-3686/src/oldsed/testsuite/8to7.good0000664000175000017500000000123515053010105020450 0ustar locutuslocutus\344\306\244\342\244\350 \244\337\344\306\273\375\244\301$ \267\241\266\372\244\342\244\350 \244\337\267\241\266\372\273\375\244\ \301$ \244\263\244\316\265\326\244\313 \272\332\305\246\244\336\244\271\273\ \371$ \262\310\264\326\244\253\244\312 \271\360\244\351\244\265\244\315$ \244\275\244\351\244\337\244\304 \302\347\317\302\244\316\271\361\244\ \317$ \244\252\244\267\244\343\244\312\244\331\244\306 \244\357\244\354\244\ \263\244\275\265\357\244\354$ \244\267\244\255\244\312\244\331\244\306 \244\357\244\354\244\263\244\ \275 \272\302\244\273$ \244\357\244\313\244\263\244\275\244\317 \271\360\244\351\244\341$ \262\310\244\362\244\342\314\276\244\362\244\342$ kbuild-3686/src/oldsed/testsuite/numsub2.good0000664000175000017500000000000015053010105021227 0ustar locutuslocutuskbuild-3686/src/oldsed/testsuite/modulo.good0000664000175000017500000000040515053010105021144 0ustar locutuslocutus1 s%@CFLAGS@%%g 3 s%@CXXFLAGS@%-x c++%g 5 s%@LDFLAGS@%-L/usr/lib%g 7 s%@exec_prefix@%%g 9 s%@RANLIB@%$RANLIB%g 11 s%@CPP@%$CPP%g 13 s%@XINCLUDES@%$XINCLUDES%g 15 s%@XPROGS@%$XPROGS%g 17 s%@TCLLIB@%$TCLLIB%g 19 s%@TKLIB@%$TKLIB%g 21 s%@EVENT_TYPE@%$EVENT_TYPE%g kbuild-3686/src/oldsed/testsuite/sep.good0000664000175000017500000000001015053010105020424 0ustar locutuslocutus /// // kbuild-3686/src/oldsed/testsuite/wrtout1.good0000664000175000017500000000022015053010105021265 0ustar locutuslocutusFacts are simple and facts are straight Facts are lazy and facts are late Facts all come with points of view Facts don't do what I want them to kbuild-3686/src/oldsed/testsuite/linecnt.good0000664000175000017500000000414015053010105021301 0ustar locutuslocutus1 A dialogue on poverty 2 3 On the night when the rain beats, 4 Driven by the wind, 5 On the night when the snowflakes mingle 6 With a sleety rain, 7 I feel so helplessly cold. 8 I nibble at a lump of salt, 9 Sip the hot, oft-diluted dregs of _sake_; 10 And coughing, snuffling, 11 And stroking my scanty beard, 12 I say in my pride, 13 "There's none worthy, save I!" 14 But I shiver still with cold. 15 I pull up my hempen bedclothes, 16 Wear what few sleeveless clothes I have, 17 But cold and bitter is the night! 18 As for those poorer than myself, 19 Their parents must be cold and hungry, 20 Their wives and children beg and cry. 21 Then, how do you struggle through life? 22 23 Wide as they call the heaven and earth, 24 For me they have shrunk quite small; 25 Bright though they call the sun and moon, 26 They never shine for me. 27 Is it the same with all men, 28 Or for me alone? 29 By rare chance I was born a man 30 And no meaner than my fellows, 31 But, wearing unwadded sleeveless clothes 32 In tatters, like weeds waving in the sea, 33 Hanging from my shoulders, 34 And under the sunken roof, 35 Within the leaning walls, 36 Here I lie on straw 37 Spread on bare earth, 38 With my parents at my pillow, 39 And my wife and children at my feet, 40 All huddled in grief and tears. 41 No fire sends up smoke 42 At the cooking-place, 43 And in the cauldron 44 A spider spins its web. 45 With not a grain to cook, 46 We moan like the night thrush. 47 Then, "to cut," as the saying is, 48 "The ends of what is already too short," 49 The village headman comes, 50 With rod in hand, to our sleeping place, 51 Growling for his dues. 52 Must it be so hopeless -- 53 The way of this world? 54 55 -- Yamanoue Okura kbuild-3686/src/oldsed/testsuite/appquit.inp0000664000175000017500000000000415053010105021161 0ustar locutuslocutusdoh kbuild-3686/src/oldsed/testsuite/newjis.sed0000664000175000017500000000002315053010105020763 0ustar locutuslocutuss/$?$1$,$-/M9JX6I/ kbuild-3686/src/oldsed/testsuite/y-newline.sed0000664000175000017500000000002415053010105021374 0ustar locutuslocutusH G y/Ss\nYy/yY$sS/ kbuild-3686/src/oldsed/testsuite/enable.good0000664000175000017500000000005415053010105021073 0ustar locutuslocutustargets x11-testing wollybears-in-minnesota kbuild-3686/src/oldsed/testsuite/Makefile.am0000664000175000017500000000635015053010105021034 0ustar locutuslocutusCLEANFILES = tmp* core *.core $(EXTRA_PROGRAMS) *.*out *.log TESTS = $(check_PROGRAMS) $(SEDTESTS) SEDTESTS = LDADD = ../lib/libsed.a noinst_HEADERS = testcases.h ptestcases.h AM_CPPFLAGS = -I../lib if TEST_REGEX check_PROGRAMS = bug-regex7 \ bug-regex8 bug-regex9 bug-regex10 bug-regex11 bug-regex12 \ bug-regex13 bug-regex14 bug-regex15 bug-regex16 bug-regex21 \ tst-pcre tst-boost runtests runptests tst-rxspencer tst-regex2 SEDTESTS += space endif SEDTESTS += \ appquit enable sep inclib 8bit newjis xabcx dollar noeol noeolw \ modulo numsub numsub2 numsub3 numsub4 numsub5 0range bkslashes \ head madding mac-mf empty xbxcx xbxcx3 recall recall2 xemacs \ fasts uniq manis khadafy linecnt eval distrib 8to7 y-bracket \ y-newline allsub cv-vars classes middle bsd stdin flipcase \ insens subwrite writeout readin \ help version file quiet \ factor binary3 binary2 binary dc TESTS_ENVIRONMENT = MAKE="$(MAKE)" VERSION="$(VERSION)" $(srcdir)/runtest EXTRA_DIST = \ PCRE.tests BOOST.tests SPENCER.tests \ runtest Makefile.tests \ 0range.good 0range.inp 0range.sed \ 8bit.good 8bit.inp 8bit.sed \ 8to7.good 8to7.inp 8to7.sed \ allsub.good allsub.inp allsub.sed \ appquit.good appquit.inp appquit.sed \ binary.good binary.inp binary.sed binary2.sed binary3.sed \ bkslashes.good bkslashes.inp bkslashes.sed \ bsd.good bsd.sh \ cv-vars.good cv-vars.inp cv-vars.sed \ classes.good classes.inp classes.sed \ dc.good dc.inp dc.sed \ distrib.good distrib.inp distrib.sed distrib.sh \ dollar.good dollar.inp dollar.sed \ empty.good empty.inp empty.sed \ enable.good enable.inp enable.sed \ eval.good eval.inp eval.sed \ factor.good factor.inp factor.sed \ fasts.good fasts.inp fasts.sed \ flipcase.good flipcase.inp flipcase.sed \ head.good head.inp head.sed \ inclib.good inclib.inp inclib.sed \ insens.good insens.inp insens.sed \ khadafy.good khadafy.inp khadafy.sed \ linecnt.good linecnt.inp linecnt.sed \ space.good space.inp space.sed \ mac-mf.good mac-mf.inp mac-mf.sed \ madding.good madding.inp madding.sed \ manis.good manis.inp manis.sed \ middle.good middle.sed middle.inp \ modulo.good modulo.sed modulo.inp \ newjis.good newjis.inp newjis.sed \ noeol.good noeol.inp noeol.sed \ noeolw.good noeolw.1good noeolw.2good noeolw.sed \ numsub.good numsub.inp numsub.sed \ numsub2.good numsub2.inp numsub2.sed \ numsub3.good numsub3.inp numsub3.sed \ numsub4.good numsub4.inp numsub4.sed \ numsub5.good numsub5.inp numsub5.sed \ readin.good readin.in2 readin.inp readin.sed \ recall.good recall.inp recall.sed \ recall2.good recall2.inp recall2.sed \ sep.good sep.inp sep.sed \ subwrite.inp subwrite.sed subwrt1.good subwrt2.good \ uniq.good uniq.inp uniq.sed \ version.gin \ writeout.inp writeout.sed wrtout1.good wrtout2.good \ xabcx.good xabcx.inp xabcx.sed \ xbxcx.good xbxcx.inp xbxcx.sed \ xbxcx3.good xbxcx3.inp xbxcx3.sed \ xemacs.good xemacs.inp xemacs.sed \ y-bracket.good y-bracket.sed y-bracket.inp \ y-newline.good y-newline.sed y-newline.inp clean-local: test x$(srcdir) = x. || rm -f readin.in2 eval.in2 # automake makes `check' depend on $(TESTS). Declare # dummy targets for $(TESTS) so that make does not complain. .PHONY: $(SEDTESTS) $(SEDTESTS): kbuild-3686/src/oldsed/testsuite/bkslashes.sed0000664000175000017500000000003415053010105021445 0ustar locutuslocutus# bug in sed 4.0b s/$/\\\ / kbuild-3686/src/oldsed/testsuite/numsub5.inp0000664000175000017500000000000215053010105021072 0ustar locutuslocutusz kbuild-3686/src/oldsed/testsuite/numsub.inp0000664000175000017500000000021615053010105021014 0ustar locutuslocutusfoo foo fo oo f oo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo fo oo f oo foo foo foo foo foo foo foo foo foo foo foo foo foo kbuild-3686/src/oldsed/testsuite/8bit.sed0000664000175000017500000000125515053010105020342 0ustar locutuslocutus# The first poem from the Man'yoshu. I like Hitomaro's poems better # but I couldn't find a copy of any of them in Japanese. This version # of this poem is from $BNc2r8E8l<-E5(B($BBh;0HG(B)$B;0>JF2(B. # # Speaking of Hitomaro, here is the english translation of one of my # favorites. I just know that everyone reading these test cases wants # to see this. # # In the autumn mountains # The yellow leaves are so thick. # Alas, how shall I seek my love # Who has wandered away? # # I see the messenger come # As the yellow leaves are falling. # Oh, well I remember # How on such a day we used to meet-- # My lover and I! # -- Kakinomoto Hitomaro # s/ÂçÏÂ/ÆüËÜ/ kbuild-3686/src/oldsed/testsuite/xemacs.good0000664000175000017500000000504015053010105021125 0ustar locutuslocutus#Makefile.in generated automatically by automake 1.5 from Makefile.am. #Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 #Free Software Foundation, Inc. #This Makefile.in is free software; the Free Software Foundation #gives unlimited permission to copy and/or distribute it, #with or without modifications, as long as this notice is preserved. #This program is distributed in the hope that it will be useful, #but WITHOUT ANY WARRANTY, to the extent permitted by law; without #even the implied warranty of MERCHANTABILITY or FITNESS FOR A #PARTICULAR PURPOSE. "@SET_MAKE@" #Automake requirements "SHELL = @SHELL@" "PACKAGE = sed" "EXTRA_DIST = BUGS THANKS README.boot bootstrap.sh dc.sed autogen \\" " m4/codeset.m4 m4/gettext.m4 m4/iconv.m4 m4/lcmessage.m4 \\" " m4/getline.m4 m4/glibc21.m4 m4/isc-posix.m4 m4/progtest.m4 \\" " m4/obstack.m4" "subdir = ." "ACLOCAL_M4 = $(top_srcdir)/aclocal.m4" "mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs" "CONFIG_HEADER = config.h" "CONFIG_CLEAN_FILES = bootstrap.sh intl/Makefile" "DIST_SOURCES =" "DATA = $(noinst_DATA)" "HEADERS = $(noinst_HEADERS)" "RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \\" " uninstall-info-recursive all-recursive install-data-recursive \\" " install-exec-recursive installdirs-recursive install-recursive \\" " uninstall-recursive check-recursive installcheck-recursive" "DIST_COMMON = README $(noinst_HEADERS) ./stamp-h.in ABOUT-NLS AUTHORS \\" " COPYING ChangeLog INSTALL Makefile.am Makefile.in NEWS THANKS \\" " TODO acconfig.h aclocal.m4 bootstrap.sh.in config.guess \\" " config.sub config_h.in configure configure.ac depcomp \\" " install-sh missing mkinstalldirs" "DIST_SUBDIRS = $(SUBDIRS)" "all: config.h" " $(MAKE) $(AM_MAKEFLAGS) all-recursive" ".SUFFIXES:" "$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)" " cd $(top_srcdir) && \\" " $(AUTOMAKE) --gnu Makefile" "Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status" " cd $(top_builddir) && \\" " CONFIG_HEADERS= CONFIG_LINKS= \\" " CONFIG_FILES=$@ $(SHELL) ./config.status" "$(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)" " $(SHELL) ./config.status --recheck" "$(srcdir)/configure: $(srcdir)/configure.ac $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)" " cd $(srcdir) && $(AUTOCONF)" "$(ACLOCAL_M4): configure.ac m4/codeset.m4 m4/getline.m4 m4/gettext.m4 m4/glibc21.m4 m4/iconv.m4 m4/isc-posix.m4 m4/lcmessage.m4 m4/obstack.m4 m4/progtest.m4" " cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)" "config.h: stamp-h"kbuild-3686/src/oldsed/testsuite/newjis.inp0000664000175000017500000000013415053010105021001 0ustar locutuslocutus$B$H$J$j$N$?$1$,$-$K(B $B$?$F$+$1$?$N$O(B $B$?$F$+$1$?$+$C$?$+$i(B $B$?$F$+$1$?!#(B kbuild-3686/src/oldsed/testsuite/Makefile.tests0000664000175000017500000001153515053010105021602 0ustar locutuslocutus# Testsuite makefile for GNU sed SHELL = /bin/sh # These are only fallback values. They are usually overridden by runtest. srcdir = . SED = ../sed/sed SEDENV = LC_ALL=C $(TIME) #TIME=time CMP=cmp RM=rm -f enable sep inclib 8bit 8to7 newjis xabcx dollar noeol bkslashes \ numsub head madding mac-mf empty xbxcx xbxcx3 recall recall2 xemacs \ appquit fasts uniq manis linecnt khadafy allsub flipcase space modulo \ y-bracket y-newline:: $(SEDENV) $(SED) -f $(srcdir)/$@.sed \ < $(srcdir)/$@.inp > $@.out $(CMP) $(srcdir)/$@.good $@.out @$(RM) $@.out 0range:: $(SEDENV) $(SED) -s -f $(srcdir)/$@.sed < $(srcdir)/$@.inp > $@.out $(CMP) $(srcdir)/$@.good $@.out @$(RM) $@.out # This checks for a bug in 3.02 and 3.02.80 stdin:: ($(SEDENV) $(SED) d; $(SEDENV) $(SED) G) < $(srcdir)/numsub.inp > $@.1out $(SEDENV) cat $(srcdir)/numsub.inp | ($(SEDENV) $(SED) d; $(SEDENV) $(SED) G) > $@.2out $(CMP) $@.1out $@.2out @$(RM) $@.1out $@.2out cv-vars classes middle dc distrib factor numsub2 numsub3 numsub4 numsub5 \ insens:: $(SEDENV) $(SED) -n -f $(srcdir)/$@.sed < $(srcdir)/$@.inp > $@.out $(CMP) $(srcdir)/$@.good $@.out @$(RM) $@.out noeolw:: $(SEDENV) $(SED) -n -f $(srcdir)/$@.sed \ $(srcdir)/noeol.inp $(srcdir)/noeol.inp > $@.out $(CMP) $(srcdir)/$@.good $@.out $(CMP) $(srcdir)/$@.1good $@.1out $(CMP) $(srcdir)/$@.2good $@.2out @$(RM) $@.1out $@.2out $@.out subwrite:: $(SEDENV) $(SED) -f $(srcdir)/$@.sed < $(srcdir)/$@.inp > $@.1out $(CMP) $(srcdir)/subwrt1.good $@.1out $(CMP) $(srcdir)/subwrt2.good $@.wout @$(RM) $@.1out $@.wout bsd:: $(SEDENV) sh $(srcdir)/$@.sh '$(SED)' bsd.out $(CMP) $(srcdir)/$@.good $@.out @$(RM) $@.out writeout:: $(SEDENV) $(SED) -f $(srcdir)/$@.sed < $(srcdir)/$@.inp >$@.1out $(CMP) $(srcdir)/wrtout1.good $@.1out $(CMP) $(srcdir)/wrtout2.good $@.wout @$(RM) $@.1out $@.wout readin.in2: $(srcdir)/readin.in2 cat $(srcdir)/readin.in2 > $@ readin:: readin.in2 $(SEDENV) $(SED) -f $(srcdir)/$@.sed < $(srcdir)/$@.inp >$@.out $(CMP) $(srcdir)/$@.good $@.out @$(RM) $@.out eval.in2: $(srcdir)/eval.inp cat $(srcdir)/eval.inp > $@ eval:: eval.in2 $(SEDENV) $(SED) -f $(srcdir)/$@.sed < $(srcdir)/$@.inp > $@.out $(CMP) $(srcdir)/$@.good $@.out @$(RM) $@.out binary binary2 binary3:: $(SEDENV) $(SED) -n -f $(srcdir)/$@.sed < $(srcdir)/binary.inp >$@.out $(CMP) $(srcdir)/binary.good $@.out @$(RM) $@.out # # cmdlines targets # help:: $(SED) --help | $(SED) '1s/ [^ ]* / sed /' > $@.1out $(SED) 2>&1 | $(SED) '1s/ [^ ]* / sed /' > $@.2out || : $(CMP) $@.1out $@.2out @$(RM) $@.1out $@.2out version:: $(SED) 's^@'VERSION'@^$(VERSION)^' $(srcdir)/version.gin > $@.good $(SEDENV) $(SED) --version > $@.out 2>&1 $(CMP) $@.good $@.out @$(RM) $@.good $@.out file:: $(SEDENV) $(SED) --file=$(srcdir)/newjis.sed \ < $(srcdir)/newjis.inp > $@.out $(CMP) $(srcdir)/newjis.good $@.out @$(RM) $@.out quiet:: $(SEDENV) $(SED) --quiet -f $(srcdir)/cv-vars.sed \ < $(srcdir)/cv-vars.inp > $@.out $(CMP) $(srcdir)/cv-vars.good $@.out @$(RM) $@.out # The following target is not used in super sed builds (only GNU sed) bug-regex7$(EXEEXT) bug-regex8$(EXEEXT) bug-regex9$(EXEEXT) \ bug-regex10$(EXEEXT) bug-regex11$(EXEEXT) bug-regex12$(EXEEXT) \ bug-regex13$(EXEEXT) bug-regex14$(EXEEXT) bug-regex15$(EXEEXT) bug-regex16$(EXEEXT) \ bug-regex21$(EXEEXT) runtests$(EXEEXT) runptests$(EXEEXT):: echo "$(SEDENV) ./$@ > `echo $@ | $(SED) s/$(EXEEXT)$$/.log/`" @$(SEDENV) ./$@ > `echo $@ | $(SED) s/$(EXEEXT)$$/.log/` tst-pcre$(EXEEXT):: $(SEDENV) ./tst-pcre $(srcdir)/PCRE.tests > tst-pcre.log tst-boost$(EXEEXT):: $(SEDENV) ./tst-boost $(srcdir)/BOOST.tests > tst-boost.log tst-rxspencer$(EXEEXT):: $(SEDENV) ./tst-rxspencer $(srcdir)/SPENCER.tests > tst-spencer.log tst-regex2$(EXEEXT):: $(SEDENV) ./tst-regex2 $(srcdir)/tst-regex2.c > tst-regex2.log # The following target is not used in GNU sed builds (only super-sed) pcretest$(EXEEXT):: $(SEDENV) ./pcretest $(srcdir)/pcre1.inp pcre1.out $(CMP) $(srcdir)/pcre1.good pcre1.out #$(SEDENV) ./pcretest -p $(srcdir)/pcre1.inp pcre1p.out #$(CMP) $(srcdir)/pcre1p.good pcre1p.out $(SEDENV) ./pcretest -P $(srcdir)/pcre2.inp pcre2.out $(CMP) $(srcdir)/pcre2.good pcre2.out $(SEDENV) ./pcretest -P -p $(srcdir)/pcre2.inp pcre2p.out $(CMP) $(srcdir)/pcre2p.good pcre2p.out $(SEDENV) ./pcretest $(srcdir)/pcre3.inp pcre3.out $(CMP) $(srcdir)/pcre3.good pcre3.out $(SEDENV) ./pcretest -p $(srcdir)/pcre3.inp pcre3p.out $(CMP) $(srcdir)/pcre3p.good pcre3p.out @$(RM) pcre*.out .PHONY: \ bug-regex7$(EXEEXT) bug-regex8$(EXEEXT) bug-regex9$(EXEEXT) \ bug-regex10$(EXEEXT) bug-regex11$(EXEEXT) bug-regex12$(EXEEXT) \ bug-regex13$(EXEEXT) bug-regex14$(EXEEXT) bug-regex15$(EXEEXT) bug-regex16$(EXEEXT) \ bug-regex21$(EXEEXT) runtests$(EXEEXT) runptests$(EXEEXT) tst-regex2$(EXEEXT) \ tst-pcre$(EXEEXT) tst-boost$(EXEEXT) tst-rxspencer$(EXEEXT) pcretest$(EXEEXT) kbuild-3686/src/oldsed/testsuite/y-newline.good0000664000175000017500000000006315053010105021554 0ustar locutuslocutusAre Sou Yure (S/n)? [S] $$Are Sou Yure (S/n)? [S] kbuild-3686/src/oldsed/testsuite/cv-vars.good0000664000175000017500000000023015053010105021222 0ustar locutuslocutus: ${_cv_='emptyvar'} : ${ac_cv_prog_RANLIB='/usr/bin/ranlib'} : ${ac_cv_prog_CC='/usr/unsupported/\ \ /lib/_cv_/cc'} : ${ac_cv_prog_CPP='/usr/bin/cpp'} kbuild-3686/src/oldsed/testsuite/bkslashes.good0000664000175000017500000000000415053010105021617 0ustar locutuslocutusa\ kbuild-3686/src/oldsed/testsuite/binary3.sed0000664000175000017500000001204615053010105021043 0ustar locutuslocutus# A kind of clone of dc geared towards binary operations. # by Paolo Bonzini # # commands available: # conversion commands # b convert decimal to binary # d convert binary to decimal # # arithmetic commands # < shift left binary by decimal number of bits (11 3< gives 11000) # > shift right binary by decimal number of bits (1011 2> gives 10) # & binary AND (between two binary operands) # | binary OR (between two binary operands) # ^ binary XOR (between two binary operands) # ~ binary NOT (between one binary operand) # # stack manipulation commands # c clear stack # P pop stack top # D duplicate stack top # x exchange top two elements # r rotate stack counter-clockwise (second element becomes first) # R rotate stack clockwise (last element becomes first) # # other commands # l print stack (stack top is first) # p print stack top # q quit, print stack top if any (cq is quiet quit) # # The only shortcoming is that you'd better not attempt conversions of # values above 1000 or so. # # This version keeps the stack and the current command in hold space and # the commands in pattern space; it is just a bit slower than binary2.sed # but more size optimized for broken seds which have a 199-command limit # (though binary2.sed does not have this much). # # -------------------------------------------------------------------------- # This was actually used in a one-disk distribution of Linux to compute # netmasks as follows (1 parameter => compute netmask e.g. 24 becomes # 255.255.255.0; 2 parameters => given host address and netmask compute # network and broadcast addresses): # # if [ $# = 1 ]; then # OUTPUT='$1.$2.$3.$4' # set 255.255.255.255 $1 # else # OUTPUT='$1.$2.$3.$4 $5.$6.$7.$8' # fi # # if [ `expr $2 : ".*\\."` -gt 0 ]; then # MASK="$2 br b8dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP # | DDD 24>dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP # " | sed -f binary.sed` # # eval echo $OUTPUT # -------------------------------------------------------------------------- :cmd s/^[\n\t ]*// s/^#.*// /^$/ { $b quit N t cmd } /^[0-9][0-9]*/ { G h s/^[0-9][0-9]* *\([^\n]*\).*/\1/ x s/^\([0-9][0-9]*\)[^\n]*/\1/ x t cmd } /^[^DPxrRcplqbd&|^~<>]/bbad H x s/\(\n[^\n]\)[^\n]*$/\1/ /D$/ s/^[^\n]*\n/&&/ /P$/ s/^[^\n]*\n// /x$/ s/^\([^\n]*\n\)\([^\n]*\n\)/\2\1/ /r$/ s/^\([^\n]*\n\)\(.*\)\(..\)/\2\1\3/ /R$/ s/^\(.*\n\)\([^\n]*\n\)\(..\)/\2\1\3/ /c$/ s/.*// /p$/ P /l$/ { s/...$// p t cmd } /q$/ { :quit /.../P d } /b$/ { # Decimal to binary via analog form s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/ :d2bloop1 s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/ t d2bloop1 s/-;9876543210aaaaaaaaa/;a01!/ :d2bloop2 s/\(a*\)\1\(a\{0,1\}\)\(;\2.\(.\)[^!]*!\)/\1\3\4/ /^a/b d2bloop2 s/[^!]*!// } /d$/ { # Binary to decimal via analog form s/^\([^\n]*\)/-&;10a/ :b2dloop1 s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\(a*\)\)/\1\1\4-\3/ t b2dloop1 s/-;10a/;aaaaaaaaa0123456789!/ :b2dloop2 s/\(a*\)\1\1\1\1\1\1\1\1\1\(a\{0,9\}\)\(;\2.\{9\}\(.\)[^!]*!\)/\1\3\4/ /^a/b b2dloop2 s/[^!]*!// } /&$/ { # Binary AND s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-111 01000/ :andloop s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/ t andloop s/^0*\([^-]*\)-[^\n]*/\1/ s/^\n/0&/ } /\^$/ { # Binary XOR s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 01101/ b orloop } /|$/ { # Binary OR s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 10111/ :orloop s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/ t orloop s/\([^-]*\)-\([^-]*\)-\([^-]*\)-[^\n]*/\2\3\1/ } /~$/ { # Binary NOT s/^\(.\)\([^\n]*\n\)/\1-010-\2/ :notloop s/\(.\)-0\{0,1\}\1\(.\)0\{0,1\}-\([01\n]\)/\2\3-010-/ t notloop # If result is 00001..., \3 does not match (it looks for -10) and we just # remove the table and leading zeros. If result is 0000...0, \3 matches # (it looks for -0), \4 is a zero and we leave a lone zero as top of the # stack. s/0*\(1\{0,1\}\)\([^-]*\)-\(\1\(0\)\)\{0,1\}[^-]*-/\4\1\2/ } /<$/ { # Left shift, convert to analog and add a binary digit for each analog digit s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/ :lshloop1 s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/ t lshloop1 s/^\(a*\)-;9876543210aaaaaaaaa\n\([^\n]*\)/\2\1/ s/a/0/g } />$/ { # Right shift, convert to analog and remove a binary digit for each analog digit s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/ :rshloop1 s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/ t rshloop1 s/^\(a*\)-;9876543210aaaaaaaaa\n\([^\n]*\)/\2\1/ :rshloop2 s/.a// s/^aa*/0/ /a\n/b rshloop2 } s/..$// x :bad s/^.// tcmd kbuild-3686/src/oldsed/testsuite/modulo.sed0000664000175000017500000000000715053010105020765 0ustar locutuslocutus0~2d;= kbuild-3686/src/oldsed/testsuite/binary.sed0000664000175000017500000001141115053010105020753 0ustar locutuslocutus# A kind of clone of dc geared towards binary operations. # by Paolo Bonzini # # commands available: # conversion commands # b convert decimal to binary # d convert binary to decimal # # arithmetic commands # < shift left binary by decimal number of bits (11 3< gives 11000) # > shift right binary by decimal number of bits (1011 2> gives 10) # & binary AND (between two binary operands) # | binary OR (between two binary operands) # ^ binary XOR (between two binary operands) # ~ binary NOT (between one binary operand) # # stack manipulation commands # c clear stack # P pop stack top # D duplicate stack top # x exchange top two elements # r rotate stack counter-clockwise (second element becomes first) # R rotate stack clockwise (last element becomes first) # # other commands # l print stack (stack top is first) # p print stack top # q quit, print stack top if any (cq is quiet quit) # # The only shortcoming is that you'd better not attempt conversions of # values above 1000 or so. # # This version does everything in pattern space (a la dc.sed). # -------------------------------------------------------------------------- # This was actually used in a one-disk distribution of Linux to compute # netmasks as follows (1 parameter => compute netmask e.g. 24 becomes # 255.255.255.0; 2 parameters => given host address and netmask compute # network and broadcast addresses): # # if [ $# = 1 ]; then # OUTPUT='$1.$2.$3.$4' # set 255.255.255.255 $1 # else # OUTPUT='$1.$2.$3.$4 $5.$6.$7.$8' # fi # # if [ `expr $2 : ".*\\."` -gt 0 ]; then # MASK="$2 br b8dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP # | DDD 24>dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP # " | sed -f binary.sed` # # eval echo $OUTPUT # -------------------------------------------------------------------------- 1s/^/%%/ :cmd s/\(.*%%\) *\([0-9][0-9]*\)/\2\ \1/ tcmd s/%% *#.*/%%/ /%%$/ { $b quit N } /^.*%%D/ s/^[^\n]*\n/&&/ /^.*%%P/ s/^[^\n]*\n// /^.*%%x/ s/^\([^\n]*\n\)\([^\n]*\n\)/\2\1/ /^.*%%r/ s/^\([^\n]*\n\)\([^%]*\)/\2\1/ /^.*%%R/ s/^\([^%]*\n\)\([^\n]*\n\)/\2\1/ /^.*%%c/ s/^.*%%/%%/ /^.*%%p/ P /^.*%%l/ { h s/.%%.*// p g } /^.*%%q/ { :quit /^%%/!P d } /^.*%%b/ { # Decimal to binary via analog form s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/ :d2bloop1 s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/ t d2bloop1 s/-;9876543210aaaaaaaaa/;a01!/ :d2bloop2 s/\(a*\)\1\(a\{0,1\}\)\(;\2.\(.\)[^!]*!\)/\1\3\4/ /^a/b d2bloop2 s/[^!]*!// } /^.*%%d/ { # Binary to decimal via analog form s/^\([^\n]*\)/-&;10a/ :b2dloop1 s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\(a*\)\)/\1\1\4-\3/ t b2dloop1 s/-;10a/;aaaaaaaaa0123456789!/ :b2dloop2 s/\(a*\)\1\1\1\1\1\1\1\1\1\(a\{0,9\}\)\(;\2.\{9\}\(.\)[^!]*!\)/\1\3\4/ /^a/b b2dloop2 s/[^!]*!// } /^.*%%&/ { # Binary AND s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-111 01000/ :andloop s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/ t andloop s/^0*\([^-]*\)-[^\n]*/\1/ s/^\n/0&/ } /^.*%%^/ { # Binary XOR s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 01101/ b orloop } /^.*%%|/ { # Binary OR s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 10111/ :orloop s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/ t orloop s/\([^-]*\)-\([^-]*\)-\([^-]*\)-[^\n]*/\2\3\1/ } /^.*%%~/ { # Binary NOT s/^\(.\)\([^\n]*\n\)/\1-010-\2/ :notloop s/\(.\)-0\{0,1\}\1\(.\)0\{0,1\}-\([01\n]\)/\2\3-010-/ t notloop # If result is 00001..., \3 does not match (it looks for -10) and we just # remove the table and leading zeros. If result is 0000...0, \3 matches # (it looks for -0), \4 is a zero and we leave a lone zero as top of the # stack. s/0*\(1\{0,1\}\)\([^-]*\)-\(\1\(0\)\)\{0,1\}[^-]*-/\4\1\2/ } /^.*%%/ { # Right shift, convert to analog and remove a binary digit for each analog digit s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/ :rshloop1 s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/ t rshloop1 s/^\(a*\)-;9876543210aaaaaaaaa\n\([^\n]*\)/\2\1/ :rshloop2 s/.a// s/^aa*/0/ /a\n/b rshloop2 } s/%%./%%/ tcmd kbuild-3686/src/oldsed/testsuite/classes.good0000664000175000017500000000023115053010105021277 0ustar locutuslocutus: ${_cv_='emptyvar'} : ${ac_cv_prog/RANLIB='/usr/bin/ranlib'} : ${ac_cv_prog/CC='/usr/unsupported/\ \ /lib/_cv_/cc'} : ${a/c_cv_prog/CPP='/usr/bin/cpp'} kbuild-3686/src/oldsed/testsuite/tst-rxspencer.c0000664000175000017500000003065015053010105021765 0ustar locutuslocutus/* Regular expression tests. Copyright (C) 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2003. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #ifdef HAVE_MCHECK_H #include #endif #include #include #include #include #include #include static void replace_special_chars (char *str) { for (; (str = strpbrk (str, "NTSZ")) != NULL; ++str) switch (*str) { case 'N': *str = '\n'; break; case 'T': *str = '\t'; break; case 'S': *str = ' '; break; case 'Z': *str = '\0'; break; } } static void glibc_re_syntax (char *str) { char *p, *end = strchr (str, '\0') + 1; /* Replace [[:<:]] with \< and [[:>:]] with \>. */ for (p = str; (p = strstr (p, "[[:")) != NULL; ) if ((p[3] == '<' || p[3] == '>') && strncmp (p + 4, ":]]", 3) == 0) { p[0] = '\\'; p[1] = p[3]; memmove (p + 2, p + 7, end - p - 7); end -= 5; p += 2; } else p += 3; } static char * mb_replace (char *dst, const char c) { switch (c) { /* Replace a with \'a and A with \'A. */ case 'a': *dst++ = '\xc3'; *dst++ = '\xa1'; break; case 'A': *dst++ = '\xc3'; *dst++ = '\x81'; break; /* Replace b with \v{c} and B with \v{C}. */ case 'b': *dst++ = '\xc4'; *dst++ = '\x8d'; break; case 'B': *dst++ = '\xc4'; *dst++ = '\x8c'; break; /* Replace c with \v{d} and C with \v{D}. */ case 'c': *dst++ = '\xc4'; *dst++ = '\x8f'; break; case 'C': *dst++ = '\xc4'; *dst++ = '\x8e'; break; /* Replace d with \'e and D with \'E. */ case 'd': *dst++ = '\xc3'; *dst++ = '\xa9'; break; case 'D': *dst++ = '\xc3'; *dst++ = '\x89'; break; } return dst; } static char * mb_frob_string (const char *str, const char *letters) { char *ret, *dst; const char *src; if (str == NULL) return NULL; ret = malloc (2 * strlen (str) + 1); if (ret == NULL) return NULL; for (src = str, dst = ret; *src; ++src) if (strchr (letters, *src)) dst = mb_replace (dst, *src); else *dst++ = *src; *dst = '\0'; return ret; } /* Like mb_frob_string, but don't replace anything between [: and :], [. and .] or [= and =]. */ static char * mb_frob_pattern (const char *str, const char *letters) { char *ret, *dst; const char *src; int in_class = 0; if (str == NULL) return NULL; ret = malloc (2 * strlen (str) + 1); if (ret == NULL) return NULL; for (src = str, dst = ret; *src; ++src) if (!in_class && strchr (letters, *src)) dst = mb_replace (dst, *src); else { if (!in_class && *src == '[' && strchr (":.=", src[1])) in_class = 1; else if (in_class && *src == ']' && strchr (":.=", src[-1])) in_class = 0; *dst++ = *src; } *dst = '\0'; return ret; } static int check_match (regmatch_t *rm, int idx, const char *string, const char *match, const char *fail) { if (match[0] == '-' && match[1] == '\0') { if (rm[idx].rm_so == -1 && rm[idx].rm_eo == -1) return 0; printf ("%s rm[%d] unexpectedly matched\n", fail, idx); return 1; } if (rm[idx].rm_so == -1 || rm[idx].rm_eo == -1) { printf ("%s rm[%d] unexpectedly did not match\n", fail, idx); return 1; } if (match[0] == '@') { if (rm[idx].rm_so != rm[idx].rm_eo) { printf ("%s rm[%d] not empty\n", fail, idx); return 1; } if (strncmp (string + rm[idx].rm_so, match + 1, strlen (match + 1) ? strlen (match + 1) : 1)) { printf ("%s rm[%d] not matching %s\n", fail, idx, match); return 1; } return 0; } if (rm[idx].rm_eo - rm[idx].rm_so != strlen (match) || strncmp (string + rm[idx].rm_so, match, rm[idx].rm_eo - rm[idx].rm_so)) { printf ("%s rm[%d] not matching %s\n", fail, idx, match); return 1; } return 0; } static int test (const char *pattern, int cflags, const char *string, int eflags, char *expect, char *matches, const char *fail) { regex_t re; regmatch_t rm[10]; int n, ret = 0; n = regcomp (&re, pattern, cflags); if (n != 0) { char buf[500]; if (eflags == -1) { static struct { reg_errcode_t code; const char *name; } codes [] #define C(x) { REG_##x, #x } = { C(NOERROR), C(NOMATCH), C(BADPAT), C(ECOLLATE), C(ECTYPE), C(EESCAPE), C(ESUBREG), C(EBRACK), C(EPAREN), C(EBRACE), C(BADBR), C(ERANGE), C(ESPACE), C(BADRPT) }; int i; for (i = 0; i < sizeof (codes) / sizeof (codes[0]); ++i) if (n == codes[i].code) { if (strcmp (string, codes[i].name)) { printf ("%s regcomp returned REG_%s (expected REG_%s)\n", fail, codes[i].name, string); return 1; } return 0; } printf ("%s regcomp return value REG_%d\n", fail, n); return 1; } regerror (n, &re, buf, sizeof (buf)); printf ("%s regcomp failed: %s\n", fail, buf); return 1; } if (eflags == -1) { regfree (&re); /* The test case file assumes something only guaranteed by the rxspencer regex implementation. Namely that for empty expressions regcomp() return REG_EMPTY. This is not the case for us and so we ignore this error. */ if (strcmp (string, "EMPTY") == 0) return 0; printf ("%s regcomp unexpectedly succeeded\n", fail); return 1; } if (regexec (&re, string, 10, rm, eflags)) { regfree (&re); if (expect == NULL) return 0; printf ("%s regexec failed\n", fail); return 1; } regfree (&re); if (expect == NULL) { printf ("%s regexec unexpectedly succeeded\n", fail); return 1; } if (cflags & REG_NOSUB) return 0; ret = check_match (rm, 0, string, expect, fail); if (matches == NULL) return ret; for (n = 1; ret == 0 && n < 10; ++n) { char *p = NULL; if (matches) { p = strchr (matches, ','); if (p != NULL) *p = '\0'; } ret = check_match (rm, n, string, matches ? matches : "-", fail); if (p) { *p = ','; matches = p + 1; } else matches = NULL; } return ret; } static int mb_test (const char *pattern, int cflags, const char *string, int eflags, char *expect, const char *matches, const char *letters, const char *fail) { char *pattern_mb = mb_frob_pattern (pattern, letters); const char *string_mb = eflags == -1 ? string : mb_frob_string (string, letters); char *expect_mb = mb_frob_string (expect, letters); char *matches_mb = mb_frob_string (matches, letters); int ret = 0; if (!pattern_mb || !string_mb || (expect && !expect_mb) || (matches && !matches_mb)) { printf ("%s %m", fail); ret = 1; } else ret = test (pattern_mb, cflags, string_mb, eflags, expect_mb, matches_mb, fail); free (matches_mb); free (expect_mb); if (string_mb != string) free ((char *) string_mb); free (pattern_mb); return ret; } static int mb_tests (const char *pattern, int cflags, const char *string, int eflags, char *expect, const char *matches) { int ret = 0; int i; char letters[9], fail[20]; /* The tests aren't supposed to work with xdigit, since a-dA-D are hex digits while \'a \'A \v{c}\v{C}\v{d}\v{D}\'e \'E are not. */ if (strstr (pattern, "[:xdigit:]")) return 0; /* XXX: regex ATM handles only single byte equivalence classes. */ if (strstr (pattern, "[[=b=]]")) return 0; for (i = 1; i < 16; ++i) { char *p = letters; if (i & 1) { if (!strchr (pattern, 'a') && !strchr (string, 'a') && !strchr (pattern, 'A') && !strchr (string, 'A')) continue; *p++ = 'a', *p++ = 'A'; } if (i & 2) { if (!strchr (pattern, 'b') && !strchr (string, 'b') && !strchr (pattern, 'B') && !strchr (string, 'B')) continue; *p++ = 'b', *p++ = 'B'; } if (i & 4) { if (!strchr (pattern, 'c') && !strchr (string, 'c') && !strchr (pattern, 'C') && !strchr (string, 'C')) continue; *p++ = 'c', *p++ = 'C'; } if (i & 8) { if (!strchr (pattern, 'd') && !strchr (string, 'd') && !strchr (pattern, 'D') && !strchr (string, 'D')) continue; *p++ = 'd', *p++ = 'D'; } *p++ = '\0'; sprintf (fail, "UTF-8 %s FAIL", letters); ret |= mb_test (pattern, cflags, string, eflags, expect, matches, letters, fail); } return ret; } int main (int argc, char **argv) { int ret = 0; char *line = NULL; size_t line_len = 0; ssize_t len; FILE *f; static int test_utf8 = 0; static const struct option options[] = { {"utf8", no_argument, &test_utf8, 1}, {NULL, 0, NULL, 0 } }; #ifdef HAVE_MCHECK_H mtrace (); #endif while (getopt_long (argc, argv, "", options, NULL) >= 0); if (optind + 1 != argc) { fprintf (stderr, "Missing test filename\n"); return 1; } f = fopen (argv[optind], "r"); if (f == NULL) { fprintf (stderr, "Couldn't open %s\n", argv[optind]); return 1; } while ((len = getline (&line, &line_len, f)) > 0) { char *pattern, *flagstr, *string, *expect, *matches, *p; int cflags = REG_EXTENDED, eflags = 0, try_bre_ere = 0; if (line[len - 1] == '\n') line[len - 1] = '\0'; /* Skip comments and empty lines. */ if (*line == '#' || *line == '\0') continue; puts (line); fflush (stdout); pattern = strtok (line, "\t"); if (pattern == NULL) continue; if (strcmp (pattern, "\"\"") == 0) pattern += 2; flagstr = strtok (NULL, "\t"); if (flagstr == NULL) continue; string = strtok (NULL, "\t"); if (string == NULL) continue; if (strcmp (string, "\"\"") == 0) string += 2; for (p = flagstr; *p; ++p) switch (*p) { case '-': break; case 'b': cflags &= ~REG_EXTENDED; break; case '&': try_bre_ere = 1; break; case 'C': eflags = -1; break; case 'i': cflags |= REG_ICASE; break; case 's': cflags |= REG_NOSUB; break; case 'n': cflags |= REG_NEWLINE; break; case '^': eflags |= REG_NOTBOL; break; case '$': eflags |= REG_NOTEOL; break; case 'm': case 'p': case '#': /* Not supported. */ flagstr = NULL; break; } if (flagstr == NULL) continue; replace_special_chars (pattern); glibc_re_syntax (pattern); if (eflags != -1) replace_special_chars (string); expect = strtok (NULL, "\t"); matches = NULL; if (expect != NULL) { replace_special_chars (expect); matches = strtok (NULL, "\t"); if (matches != NULL) replace_special_chars (matches); } if (setlocale (LC_ALL, "C") == NULL) { puts ("setlocale C failed"); ret = 1; } if (test (pattern, cflags, string, eflags, expect, matches, "FAIL") || (try_bre_ere && test (pattern, cflags & ~REG_EXTENDED, string, eflags, expect, matches, "FAIL"))) ret = 1; else if (test_utf8) { if (setlocale (LC_ALL, "cs_CZ.UTF-8") == NULL) { puts ("setlocale cs_CZ.UTF-8 failed"); ret = 1; } else if (test (pattern, cflags, string, eflags, expect, matches, "UTF-8 FAIL") || (try_bre_ere && test (pattern, cflags & ~REG_EXTENDED, string, eflags, expect, matches, "UTF-8 FAIL"))) ret = 1; else if (mb_tests (pattern, cflags, string, eflags, expect, matches) || (try_bre_ere && mb_tests (pattern, cflags & ~REG_EXTENDED, string, eflags, expect, matches))) ret = 1; } } free (line); fclose (f); return ret; } kbuild-3686/src/oldsed/testsuite/factor.inp0000664000175000017500000000002415053010105020756 0ustar locutuslocutus2 3 4 5 8 11 16 143 kbuild-3686/src/oldsed/testsuite/numsub.good0000664000175000017500000000010715053010105021155 0ustar locutuslocutusfoo foo fo oo f oo foo foo foo foo foo foo foo bar foo foo foo foo foo kbuild-3686/src/oldsed/testsuite/runtests.c0000664000175000017500000000572415053010105021037 0ustar locutuslocutus/*********************************************************** Copyright 1995 by Tom Lord All Rights Reserved 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, and that the name of the copyright holder not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Tom Lord DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL TOM LORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ #include #include #include #include #include struct a_test { int expected; const char * pattern; const unsigned char * data; }; static const struct a_test the_tests[] = { #include "testcases.h" {-1, 0, 0} }; static int run_a_test (int id, const struct a_test * t) { static const char * last_pattern = 0; static regex_t r; int err; char errmsg[100]; int x; regmatch_t regs[10]; if (!last_pattern || strcmp (last_pattern, t->pattern)) { if (last_pattern) regfree (&r); last_pattern = t->pattern; err = regcomp (&r, t->pattern, REG_EXTENDED); if (err) { if (t->expected == 2) { puts (" OK."); return 0; } if (last_pattern) regfree (&r); last_pattern = NULL; regerror (err, &r, errmsg, 100); printf (" FAIL: %s.\n", errmsg); return 1; } else if (t->expected == 2) { printf ("test %d\n", id); printf ("pattern \"%s\" successfull compilation not expected\n", t->pattern); return 1; } } err = regexec (&r, t->data, 10, regs, 0); if (err != t->expected) { printf ("test %d\n", id); printf ("pattern \"%s\" data \"%s\" wanted %d got %d\n", t->pattern, t->data, t->expected, err); for (x = 0; x < 10; ++x) printf ("reg %d == (%d, %d) %.*s\n", x, regs[x].rm_so, regs[x].rm_eo, regs[x].rm_eo - regs[x].rm_so, t->data + regs[x].rm_so); return 1; } puts (" OK."); return 0; } int main (int argc, char * argv[]) { int x; int lo; int hi; int res = 0; lo = 0; hi = (sizeof (the_tests) / sizeof (the_tests[0])) - 1; if (argc > 1) { lo = atoi (argv[1]); hi = lo + 1; if (argc > 2) hi = atoi (argv[2]); } for (x = lo; x < hi; ++x) { printf ("#%d:", x); res |= run_a_test (x, &the_tests[x]); } return res != 0; } kbuild-3686/src/oldsed/testsuite/insens.good0000664000175000017500000000001415053010105021140 0ustar locutuslocutus1.2.3 1.2.3 kbuild-3686/src/oldsed/testsuite/eval.inp0000664000175000017500000000005515053010105020433 0ustar locutuslocutus17380: 2 2 5 11 79 abcd cpu abcd cpu kbuild-3686/src/oldsed/testsuite/bug-regex7.c0000664000175000017500000000461115053010105021116 0ustar locutuslocutus/* Test for regs allocation in re_search and re_match. Copyright (C) 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Stepan Kasal , 2002. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include int main (void) { struct re_pattern_buffer regex; struct re_registers regs; const char *s; int match, n; int result = 0; memset (®ex, '\0', sizeof (regex)); regs.start = regs.end = NULL; regs.num_regs = 0; s = re_compile_pattern ("a", 1, ®ex); if (s != NULL) { puts ("failed to compile pattern \"a\""); result = 1; } else { match = re_search (®ex, "baobab", 6, 0, 6, ®s); n = 1; if (match != 1) { printf ("re_search returned %d, expected 1\n", match); result = 1; } else if (regs.num_regs <= n || regs.start[n] != -1 || regs.end[n] != -1) { puts ("re_search failed to fill the -1 sentinel"); result = 1; } } free (regex.buffer); memset (®ex, '\0', sizeof (regex)); s = re_compile_pattern ("\\(\\(\\(a\\)\\)\\)", 13, ®ex); if (s != NULL) { puts ("failed to compile pattern /\\(\\(\\(a\\)\\)\\)/"); result = 1; } else { match = re_match (®ex, "apl", 3, 0, ®s); n = 4; if (match != 1) { printf ("re_match returned %d, expected 1\n", match); result = 1; } else if (regs.num_regs <= n || regs.start[n] != -1 || regs.end[n] != -1) { puts ("re_match failed to fill the -1 sentinel"); result = 1; } } if (result == 0) puts (" -> OK"); return result; } kbuild-3686/src/oldsed/testsuite/insens.inp0000664000175000017500000000001715053010105021001 0ustar locutuslocutusVersion: 1.2.3 kbuild-3686/src/oldsed/testsuite/0range.sed0000664000175000017500000000001115053010105020635 0ustar locutuslocutus0,/aaa/d kbuild-3686/src/oldsed/testsuite/flipcase.good0000664000175000017500000000241215053010105021433 0ustar locutuslocutus09 - 02 - 2002 00.00 Tg La7 La7 - 09 - 02 - 2002 00.00 Brand New Tmc 2 - 09 - 02 - 2002 00.10 Tg1 Notte Rai Uno - 09 - 02 - 2002 00.15 Tg Parlamento Rai Due - 09 - 02 - 2002 00.15 Kung Fu - La Leggenda Continua La7 - 09 - 02 - 2002 00.20 Berserk - La Confessione Di Gatz Italia 1 Cartoon 09 - 02 - 2002 00.20 Tg3 - Tg3 Meteo Rai Tre - 09 - 02 - 2002 00.25 Meteo 2 Rai Due - 09 - 02 - 2002 00.30 Appuntamento Al Cinema Rai Due - 09 - 02 - 2002 00.30 Rai Educational - Mediamente Rai Tre - 09 - 02 - 2002 00.35 Profiler Rai Due - 09 - 02 - 2002 00.35 Stampa Oggi - Che Tempo Fa Rai Uno - 09 - 02 - 2002 00.45 Rai Educational - Babele: Euro Rai Uno - 09 - 02 - 2002 00.45 Bollettino Della Neve Rete 4 News 09 - 02 - 2002 00.50 Studio Aperto - La Giornata Italia 1 News 09 - 02 - 2002 00.50 Bocca A Bocca - 2 Tempo Rete 4 Film 09 - 02 - 2002 01.00 Appuntamento Al Cinema Rai Tre - 09 - 02 - 2002 01.00 Music Non Stop Tmc 2 - 09 - 02 - 2002 01.00 Studio Sport Italia 1 Sport 09 - 02 - 2002 01.00 Tg 5 - Notte Canale 5 News 09 - 02 - 2002 01.05 Fuori Orario. Cose (Mai) Viste Rai Tre - 09 - 02 - 2002 01.15 Rainotte Rai Due - 09 - 02 - 2002 01.15 Sottovoce Rai Uno - 09 - 02 - 2002 01.15 Giochi Olimpici Invernali - Cerimonia Di Apertura Rai Tre - 09 - 02 - 2002 01.17 Italia Interroga Rai Due - kbuild-3686/src/oldsed/testsuite/manis.inp0000664000175000017500000000073115053010105020614 0ustar locutuslocutuss%@CFLAGS@%%g s%@CPPFLAGS@%-I/%g s%@CXXFLAGS@%-x c++%g s%@DEFS@%$DEFS%g s%@LDFLAGS@%-L/usr/lib%g s%@LIBS@%-lgnu -lbfd%g s%@exec_prefix@%%g s%@prefix@%$prefix%g s%@RANLIB@%$RANLIB%g s%@CC@%/usr/local/bin/gcc%g s%@CPP@%$CPP%g s%@XCFLAGS@%$XCFLAGS%g s%@XINCLUDES@%$XINCLUDES%g s%@XLIBS@%$XLIBS%g s%@XPROGS@%$XPROGS%g s%@TCLHDIR@%$TCLHDIR%g s%@TCLLIB@%$TCLLIB%g s%@TKHDIR@%$TKHDIR%g s%@TKLIB@%$TKLIB%g s%@PTY_TYPE@%$PTY_TYPE%g s%@EVENT_TYPE@%$EVENT_TYPE%g s%@SETUID@%$SETUID%g kbuild-3686/src/oldsed/testsuite/numsub.sed0000664000175000017500000000021215053010105020775 0ustar locutuslocutus# the first one matches, the second doesn't 1s/foo/bar/10 2s/foo/bar/20 # The second line should be deleted. ssed 3.55-3.58 do not. t d kbuild-3686/src/oldsed/testsuite/numsub3.inp0000664000175000017500000000000115053010105021067 0ustar locutuslocutus kbuild-3686/src/oldsed/testsuite/manis.good0000664000175000017500000000073115053010105020756 0ustar locutuslocutuss%@CFLAGS@%%g s%@CPPFLAGS@%-I/%g s%@CXXFLAGS@%-x c++%g s%@DEFS@%$DEFS%g s%@LDFLAGS@%-L/usr/lib%g s%@LIBS@%-lgnu -lbfd%g s%@exec_prefix@%%g s%@prefix@%$prefix%g s%@RANLIB@%$RANLIB%g s%@CC@%/usr/local/bin/gcc%g s%@CPP@%$CPP%g s%@XCFLAGS@%$XCFLAGS%g s%@XINCLUDES@%$XINCLUDES%g s%@XLIBS@%$XLIBS%g s%@XPROGS@%$XPROGS%g s%@TCLHDIR@%$TCLHDIR%g s%@TCLLIB@%$TCLLIB%g s%@TKHDIR@%$TKHDIR%g s%@TKLIB@%$TKLIB%g s%@PTY_TYPE@%$PTY_TYPE%g s%@EVENT_TYPE@%$EVENT_TYPE%g s%@SETUID@%$SETUID%g kbuild-3686/src/oldsed/testsuite/readin.good0000664000175000017500000000070115053010105021106 0ustar locutuslocutus``Democracy will not come today, this year, nor ever through compromise and fear. MOO I have as much right as the other fellow has to stand on my two feet and own the land. MOO I tire so of hearing people say let things take their course, tomorrow is another day. MOO I do not need my freedom when I'm dead. MOO I cannot live on tomorrow's bread. MOO Freedom is a strong seed planted in a great need. MOO I live here, too. MOO kbuild-3686/src/oldsed/testsuite/allsub.good0000664000175000017500000000010715053010105021126 0ustar locutuslocutusbar bar fo oo f oo bar bar bar bar bar bar bar bar bar bar bar bar bar kbuild-3686/src/oldsed/testsuite/dc.sed0000664000175000017500000002106615053010105020064 0ustar locutuslocutus#!/bin/sed -nf # dc.sed - an arbitrary precision RPN calculator # Created by Greg Ubben early 1995, late 1996 # # Dedicated to MAC's memory of the IBM 1620 ("CADET") computer. # @(#)GSU dc.sed 1.1 06-Mar-1999 [non-explanatory] # # Examples: # sqrt(2) to 10 digits: echo "10k 2vp" | dc.sed # 20 factorial: echo "[d1-d1 != fractional-bases # SunOS limits: 199/199 commands (though could pack in 10-20 more) # Limitations: scale <= 999; |obase| >= 1; input digits in [0..F] # Completed: 1am Feb 4, 1997 s/^/|P|K0|I10|O10|?~/ : next s/|?./|?/ s/|?#[ -}]*/|?/ /|?!*[lLsS;:<>=]\{0,1\}$/N /|?!*[-+*/%^<>=]/b binop /^|.*|?[dpPfQXZvxkiosStT;:]/b binop /|?[_0-9A-F.]/b number /|?\[/b string /|?l/b load /|?L/b Load /|?[sS]/b save /|?c/ s/[^|]*// /|?d/ s/[^~]*~/&&/ /|?f/ s//&[pSbz0}s\1L\1l{xS\1]dS{xL}/ /|?:/ s/|?:\([^{}]\)/|?~[s}L{s}L{s}L}s\1q]S}S}S{[L}1-d0>}S}l\1s\1L\1l{xS\1]dS{x/ /|?[ ~ cdfxKIOT]/b next /|?\n/b next /|?[pP]/b print /|?k/ s/^\([0-9]\{1,3\}\)\([.~].*|K\)[^|]*/\2\1/ /|?i/ s/^\(-\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}\)\(~.*|I\)[^|]*/\2\1/ /|?o/ s/^\(-\{0,1\}[1-9][0-9]*\.\{0,1\}[0-9]*\)\(~.*|O\)[^|]*/\2\1/ /|?[kio]/b pop /|?t/b trunc /|??/b input /|?Q/b break /|?q/b quit h /|?[XZz]/b count /|?v/b sqrt s/.*|?\([^Y]\).*/\1 is unimplemented/ s/\n/\\n/g l g b next : print /^-\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}~.*|?p/!b Print /|O10|/b Print # Print a number in a non-decimal output base. Uses registers a,b,c,d. # Handles fractional output bases (O<-1 or O>=1), unlike other dc's. # Converts the fraction correctly on negative output bases, unlike # UNIX dc. Also scales the fraction more accurately than UNIX dc. # s,|?p,&KSa0kd[[-]Psa0la-]Sad0>a[0P]sad0=a[A*2+]saOtd0>a1-ZSd[[[[ ]P]sclb1\ !=cSbLdlbtZ[[[-]P0lb-sb]sclb0>c1+]sclb0!c]scdld>cscSdLbP]q]Sb\ [t[1P1-d0bO1!c[A]sbdA=c[B]sbd\ B=c[C]sbdC=c[D]sbdD=c[E]sbdE=c[F]sb]xscLbP]~Sd[dtdZOZ+k1O/Tdsb[.5]*[.1]O\ X^*dZkdXK-1+ktsc0kdSb-[Lbdlb*lc+tdSbO*-lb0!=aldx]dsaxLbsb]sad1!>a[[.]POX\ +sb1[SbO*dtdldx-LbO*dZlb!]\)/0\1/ /^[^~]*~-\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}~/ !s/~[^~]*\(.*|?!*[^!=<>]\)/~0\1/ h /|?\*/b mul /|?\//b div /|?%/b rem /|?^/b exp /|?[+-]/ s/^\(-*\)\([^~]*~\)\(-*\)\([^~]*~\).*|?\(-\{0,1\}\).*/\2\4s\3o\1\3\5/ s/\([^.~]*\)\([^~]*~[^.~]*\)\(.*\)/<\1,\2,\3|=-~.0,123456789<>/ /|?/{ s/^\([<>]\)\(-[^~]*~-.*\1\)\(.\)/\3\2/ s/^\(.\)\(.*|?!*\)\1/\2!\1/ s/|?![^!]\(.\)/&l\1x/ s/[^~]*~[^~]*~\(.*|?\)!*.\(.*\)|=.*/\1\2/ b next } s/\(-*\)\1|=.*/;9876543210;9876543210/ /o-/ s/;9876543210/;0123456789/ s/^>\([^~]*~\)\([^~]*~\)s\(-*\)\(-*o\3\(-*\)\)/>\2\1s\5\4/ s/,\([0-9]*\)\.*\([^,]*\),\([0-9]*\)\.*\([0-9]*\)/\1,\2\3.,\4;0/ : right1 s/,\([0-9]\)\([^,]*\),;*\([0-9]\)\([0-9]*\);*0*/\1,\2\3,\4;0/ t right1 s/.\([^,]*\),~\(.*\);0~s\(-*\)o-*/\1~\30\2~/ : addsub1 s/\(.\{0,1\}\)\(~[^,]*\)\([0-9]\)\(\.*\),\([^;]*\)\(;\([^;]*\(\3[^;]*\)\).*X*\1\(.*\)\)/\2,\4\5\9\8\7\6/ s/,\([^~]*~\).\{10\}\(.\)[^;]\{0,9\}\([^;]\{0,1\}\)[^;]*/,\2\1\3/ # could be done in one s/// if we could have >9 back-refs... /^~.*~;/!b addsub1 : endbin s/.\([^,]*\),\([0-9.]*\).*/\1\2/ G s/\n[^~]*~[^~]*// : normal s/^\(-*\)0*\([0-9.]*[0-9]\)[^~]*/\1\2/ s/^[^1-9~]*~/0~/ b next : mul s/\(-*\)\([0-9]*\)\.*\([0-9]*\)~\(-*\)\([0-9]*\)\.*\([0-9]*\).*|K\([^|]*\).*/\1\4\2\5.!\3\6,|\2<\3~\5>\6:\7;9876543210009909/ : mul1 s/![0-9]\([^<]*\)<\([0-9]\{0,1\}\)\([^>]*\)>\([0-9]\{0,1\}\)/0!\1\2<\3\4>/ /![0-9]/ s/\(:[^;]*\)\([1-9]\)\(0*\)\([^0]*\2\(.\).*X*\3\(9*\)\)/\1\5\6\4/ /<~[^>]*>:0*;/!t mul1 s/\(-*\)\1\([^>]*\).*/;\2^>:9876543210aaaaaaaaa/ : mul2 s/\([0-9]~*\)^/^\1/ s/<\([0-9]*\)\(.*[~^]\)\([0-9]*\)>/\1<\2>\3/ : mul3 s/>\([0-9]\)\(.*\1.\{9\}\(a*\)\)/\1>\2;9\38\37\36\35\34\33\32\31\30/ s/\(;[^<]*\)\([0-9]\)<\([^;]*\).*\2[0-9]*\(.*\)/\4\1<\2\3/ s/a[0-9]/a/g s/a\{10\}/b/g s/b\{10\}/c/g /|0*[1-9][^>]*>0*[1-9]/b mul3 s/;/a9876543210;/ s/a.\{9\}\(.\)[^;]*\([^,]*\)[0-9]\([.!]*\),/\2,\1\3/ y/cb/ba/ /|<^/!b mul2 b endbin : div # CDDET /^[-.0]*[1-9]/ !i\ divide by 0 //!b pop s/\(-*\)\([0-9]*\)\.*\([^~]*~-*\)\([0-9]*\)\.*\([^~]*\)/\2.\3\1;0\4.\5;0/ : div1 s/^\.0\([^.]*\)\.;*\([0-9]\)\([0-9]*\);*0*/.\1\2.\3;0/ s/^\([^.]*\)\([0-9]\)\.\([^;]*;\)0*\([0-9]*\)\([0-9]\)\./\1.\2\30\4.\5/ t div1 s/~\(-*\)\1\(-*\);0*\([^;]*[0-9]\)[^~]*/~123456789743222111~\2\3/ s/\(.\(.\)[^~]*\)[^9]*\2.\{8\}\(.\)[^~]*/\3~\1/ s,|?.,&SaSadSaKdlaZ+LaX-1+[sb1]Sbd1>bkLatsbLa[dSa2lbla*-*dLa!=a]dSaxsakLasbLb*t, b next : rem s,|?%,&Sadla/LaKSa[999]k*Lak-, b next : exp # This decimal method is just a little faster than the binary method done # totally in dc: 1LaKLb [kdSb*LbK]Sb [[.5]*d0ktdSaa[dk]sadKa]dsaxsasaLbsaLatLbk K1-kt, b next # END OF GSU dc.sed kbuild-3686/src/oldsed/testsuite/Makefile.in0000664000175000017500000006254715053010105021057 0ustar locutuslocutus# Makefile.in generated by automake 1.9.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SOURCES = bug-regex10.c bug-regex11.c bug-regex12.c bug-regex13.c bug-regex14.c bug-regex15.c bug-regex16.c bug-regex21.c bug-regex7.c bug-regex8.c bug-regex9.c runptests.c runtests.c tst-boost.c tst-pcre.c tst-regex2.c tst-rxspencer.c srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @TEST_REGEX_TRUE@check_PROGRAMS = bug-regex7$(EXEEXT) \ @TEST_REGEX_TRUE@ bug-regex8$(EXEEXT) bug-regex9$(EXEEXT) \ @TEST_REGEX_TRUE@ bug-regex10$(EXEEXT) bug-regex11$(EXEEXT) \ @TEST_REGEX_TRUE@ bug-regex12$(EXEEXT) bug-regex13$(EXEEXT) \ @TEST_REGEX_TRUE@ bug-regex14$(EXEEXT) bug-regex15$(EXEEXT) \ @TEST_REGEX_TRUE@ bug-regex16$(EXEEXT) bug-regex21$(EXEEXT) \ @TEST_REGEX_TRUE@ tst-pcre$(EXEEXT) tst-boost$(EXEEXT) \ @TEST_REGEX_TRUE@ runtests$(EXEEXT) runptests$(EXEEXT) \ @TEST_REGEX_TRUE@ tst-rxspencer$(EXEEXT) tst-regex2$(EXEEXT) @TEST_REGEX_TRUE@am__append_1 = space subdir = testsuite DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/codeset.m4 \ $(top_srcdir)/config/getline.m4 \ $(top_srcdir)/config/gettext-ver.m4 \ $(top_srcdir)/config/gettext.m4 \ $(top_srcdir)/config/glibc21.m4 $(top_srcdir)/config/iconv.m4 \ $(top_srcdir)/config/lcmessage.m4 \ $(top_srcdir)/config/lib-ld.m4 \ $(top_srcdir)/config/lib-link.m4 \ $(top_srcdir)/config/lib-prefix.m4 \ $(top_srcdir)/config/progtest.m4 \ $(top_srcdir)/config/stdbool.m4 \ $(top_srcdir)/config/strverscmp.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = bug_regex10_SOURCES = bug-regex10.c bug_regex10_OBJECTS = bug-regex10.$(OBJEXT) bug_regex10_LDADD = $(LDADD) bug_regex10_DEPENDENCIES = ../lib/libsed.a bug_regex11_SOURCES = bug-regex11.c bug_regex11_OBJECTS = bug-regex11.$(OBJEXT) bug_regex11_LDADD = $(LDADD) bug_regex11_DEPENDENCIES = ../lib/libsed.a bug_regex12_SOURCES = bug-regex12.c bug_regex12_OBJECTS = bug-regex12.$(OBJEXT) bug_regex12_LDADD = $(LDADD) bug_regex12_DEPENDENCIES = ../lib/libsed.a bug_regex13_SOURCES = bug-regex13.c bug_regex13_OBJECTS = bug-regex13.$(OBJEXT) bug_regex13_LDADD = $(LDADD) bug_regex13_DEPENDENCIES = ../lib/libsed.a bug_regex14_SOURCES = bug-regex14.c bug_regex14_OBJECTS = bug-regex14.$(OBJEXT) bug_regex14_LDADD = $(LDADD) bug_regex14_DEPENDENCIES = ../lib/libsed.a bug_regex15_SOURCES = bug-regex15.c bug_regex15_OBJECTS = bug-regex15.$(OBJEXT) bug_regex15_LDADD = $(LDADD) bug_regex15_DEPENDENCIES = ../lib/libsed.a bug_regex16_SOURCES = bug-regex16.c bug_regex16_OBJECTS = bug-regex16.$(OBJEXT) bug_regex16_LDADD = $(LDADD) bug_regex16_DEPENDENCIES = ../lib/libsed.a bug_regex21_SOURCES = bug-regex21.c bug_regex21_OBJECTS = bug-regex21.$(OBJEXT) bug_regex21_LDADD = $(LDADD) bug_regex21_DEPENDENCIES = ../lib/libsed.a bug_regex7_SOURCES = bug-regex7.c bug_regex7_OBJECTS = bug-regex7.$(OBJEXT) bug_regex7_LDADD = $(LDADD) bug_regex7_DEPENDENCIES = ../lib/libsed.a bug_regex8_SOURCES = bug-regex8.c bug_regex8_OBJECTS = bug-regex8.$(OBJEXT) bug_regex8_LDADD = $(LDADD) bug_regex8_DEPENDENCIES = ../lib/libsed.a bug_regex9_SOURCES = bug-regex9.c bug_regex9_OBJECTS = bug-regex9.$(OBJEXT) bug_regex9_LDADD = $(LDADD) bug_regex9_DEPENDENCIES = ../lib/libsed.a runptests_SOURCES = runptests.c runptests_OBJECTS = runptests.$(OBJEXT) runptests_LDADD = $(LDADD) runptests_DEPENDENCIES = ../lib/libsed.a runtests_SOURCES = runtests.c runtests_OBJECTS = runtests.$(OBJEXT) runtests_LDADD = $(LDADD) runtests_DEPENDENCIES = ../lib/libsed.a tst_boost_SOURCES = tst-boost.c tst_boost_OBJECTS = tst-boost.$(OBJEXT) tst_boost_LDADD = $(LDADD) tst_boost_DEPENDENCIES = ../lib/libsed.a tst_pcre_SOURCES = tst-pcre.c tst_pcre_OBJECTS = tst-pcre.$(OBJEXT) tst_pcre_LDADD = $(LDADD) tst_pcre_DEPENDENCIES = ../lib/libsed.a tst_regex2_SOURCES = tst-regex2.c tst_regex2_OBJECTS = tst-regex2.$(OBJEXT) tst_regex2_LDADD = $(LDADD) tst_regex2_DEPENDENCIES = ../lib/libsed.a tst_rxspencer_SOURCES = tst-rxspencer.c tst_rxspencer_OBJECTS = tst-rxspencer.$(OBJEXT) tst_rxspencer_LDADD = $(LDADD) tst_rxspencer_DEPENDENCIES = ../lib/libsed.a DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = bug-regex10.c bug-regex11.c bug-regex12.c bug-regex13.c \ bug-regex14.c bug-regex15.c bug-regex16.c bug-regex21.c \ bug-regex7.c bug-regex8.c bug-regex9.c runptests.c runtests.c \ tst-boost.c tst-pcre.c tst-regex2.c tst-rxspencer.c DIST_SOURCES = bug-regex10.c bug-regex11.c bug-regex12.c bug-regex13.c \ bug-regex14.c bug-regex15.c bug-regex16.c bug-regex21.c \ bug-regex7.c bug-regex8.c bug-regex9.c runptests.c runtests.c \ tst-boost.c tst-pcre.c tst-regex2.c tst-rxspencer.c HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_HTML_FALSE = @BUILD_HTML_FALSE@ BUILD_HTML_TRUE = @BUILD_HTML_TRUE@ BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GENCAT = @GENCAT@ GLIBC21 = @GLIBC21@ GMSGFMT = @GMSGFMT@ HAVE__BOOL = @HAVE__BOOL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLBISON = @INTLBISON@ INTLLIBS = @INTLLIBS@ INTLOBJS = @INTLOBJS@ INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MAKEINFO_HTML_FALSE = @MAKEINFO_HTML_FALSE@ MAKEINFO_HTML_TRUE = @MAKEINFO_HTML_TRUE@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ RANLIB = @RANLIB@ SED_FEATURE_VERSION = @SED_FEATURE_VERSION@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TEST_REGEX_FALSE = @TEST_REGEX_FALSE@ TEST_REGEX_TRUE = @TEST_REGEX_TRUE@ TEXI2HTML = @TEXI2HTML@ TEXI2HTML_HTML_FALSE = @TEXI2HTML_HTML_FALSE@ TEXI2HTML_HTML_TRUE = @TEXI2HTML_HTML_TRUE@ USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ CLEANFILES = tmp* core *.core $(EXTRA_PROGRAMS) *.*out *.log TESTS = $(check_PROGRAMS) $(SEDTESTS) SEDTESTS = $(am__append_1) appquit enable sep inclib 8bit newjis xabcx \ dollar noeol noeolw modulo numsub numsub2 numsub3 numsub4 \ numsub5 0range bkslashes head madding mac-mf empty xbxcx \ xbxcx3 recall recall2 xemacs fasts uniq manis khadafy linecnt \ eval distrib 8to7 y-bracket y-newline allsub cv-vars classes \ middle bsd stdin flipcase insens subwrite writeout readin help \ version file quiet factor binary3 binary2 binary dc LDADD = ../lib/libsed.a noinst_HEADERS = testcases.h ptestcases.h AM_CPPFLAGS = -I../lib TESTS_ENVIRONMENT = MAKE="$(MAKE)" VERSION="$(VERSION)" $(srcdir)/runtest EXTRA_DIST = \ PCRE.tests BOOST.tests SPENCER.tests \ runtest Makefile.tests \ 0range.good 0range.inp 0range.sed \ 8bit.good 8bit.inp 8bit.sed \ 8to7.good 8to7.inp 8to7.sed \ allsub.good allsub.inp allsub.sed \ appquit.good appquit.inp appquit.sed \ binary.good binary.inp binary.sed binary2.sed binary3.sed \ bkslashes.good bkslashes.inp bkslashes.sed \ bsd.good bsd.sh \ cv-vars.good cv-vars.inp cv-vars.sed \ classes.good classes.inp classes.sed \ dc.good dc.inp dc.sed \ distrib.good distrib.inp distrib.sed distrib.sh \ dollar.good dollar.inp dollar.sed \ empty.good empty.inp empty.sed \ enable.good enable.inp enable.sed \ eval.good eval.inp eval.sed \ factor.good factor.inp factor.sed \ fasts.good fasts.inp fasts.sed \ flipcase.good flipcase.inp flipcase.sed \ head.good head.inp head.sed \ inclib.good inclib.inp inclib.sed \ insens.good insens.inp insens.sed \ khadafy.good khadafy.inp khadafy.sed \ linecnt.good linecnt.inp linecnt.sed \ space.good space.inp space.sed \ mac-mf.good mac-mf.inp mac-mf.sed \ madding.good madding.inp madding.sed \ manis.good manis.inp manis.sed \ middle.good middle.sed middle.inp \ modulo.good modulo.sed modulo.inp \ newjis.good newjis.inp newjis.sed \ noeol.good noeol.inp noeol.sed \ noeolw.good noeolw.1good noeolw.2good noeolw.sed \ numsub.good numsub.inp numsub.sed \ numsub2.good numsub2.inp numsub2.sed \ numsub3.good numsub3.inp numsub3.sed \ numsub4.good numsub4.inp numsub4.sed \ numsub5.good numsub5.inp numsub5.sed \ readin.good readin.in2 readin.inp readin.sed \ recall.good recall.inp recall.sed \ recall2.good recall2.inp recall2.sed \ sep.good sep.inp sep.sed \ subwrite.inp subwrite.sed subwrt1.good subwrt2.good \ uniq.good uniq.inp uniq.sed \ version.gin \ writeout.inp writeout.sed wrtout1.good wrtout2.good \ xabcx.good xabcx.inp xabcx.sed \ xbxcx.good xbxcx.inp xbxcx.sed \ xbxcx3.good xbxcx3.inp xbxcx3.sed \ xemacs.good xemacs.inp xemacs.sed \ y-bracket.good y-bracket.sed y-bracket.inp \ y-newline.good y-newline.sed y-newline.inp all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits testsuite/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnits testsuite/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh clean-checkPROGRAMS: -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS) bug-regex10$(EXEEXT): $(bug_regex10_OBJECTS) $(bug_regex10_DEPENDENCIES) @rm -f bug-regex10$(EXEEXT) $(LINK) $(bug_regex10_LDFLAGS) $(bug_regex10_OBJECTS) $(bug_regex10_LDADD) $(LIBS) bug-regex11$(EXEEXT): $(bug_regex11_OBJECTS) $(bug_regex11_DEPENDENCIES) @rm -f bug-regex11$(EXEEXT) $(LINK) $(bug_regex11_LDFLAGS) $(bug_regex11_OBJECTS) $(bug_regex11_LDADD) $(LIBS) bug-regex12$(EXEEXT): $(bug_regex12_OBJECTS) $(bug_regex12_DEPENDENCIES) @rm -f bug-regex12$(EXEEXT) $(LINK) $(bug_regex12_LDFLAGS) $(bug_regex12_OBJECTS) $(bug_regex12_LDADD) $(LIBS) bug-regex13$(EXEEXT): $(bug_regex13_OBJECTS) $(bug_regex13_DEPENDENCIES) @rm -f bug-regex13$(EXEEXT) $(LINK) $(bug_regex13_LDFLAGS) $(bug_regex13_OBJECTS) $(bug_regex13_LDADD) $(LIBS) bug-regex14$(EXEEXT): $(bug_regex14_OBJECTS) $(bug_regex14_DEPENDENCIES) @rm -f bug-regex14$(EXEEXT) $(LINK) $(bug_regex14_LDFLAGS) $(bug_regex14_OBJECTS) $(bug_regex14_LDADD) $(LIBS) bug-regex15$(EXEEXT): $(bug_regex15_OBJECTS) $(bug_regex15_DEPENDENCIES) @rm -f bug-regex15$(EXEEXT) $(LINK) $(bug_regex15_LDFLAGS) $(bug_regex15_OBJECTS) $(bug_regex15_LDADD) $(LIBS) bug-regex16$(EXEEXT): $(bug_regex16_OBJECTS) $(bug_regex16_DEPENDENCIES) @rm -f bug-regex16$(EXEEXT) $(LINK) $(bug_regex16_LDFLAGS) $(bug_regex16_OBJECTS) $(bug_regex16_LDADD) $(LIBS) bug-regex21$(EXEEXT): $(bug_regex21_OBJECTS) $(bug_regex21_DEPENDENCIES) @rm -f bug-regex21$(EXEEXT) $(LINK) $(bug_regex21_LDFLAGS) $(bug_regex21_OBJECTS) $(bug_regex21_LDADD) $(LIBS) bug-regex7$(EXEEXT): $(bug_regex7_OBJECTS) $(bug_regex7_DEPENDENCIES) @rm -f bug-regex7$(EXEEXT) $(LINK) $(bug_regex7_LDFLAGS) $(bug_regex7_OBJECTS) $(bug_regex7_LDADD) $(LIBS) bug-regex8$(EXEEXT): $(bug_regex8_OBJECTS) $(bug_regex8_DEPENDENCIES) @rm -f bug-regex8$(EXEEXT) $(LINK) $(bug_regex8_LDFLAGS) $(bug_regex8_OBJECTS) $(bug_regex8_LDADD) $(LIBS) bug-regex9$(EXEEXT): $(bug_regex9_OBJECTS) $(bug_regex9_DEPENDENCIES) @rm -f bug-regex9$(EXEEXT) $(LINK) $(bug_regex9_LDFLAGS) $(bug_regex9_OBJECTS) $(bug_regex9_LDADD) $(LIBS) runptests$(EXEEXT): $(runptests_OBJECTS) $(runptests_DEPENDENCIES) @rm -f runptests$(EXEEXT) $(LINK) $(runptests_LDFLAGS) $(runptests_OBJECTS) $(runptests_LDADD) $(LIBS) runtests$(EXEEXT): $(runtests_OBJECTS) $(runtests_DEPENDENCIES) @rm -f runtests$(EXEEXT) $(LINK) $(runtests_LDFLAGS) $(runtests_OBJECTS) $(runtests_LDADD) $(LIBS) tst-boost$(EXEEXT): $(tst_boost_OBJECTS) $(tst_boost_DEPENDENCIES) @rm -f tst-boost$(EXEEXT) $(LINK) $(tst_boost_LDFLAGS) $(tst_boost_OBJECTS) $(tst_boost_LDADD) $(LIBS) tst-pcre$(EXEEXT): $(tst_pcre_OBJECTS) $(tst_pcre_DEPENDENCIES) @rm -f tst-pcre$(EXEEXT) $(LINK) $(tst_pcre_LDFLAGS) $(tst_pcre_OBJECTS) $(tst_pcre_LDADD) $(LIBS) tst-regex2$(EXEEXT): $(tst_regex2_OBJECTS) $(tst_regex2_DEPENDENCIES) @rm -f tst-regex2$(EXEEXT) $(LINK) $(tst_regex2_LDFLAGS) $(tst_regex2_OBJECTS) $(tst_regex2_LDADD) $(LIBS) tst-rxspencer$(EXEEXT): $(tst_rxspencer_OBJECTS) $(tst_rxspencer_DEPENDENCIES) @rm -f tst-rxspencer$(EXEEXT) $(LINK) $(tst_rxspencer_LDFLAGS) $(tst_rxspencer_OBJECTS) $(tst_rxspencer_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex10.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex11.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex12.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex13.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex14.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex15.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex16.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex21.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex7.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex8.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex9.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runptests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-boost.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-pcre.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-regex2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-rxspencer.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` uninstall-info-am: ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list='$(TESTS)'; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-local mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-local ctags distclean \ distclean-compile distclean-generic distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-exec install-exec-am \ install-info install-info-am install-man install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-info-am clean-local: test x$(srcdir) = x. || rm -f readin.in2 eval.in2 # automake makes `check' depend on $(TESTS). Declare # dummy targets for $(TESTS) so that make does not complain. .PHONY: $(SEDTESTS) $(SEDTESTS): # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: kbuild-3686/src/oldsed/testsuite/mac-mf.inp0000664000175000017500000001425315053010105020651 0ustar locutuslocutus## config/mac-pre.in ## common Macintosh prefix for all Makefile.in in the Kerberos V5 tree. # # MPW-style lines for the MakeFile. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # This first part is long enough that NFS/Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make. # # End of MPW-style lines for MakeFile. # WHAT = mac # Directory syntax: R= C= S=: U=: BUILDTOP = ../../.. srcdir = . # FIXME: This doesn't translate to MPW yet, srcdir must be same as objdir. # File in object dir can come from either the current dir or srcdir. # # . : . "{srcdir}" # Default rule that puts each file into separate segment. .c.o: .c {CC} {DepDir}{Default}.c {CFLAGS} -s {Default} -o {TargDir}{Default}.c.o CPPFLAGS = -I$(SRCTOP)/include -I$(BUILDTOP)/include -I$(SRCTOP)/include/krb5 -I$(BUILDTOP)/include/krb5 -i {CIncludes} DEFS = $(CPPFLAGS) CC = c LD = link # The funny quoting in the LDFLAGS is to avoid xxx.o being mangled by # mac-mf.sed into xxx.c.o. LDFLAGS=-t MPST -c "MPS " -sym on {Libraries}"Runtime."o {CLibraries}"StdClib."o {Libraries}"ToolLibs."o {Libraries}"Interface."o CCOPTS = LIBS = KRB5ROOT= @KRB5ROOT@ KRB4=@KRB4@ INSTALL=Duplicate -y INSTALL_PROGRAM=Duplicate -y INSTALL_DATA=Duplicate -y INSTALL_SETUID=Duplicate -y KRB5MANROOT = $(KRB5ROOT)$(S)man ADMIN_BINDIR = $(KRB5ROOT)$(S)admin SERVER_BINDIR = $(KRB5ROOT)$(S)sbin CLIENT_BINDIR = $(KRB5ROOT)$(S)bin ADMIN_MANDIR = $(KRB5MANROOT)$(S)man8 SERVER_MANDIR = $(KRB5MANROOT)$(S)man8 CLIENT_MANDIR = $(KRB5MANROOT)$(S)man1 FILE_MANDIR = $(KRB5MANROOT)$(S)man5 KRB5_LIBDIR = $(KRB5ROOT)$(S)lib KRB5_INCDIR = $(KRB5ROOT)$(S)include KRB5_INCSUBDIRS = \ $(KRB5_INCDIR)$(S)krb5 \ $(KRB5_INCDIR)$(S)asn.1 \ $(KRB5_INCDIR)$(S)kerberosIV RM = Delete -y -i CP = Duplicate -y MV = mv -f CHMOD=chmod RANLIB = @RANLIB@ ARCHIVE = @ARCHIVE@ ARADD = @ARADD@ LN = @LN_S@ AWK = @AWK@ LEX = @LEX@ LEXLIB = @LEXLIB@ YACC = @YACC@ # FIXME: This won't work for srcdir != objdir. But on the Mac, there # is no easy way to build a relative or absolute path, because : means # both the path separator, and the "go up a directory" indicator. #SRCTOP = $(srcdir)$(S)$(BUILDTOP) SRCTOP = $(BUILDTOP) SUBDIRS = @subdirs@ TOPLIBD = $(BUILDTOP)$(S)lib OBJEXT = c.o LIBEXT = a EXEEXT = all:: # Generated automatically from Makefile.in by configure. CFLAGS = $(CCOPTS) $(DEFS) -I$(srcdir)/../des ##DOSBUILDTOP = ..\..\.. ##DOSLIBNAME=..\crypto.lib ##DOS!include $(BUILDTOP)\config\windows.in OBJS= md5.$(OBJEXT) md5glue.$(OBJEXT) md5crypto.$(OBJEXT) SRCS= $(srcdir)/md5.c $(srcdir)/md5glue.c $(srcdir)/md5crypto.c all:: $(OBJS) t_mddriver: t_mddriver.o md5.o $(CC) $(CFLAGS) $(LDFLAGS) -o t_mddriver t_mddriver.o md5.o t_mddriver.exe: $(CC) $(CFLAGS2) -o t_mddriver.exe t_mddriver.c md5.c check:: t_mddriver$(EXEEXT) $(C)t_mddriver$(EXEEXT) -x clean:: $(RM) t_mddriver$(EXEEXT) t_mddriver.$(OBJEXT) # config/post.in # put all:: first just in case no other rules occur here # all:: check:: clean:: clean-$(WHAT) $(RM) config.log pre.out post.out Makefile.out clean-unix:: if test -n "$(OBJS)" ; then $(RM) $(OBJS); else :; fi clean-windows:: $(RM) *.$(OBJEXT) $(RM) msvc.pdb *.err kbuild-3686/src/oldsed/testsuite/allsub.inp0000664000175000017500000000010715053010105020764 0ustar locutuslocutusfoo foo fo oo f oo foo foo foo foo foo foo foo foo foo foo foo foo foo kbuild-3686/src/oldsed/testsuite/eval.good0000664000175000017500000000063115053010105020575 0ustar locutuslocutusabcd --- abcd --- abcd --- 17380: 2 2 5 11 79 cpu --- 17380: 2 2 5 11 79 cpu --- 17380: 2 2 5 11 79 cpu --- abcd --- abcd --- abcd --- 17380: 2 2 5 11 79 cpu --- 17380: 2 2 5 11 79 cpu --- 17380: 2 2 5 11 79 cpu --- Doing some more tests ----------------------- 17380: 2 2 5 11 79 --- ../sed/sed 1q eval.in2 --- 17380: 2 2 5 11 79 --- ../sed/sed 1q eval.in2 --- ../sed/sed 1q eval.in2 kbuild-3686/src/oldsed/testsuite/bug-regex14.c0000664000175000017500000000271515053010105021177 0ustar locutuslocutus/* Tests re_comp and re_exec. Copyright (C) 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa , 2002. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #define _REGEX_RE_COMP #include #ifdef HAVE_MCHECK_H #include #endif #include #include #include int main (void) { const char *err; size_t i; int ret = 0; #ifdef HAVE_MCHECK_H mtrace (); #endif for (i = 0; i < 100; ++i) { err = re_comp ("a t.st"); if (err) { printf ("re_comp failed: %s\n", err); ret = 1; } if (! re_exec ("This is a test.")) { printf ("re_exec failed\n"); ret = 1; } } return ret; } kbuild-3686/src/oldsed/testsuite/writeout.inp0000664000175000017500000000022015053010105021360 0ustar locutuslocutusFacts are simple and facts are straight Facts are lazy and facts are late Facts all come with points of view Facts don't do what I want them to kbuild-3686/src/oldsed/testsuite/inclib.inp0000664000175000017500000000122715053010105020746 0ustar locutuslocutus /usr/X11R6/lib /usr/X11R5/lib /usr/X11R4/lib /usr/lib/X11R6 /usr/lib/X11R5 /usr/lib/X11R4 /usr/local/X11R6/lib /usr/local/X11R5/lib /usr/local/X11R4/lib /usr/local/lib/X11R6 /usr/local/lib/X11R5 /usr/local/lib/X11R4 /usr/X11/lib /usr/lib/X11 /usr/local/X11/lib /usr/local/lib/X11 /usr/X386/lib /usr/x386/lib /usr/XFree86/lib/X11 /usr/lib /usr/local/lib /usr/unsupported/lib /usr/athena/lib /usr/local/x11r5/lib /usr/lpp/Xamples/lib /usr/openwin/lib /usr/openwin/share/lib kbuild-3686/src/oldsed/testsuite/newjis.good0000664000175000017500000000013215053010105021141 0ustar locutuslocutus$B$H$J$j$NM9JX6I$K(B $B$?$F$+$1$?$N$O(B $B$?$F$+$1$?$+$C$?$+$i(B $B$?$F$+$1$?!#(B kbuild-3686/src/oldsed/testsuite/uniq.inp0000664000175000017500000014103015053010105020457 0ustar locutuslocutus #define DPRINTF(p) /*nothing */ #define DPRINTF(p) printf p #define GETCHAR(c, eptr) c = *eptr; #define GETCHARINC(c, eptr) c = *eptr++; #define class pcre_class #define match_condassert 0x01 /* Called to check a condition assertion */ #define match_isgroup 0x02 /* Set if start of bracketed group */ #else #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #ifdef DEBUG /* Sigh. Some compilers never learn. */ #ifdef DEBUG /* Sigh. Some compilers never learn. */ #ifdef DEBUG #ifdef DEBUG #ifdef DEBUG #ifdef DEBUG #ifdef DEBUG #ifdef DEBUG #ifdef DEBUG #ifdef DEBUG #ifdef DEBUG #ifdef DEBUG #ifdef DEBUG #ifdef DEBUG #ifdef DEBUG #ifdef __cplusplus #include "internal.h" && length - re->max_match_size > start_offset) ((*ecode++ == OP_BEG_WORD) ? prev_is_word : cur_is_word)) ((md->ctypes[*eptr] & ctype_word) != 0); ((md->ctypes[*eptr] & ctype_word) != 0); ((md->ctypes[eptr[-1]] & ctype_word) != 0); ((md->ctypes[eptr[-1]] & ctype_word) != 0); (eptr == md->end_subject - 1 && *eptr != '\n')) (eptr == md->end_subject - 1 && *eptr != '\n')) (i.e. keep it out of the loop). Also we can test that there are at least (md->ctypes[*eptr++] & ctype_digit) != 0) (md->ctypes[*eptr++] & ctype_digit) == 0) (md->ctypes[*eptr++] & ctype_space) != 0) (md->ctypes[*eptr++] & ctype_space) == 0) (md->ctypes[*eptr++] & ctype_word) != 0) (md->ctypes[*eptr++] & ctype_word) == 0) (offsetcount - 2) * sizeof (int)); (offsets == NULL && offsetcount > 0)) (pcre_free) (match_block.offset_vector); (pcre_free) (match_block.offset_vector); (pcre_free) (save); (re->tables + fcc_offset)[req_char] : req_char; * Match a back-reference * * Execute a Regular Expression * * Match from current position * * Debugging function to print chars * * Perl-Compatible Regular Expressions * * Macros and tables for character handling * *************************************************/ *************************************************/ *************************************************/ *************************************************/ *************************************************/ *************************************************/ */ */ */ */ */ *iptr = -1; *iptr++ = -1; *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT || *prev == OP_ONCE) ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- -1 => failed to match /* /* "Once" brackets are like assertion brackets except that after a match, /* ... else fall through */ /* ... else fall through */ /* Advance to a possible match for an initial string after study */ /* Allow compilation as C++ source code, should anybody want to do that. */ /* Always fail if not enough characters left */ /* An alternation is the end of a branch; scan along to find the end of the /* Assert before internal newline if multiline, or before a terminating /* Assertion brackets. Check the alternative branches in turn - the /* At the start of a bracketed group, add the current subject pointer to the /* BRAZERO and BRAMINZERO occur just before a bracket group, indicating /* Caseful comparisons */ /* Caseful comparisons */ /* Change option settings */ /* Common code for all repeated single character type matches */ /* Common code for all repeated single-character matches. We can give /* Common code for all repeated single-character matches. We can give /* Compute the minimum number of offsets that we need to reset each time. Doing /* Conditional group: compilation checked that there are no more than /* Continue as from after the assertion, updating the offsets high water /* Continue from after the assertion, updating the offsets high water /* Control never gets here */ /* Control never gets here */ /* Control never gets here */ /* Control never gets here */ /* Control never gets here */ /* Control never gets here */ /* Control never gets here */ /* Control never gets here */ /* Control never gets here */ /* Control never gets here */ /* Control never gets here */ /* Control never gets here */ /* Control never gets here */ /* Control never gets here */ /* Control never reaches here */ /* Control never reaches here */ /* Copy the offset information from temporary store if necessary */ /* Do a single test if no case difference is set up */ /* Do not stick any code in here without much thought; it is assumed /* End of a group, repeated or non-repeating. If we are at the end of /* End of subject assertion (\z) */ /* End of subject or ending \n assertion (\Z) */ /* End of the pattern. If PCRE_NOTEMPTY is set, fail if we have matched /* First, ensure the minimum number of matches are present. */ /* First, ensure the minimum number of matches are present. Use inline /* First, ensure the minimum number of matches are present. We get back /* Flag bits for the match() function */ /* For a non-repeating ket, just continue at this level. This also /* For a non-repeating ket, just continue at this level. This also /* For anchored or unanchored matches, there may be a "last known required /* For extended extraction brackets (large number), we have to fish out /* For extended extraction brackets (large number), we have to fish out the /* For matches anchored to the end of the pattern, we can often avoid /* If a back reference hasn't been set, the length that is passed is greater /* If checking an assertion for a condition, return TRUE. */ /* If hit the end of the group (which could be repeated), fail */ /* If max == min we can continue with the main loop without the /* If maximizing it is worth using inline code for speed, doing the type /* If maximizing, find the longest possible run, then work backwards. */ /* If maximizing, find the longest string and work backwards */ /* If min = max, continue at the same level without recursing */ /* If min = max, continue at the same level without recursion. /* If minimizing, keep testing the rest of the expression and advancing /* If minimizing, keep trying and advancing the pointer */ /* If minimizing, we have to test the rest of the pattern before each /* If req_char is set, we know that that character must appear in the subject /* If the expression has got more back references than the offsets supplied can /* If the length of the reference is zero, just continue with the /* If the reference is unset, set the length to be longer than the amount /* If we can't find the required character, break the matching loop */ /* If we have found the required character, save the point where we /* In all other cases except a conditional group we have to check the /* In case the recursion has set more capturing values, save the final /* Include the internals header, which itself includes Standard C headers plus /* Insufficient room for saving captured contents */ /* Loop for handling unanchored repeated matching attempts; for anchored regexs /* Match a back reference, possibly repeatedly. Look past the end of the /* Match a character class, possibly repeatedly. Look past the end of the /* Match a negated single character */ /* Match a negated single character repeatedly. This is almost a repeat of /* Match a run of characters */ /* Match a single character repeatedly; different opcodes share code. */ /* Match a single character type repeatedly; several different opcodes /* Match a single character type; inline for speed */ /* Min and max values for the common repeats; for the maxima, 0 => infinity */ /* Move the subject pointer back. This occurs only at the start of /* Negative assertion: all branches must fail to match */ /* Now start processing the operations. */ /* OP_KETRMAX */ /* OP_KETRMAX */ /* On entry ecode points to the first opcode, and eptr to the first character /* Opening capturing bracket. If there is space in the offset vector, save /* Or to a non-unique first char after study */ /* Or to a unique first char if possible */ /* Or to just after \n for a multiline match if possible */ /* Other types of node can be handled by a switch */ /* Otherwise test for either case */ /* Print a sequence of chars in printable format, stopping at the end of the /* Recursion matches the current regex, nested. If there are any capturing /* Reset the maximum number of extractions we might see. */ /* Reset the value of the ims flags, in case they got changed during /* Reset the working variable associated with each extraction. These should /* Separate the caselesss case for speed */ /* Set up for repetition, or handle the non-repeated case */ /* Set up the first character to match, if available. The first_char value is /* Skip over conditional reference data or large extraction number data if /* Start of subject assertion */ /* Start of subject unless notbol, or after internal newline if multiline */ /* Structure for building a chain of data that actually lives on the /* The code is duplicated for the caseless and caseful cases, for speed, /* The code is duplicated for the caseless and caseful cases, for speed, /* The condition is an assertion. Call match() to evaluate it - setting /* The ims options can vary during the matching as a result of the presence /* The repeating kets try the rest of the pattern or restart from the /* The repeating kets try the rest of the pattern or restart from the /* There's been some horrible disaster. */ /* This "while" is the end of the "do" above */ /* This function applies a compiled re to a subject string and picks out /* Use a macro for debugging printing, 'cause that limits the use of #ifdef /* We don't need to repeat the search if we haven't yet reached the /* When a match occurs, substrings will be set for all internal extractions; /* Word boundary assertions */ /************************************************* /************************************************* /************************************************* /************************************************* /************************************************* /************************************************* 1. This software is distributed in the hope that it will be useful, 2. The origin of this software must not be misrepresented, either by 3. Altered versions must be plainly marked as such, and must not be 4. If PCRE is embedded in any software that is released under the GNU 5.005. If there is an options reset, it will get obeyed in the normal 5.005. If there is an options reset, it will get obeyed in the normal 6 : 3 + (ecode[1] << 8) + ecode[2]), < -1 => some kind of unexpected problem = 0 => success, but offsets is not big enough Arguments: Arguments: Arguments: Arguments: BOOL anchored; BOOL cur_is_word = (eptr < md->end_subject) && BOOL cur_is_word = (eptr < md->end_subject) && BOOL is_subject; BOOL minimize = FALSE; BOOL prev_is_word = (eptr != md->start_subject) && BOOL prev_is_word = (eptr != md->start_subject) && BOOL rc; BOOL startline; BOOL using_temporary_offsets = FALSE; Copyright (c) 1997-2000 University of Cambridge DPRINTF ((">>>> returning %d\n", match_block.errorcode)); DPRINTF ((">>>> returning %d\n", rc)); DPRINTF (("Copied offsets from temporary memory\n")); DPRINTF (("Freeing temporary memory\n")); DPRINTF (("Freeing temporary memory\n")); DPRINTF (("Got memory to hold back references\n")); DPRINTF (("Unknown opcode %d\n", *ecode)); DPRINTF (("bracket %d failed\n", number)); DPRINTF (("bracket 0 failed\n")); DPRINTF (("ims reset to %02lx\n", ims)); DPRINTF (("ims set to %02lx at group repeat\n", ims)); DPRINTF (("ims set to %02lx\n", ims)); DPRINTF (("matching %c{%d,%d} against subject %.*s\n", c, min, max, DPRINTF (("negative matching %c{%d,%d} against subject %.*s\n", c, min, max, DPRINTF (("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); DPRINTF (("start bracket 0\n")); GETCHAR (c, eptr) /* Get character */ GETCHARINC (c, eptr) /* Get character; increment eptr */ GETCHARINC (c, eptr) /* Get character; increment eptr */ General Purpose Licence (GPL), then the terms of that licence shall However, if the referenced string is the empty string, always treat If the bracket fails to match, we need to restore this value and also the If there isn't enough space in the offset vector, treat this as if it were a MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Otherwise, we can use the vector supplied, rounding down its size to a multiple Permission is granted to anyone to use this software for any purpose on any REPEATCHAR: REPEATNOTCHAR: REPEATTYPE: Returns: > 0 => success; value is the number of elements filled in Returns: TRUE if matched Returns: TRUE if matched Returns: nothing They are not both allowed to be zero. */ This is a library of functions to support regular expressions whose syntax This is the forcible breaking of infinite loops as implemented in Perl This is the forcible breaking of infinite loops as implemented in Perl Writing separate code makes it go faster, as does using an autoincrement and Written by: Philip Hazel a move back into the brackets. Check the alternative branches in turn - the address of eptr, so that eptr can be a register variable. */ an assertion "group", stop matching and return TRUE, but record the an empty string - recursion will then try other alternatives, if any. */ an error. Save the top 15 values on the stack, and accept that the rest an unanchored pattern, of course. If there's no first char and the pattern was analyzing most of the pattern. length > re->max_match_size is anchored = ((re->options | options) & PCRE_ANCHORED) != 0; and advance one byte in the pattern code. */ and reinstate them after the recursion. However, we don't know how many and semantics are as close as possible to those of the Perl 5 language. See and the required character in fact is caseful. */ at run time, so we have to test for anchoring. The first char may be unset for avoid duplicate testing (which takes significant time). This covers the vast backing off on a match. */ bmtable = extra->data.bmtable; both cases of the character. Otherwise set the two values the same, which will bracketed group and go to there. */ brackets - for testing for empty matches brackets started but not finished, we have to save their starting points break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; break; but WITHOUT ANY WARRANTY; without even the implied warranty of c != md->lcc[*eptr++]) c = *ecode++ - OP_CRSTAR; c = *ecode++ - OP_CRSTAR; c = *ecode++ - OP_NOTSTAR; c = *ecode++ - OP_STAR; c = *ecode++ - OP_TYPESTAR; c = *ecode++; c = *ecode++; c = *eptr++; c = 15; c = max - min; c = md->end_subject - eptr; c = md->lcc[c]; c = md->lcc[c]; c = md->offset_max; c == md->lcc[*eptr++]) can't just fail here, because of the possibility of quantifiers with zero case OP_ALT: case OP_ANY: case OP_ANY: case OP_ANY: case OP_ANY: case OP_ASSERT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ASSERT_NOT: case OP_BEG_WORD: case OP_BRA: /* Non-capturing bracket: optimized */ case OP_BRAMINZERO: case OP_BRANUMBER: case OP_BRAZERO: case OP_CHARS: case OP_CIRC: case OP_CLASS: case OP_COND: case OP_CREF: case OP_CRMINPLUS: case OP_CRMINPLUS: case OP_CRMINQUERY: case OP_CRMINQUERY: case OP_CRMINRANGE: case OP_CRMINRANGE: case OP_CRMINSTAR: case OP_CRMINSTAR: case OP_CRPLUS: case OP_CRPLUS: case OP_CRQUERY: case OP_CRQUERY: case OP_CRRANGE: case OP_CRRANGE: case OP_CRSTAR: case OP_CRSTAR: case OP_DIGIT: case OP_DIGIT: case OP_DIGIT: case OP_DIGIT: case OP_DOLL: case OP_END: case OP_END_WORD: case OP_EOD: case OP_EODN: case OP_EXACT: case OP_KET: case OP_KETRMAX: case OP_KETRMIN: case OP_MINPLUS: case OP_MINQUERY: case OP_MINSTAR: case OP_MINUPTO: case OP_NOT: case OP_NOTEXACT: case OP_NOTMINPLUS: case OP_NOTMINQUERY: case OP_NOTMINSTAR: case OP_NOTMINUPTO: case OP_NOTPLUS: case OP_NOTQUERY: case OP_NOTSTAR: case OP_NOTUPTO: case OP_NOT_DIGIT: case OP_NOT_DIGIT: case OP_NOT_DIGIT: case OP_NOT_DIGIT: case OP_NOT_WHITESPACE: case OP_NOT_WHITESPACE: case OP_NOT_WHITESPACE: case OP_NOT_WHITESPACE: case OP_NOT_WORDCHAR: case OP_NOT_WORDCHAR: case OP_NOT_WORDCHAR: case OP_NOT_WORDCHAR: case OP_NOT_WORD_BOUNDARY: case OP_ONCE: case OP_OPT: case OP_PLUS: case OP_QUERY: case OP_RECURSE: case OP_REF: case OP_REVERSE: case OP_SOD: case OP_STAR: case OP_TYPEEXACT: case OP_TYPEMINPLUS: case OP_TYPEMINQUERY: case OP_TYPEMINSTAR: case OP_TYPEMINUPTO: case OP_TYPEPLUS: case OP_TYPEQUERY: case OP_TYPESTAR: case OP_TYPEUPTO: case OP_UPTO: case OP_WHITESPACE: case OP_WHITESPACE: case OP_WHITESPACE: case OP_WHITESPACE: case OP_WORDCHAR: case OP_WORDCHAR: case OP_WORDCHAR: case OP_WORDCHAR: case OP_WORD_BOUNDARY: case matching may be when this character is hit, so test for it in both its caselessly, or if there are any changes of this flag within the regex, set up cases if necessary. However, the different cased versions will not be set up character" set. If the PCRE_CASELESS is set, implying that the match starts characters and work backwards. */ characters and work backwards. */ code for maximizing the speed, and do the type test once at the start code to character type repeats - written out again for speed. */ commoning these up that doesn't require a test of the positive/negative computer system, and to redistribute it freely, subject to the following const char *subject; const pcre *re; const pcre_extra *extra; const uschar *bmtable = NULL; const uschar *data = ecode + 1; /* Save for matching */ const uschar *end_subject; const uschar *next = ecode + 1; const uschar *next = ecode + 1; const uschar *p = md->start_subject + md->offset_vector[offset]; const uschar *p; const uschar *pp = eptr; const uschar *pp = eptr; const uschar *pp = eptr; const uschar *pp = eptr; const uschar *pp = eptr; const uschar *pp = eptr; const uschar *pp = eptr; const uschar *prev = ecode - (ecode[1] << 8) - ecode[2]; const uschar *prev = ecode; const uschar *req_char_ptr = start_match - 1; const uschar *saved_eptr = eptr; const uschar *saved_eptr = eptrb->saved_eptr; const uschar *saved_eptr; const uschar *start_bits = NULL; const uschar *start_match = (const uschar *) subject + start_offset; continue; /* With the main loop */ continue; continue; continue; continue; continue; continue; continue; continue; continue; continue; continue; continue; continue; course of events. */ course of events. */ ctype = *ecode++; /* Code for the character type */ cur_is_word == prev_is_word : cur_is_word != prev_is_word) current high water mark for use by positive assertions. Do this also default: /* No repeat follows */ default: /* No repeat follows */ default: do do do do do do do do do do do each branch of a lookbehind assertion. If we are too close to the start to each substring: the offsets to the start and end of the substring. ecode position in code ecode + ((offset < offset_top && md->offset_vector[offset] >= 0) ? ecode += (ecode[1] << 8) + ecode[2]; ecode += (ecode[1] << 8) + ecode[2]; ecode += (ecode[1] << 8) + ecode[2]; ecode += (ecode[1] << 8) + ecode[2]; ecode += (ecode[1] << 8) + ecode[2]; ecode += (ecode[1] << 8) + ecode[2]; ecode += (ecode[1] << 8) + ecode[2]; ecode += (ecode[1] << 8) + ecode[2]; ecode += (ecode[1] << 8) + ecode[2]; ecode += (ecode[1] << 8) + ecode[2]; ecode += 2; ecode += 2; ecode += 3 + (ecode[4] << 8) + ecode[5]; ecode += 33; /* Advance past the item */ ecode += 3; /* Advance past the item */ ecode += 3; ecode += 3; ecode += 3; ecode += 3; ecode += 3; ecode += 3; ecode += 3; ecode += 3; ecode += 3; ecode += 3; ecode += 3; ecode += 3; ecode += 5; ecode += 5; ecode = next + 3; ecode++; ecode++; ecode++; ecode++; ecode++; ecode++; ecode++; ecode++; ecode++; ecode++; ecode++; ecode++; ecode++; ecode++; ecode++; ecode++; else else else else else else else else else else else else else else else else else else else else else else else else else else else else else else else else else if ((extra->options & PCRE_STUDY_BM) != 0) else if (first_char >= 0) else if (start_bits != NULL) else if (startline) encountered */ end_subject = match_block.end_subject; eptr pointer in subject eptr points into the subject eptr += c; eptr += length; eptr += length; eptr += length; eptr += length; eptr += min; eptr -= (ecode[1] << 8) + ecode[2]; eptr -= length; eptr = md->end_match_ptr; eptr = md->end_match_ptr; eptr++; eptr++; eptr++; eptr++; eptr++; eptr++; eptr++; eptr++; eptr++; eptr++; eptr++; eptr++; eptrb pointer to chain of blocks containing eptr at start of eptrb = &newptrb; eptrb = eptrb->prev; /* Back up the stack of bracket start pointers */ eptrblock *eptrb; eptrblock newptrb; eptrblock; exactly what going to the ket would do. */ explicit claim or by omission. external_extra points to "hints" from pcre_study() or is NULL external_re points to the compiled expression extraction by setting the offsets and bumping the high water mark. */ first_char = match_block.lcc[first_char]; first_char = re->first_char; flags can contain for (;;) for (i = 1; i <= c; i++) for (i = 1; i <= c; i++) for (i = 1; i <= min; i++) for (i = 1; i <= min; i++) for (i = 1; i <= min; i++) for (i = 1; i <= min; i++) for (i = 1; i <= min; i++) for (i = 1; i <= min; i++) for (i = 1; i <= min; i++) for (i = 1; i <= min; i++) for (i = 1; i <= min; i++) for (i = 1; i <= min; i++) for (i = 1; i <= min; i++) for (i = 1; i <= min; i++) for (i = 1; i <= min; i++) for (i = min; i < max; i++) for (i = min; i < max; i++) for (i = min; i < max; i++) for (i = min; i < max; i++) for (i = min; i < max; i++) for (i = min; i < max; i++) for (i = min; i < max; i++) for (i = min; i < max; i++) for (i = min; i < max; i++) for (i = min; i < max; i++) for (i = min; i < max; i++) for (i = min; i < max; i++) for (i = min; i < max; i++) for (i = min;; i++) for (i = min;; i++) for (i = min;; i++) for (i = min;; i++) for (i = min;; i++) for (i = min;; i++) for (i = min;; i++) for the "once" (not-backup up) groups. */ for the match to succeed. If the first character is set, req_char must be found it, so that we don't search again next time round the loop if from a previous iteration of this group, and be referred to by a reference goto REPEATCHAR; goto REPEATCHAR; goto REPEATNOTCHAR; goto REPEATNOTCHAR; goto REPEATTYPE; goto REPEATTYPE; group number back at the start and if necessary complete handling an happens for a repeating ket if no characters were matched in the group. happens for a repeating ket if no characters were matched in the group. here; that is handled in the code for KET. */ hold, we get a temporary bit of working store to use during the matching. i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper if (!anchored) if (!match (start_match, re->code, 2, &match_block, ims, NULL, match_isgroup)) if (!match_ref (offset, eptr, length, md, ims)) if (!match_ref (offset, eptr, length, md, ims)) if (!match_ref (offset, eptr, length, md, ims)) if (!md->endonly) if (!rc) if (!startline && extra != NULL) if ((*ecode++ == OP_WORD_BOUNDARY) ? if ((data[c / 8] & (1 << (c & 7))) != 0) if ((data[c / 8] & (1 << (c & 7))) != 0) if ((data[c / 8] & (1 << (c & 7))) == 0) if ((extra->options & PCRE_STUDY_MAPPED) != 0) if ((flags & match_condassert) != 0) if ((flags & match_condassert) != 0) if ((flags & match_isgroup) != 0) if ((ims & PCRE_CASELESS) != 0) if ((ims & PCRE_CASELESS) != 0) if ((ims & PCRE_CASELESS) != 0) if ((ims & PCRE_CASELESS) != 0) if ((ims & PCRE_CASELESS) != 0) if ((ims & PCRE_CASELESS) != 0) if ((ims & PCRE_CASELESS) != 0) if ((ims & PCRE_DOTALL) == 0 && c == '\n') if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == '\n') if ((ims & PCRE_DOTALL) == 0) if ((ims & PCRE_DOTALL) == 0) if ((ims & PCRE_MULTILINE) != 0) if ((ims & PCRE_MULTILINE) != 0) if ((md->ctypes[*eptr++] & ctype_digit) != 0) if ((md->ctypes[*eptr++] & ctype_digit) == 0) if ((md->ctypes[*eptr++] & ctype_space) != 0) if ((md->ctypes[*eptr++] & ctype_space) == 0) if ((md->ctypes[*eptr++] & ctype_word) != 0) if ((md->ctypes[*eptr++] & ctype_word) == 0) if ((md->ctypes[c] & ctype_digit) != 0) if ((md->ctypes[c] & ctype_digit) == 0) if ((md->ctypes[c] & ctype_space) != 0) if ((md->ctypes[c] & ctype_space) == 0) if ((md->ctypes[c] & ctype_word) != 0) if ((md->ctypes[c] & ctype_word) == 0) if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) if ((re->options & PCRE_FIRSTSET) != 0) if ((re->options & PCRE_REQCHSET) != 0) if ((start_bits[c / 8] & (1 << (c & 7))) == 0) if (*ecode != OP_ONCE && *ecode != OP_ALT) if (*ecode == OP_KET || eptr == saved_eptr) if (*ecode == OP_KET || eptr == saved_eptr) if (*ecode == OP_KET) if (*ecode == OP_KETRMIN) if (*ecode == OP_KETRMIN) if (*ecode++ != *eptr++) if (*ecode++ == *eptr++) if (*eptr != '\n') if (*eptr++ == '\n') if (*p++ != *eptr++) if (*p++ == req_char) if (*prev != OP_COND) if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT || if (bmtable != NULL) if (bmtable[*start_match]) if (c != *eptr++) if (c != md->lcc[*eptr++]) if (c < 16) if (c == *eptr++) if (c == md->lcc[*eptr++]) if (c > md->end_subject - eptr) if (cur_is_word == prev_is_word || if (ecode[3] == OP_CREF) /* Condition is extraction test */ if (ecode[3] == OP_OPT) if (eptr != md->start_subject && eptr[-1] != '\n') if (eptr != md->start_subject) if (eptr < md->end_subject - 1 || if (eptr < md->end_subject - 1 || if (eptr < md->end_subject) if (eptr < md->end_subject) if (eptr < md->start_subject) if (eptr >= md->end_subject || if (eptr >= md->end_subject || if (eptr >= md->end_subject || if (eptr >= md->end_subject || if (eptr >= md->end_subject || if (eptr >= md->end_subject || if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0) if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0) if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0) if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0) if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0) if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0) if (eptr >= md->end_subject || *eptr == '\n') if (eptr >= md->end_subject || c != *eptr) if (eptr >= md->end_subject || c != md->lcc[*eptr]) if (eptr >= md->end_subject || c == *eptr) if (eptr >= md->end_subject || c == md->lcc[*eptr]) if (eptr >= md->end_subject) if (eptr >= md->end_subject) if (eptr >= md->end_subject) if (eptr >= md->end_subject) if (eptr >= md->end_subject) if (eptr++ >= md->end_subject) if (i >= max || !match_ref (offset, eptr, length, md, ims)) if (i >= max || eptr >= md->end_subject || if (i >= max || eptr >= md->end_subject || if (i >= max || eptr >= md->end_subject || c != *eptr++) if (i >= max || eptr >= md->end_subject || c == *eptr++) if (i >= max || eptr >= md->end_subject) if (i >= max || eptr >= md->end_subject) if (is_subject && length > md->end_subject - p) if (isprint (c = *(p++))) if (length == 0) if (length > md->end_subject - eptr) if (length > md->end_subject - eptr) if (match (eptr, ecode + 3, offset_top, md, ims, NULL, if (match (eptr, ecode + 3, offset_top, md, ims, NULL, match_isgroup)) if (match (eptr, ecode + 3, offset_top, md, ims, NULL, match_isgroup)) if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, 0) || if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, 0) || if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, match_isgroup)) if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, match_isgroup)) if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, match_isgroup)) if (match (eptr, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr, next + 3, offset_top, md, ims, eptrb, match_isgroup)) if (match (eptr, next, offset_top, md, ims, eptrb, match_isgroup)) if (match (eptr, prev, offset_top, md, ims, eptrb, match_isgroup) || if (match (eptr, prev, offset_top, md, ims, eptrb, match_isgroup) || if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0)) if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0)) if (match_block.end_offset_top > offsetcount) if (match_block.offset_vector != NULL) if (match_block.offset_vector == NULL) if (max == 0) if (max == 0) if (max == 0) if (max == 0) if (max == 0) if (max == 0) if (max == 0) if (md->lcc[*ecode++] != md->lcc[*eptr++]) if (md->lcc[*ecode++] == md->lcc[*eptr++]) if (md->lcc[*p++] != md->lcc[*eptr++]) if (md->notbol && eptr == md->start_subject) if (md->notempty && eptr == md->start_match) if (md->noteol) if (md->noteol) if (min == max) if (min == max) if (min == max) if (min == max) if (min == max) if (min == max) if (min == max) if (min > 0) if (min > md->end_subject - eptr) if (min > md->end_subject - eptr) if (min > md->end_subject - eptr) if (minimize) if (minimize) if (minimize) if (minimize) if (minimize) if (minimize) if (minimize) if (number > 0) if (number > EXTRACT_BASIC_MAX) if (number > EXTRACT_BASIC_MAX) if (offset < md->offset_max) if (offset >= md->offset_max) if (offset_top <= offset) if (offsetcount < 2) if (offsetcount >= 4) if (op > OP_BRA) if (p > req_char_ptr) if (p >= end_subject) if (pp == req_char || pp == req_char2) if (re == NULL || subject == NULL || if (re->magic_number != MAGIC_NUMBER) if (re->max_match_size >= 0 if (re->top_backref > 0 && re->top_backref >= ocount / 3) if (req_char == req_char2) if (req_char >= 0) if (resetcount > offsetcount) if (save != stacksave) if (save == NULL) if (skipped_chars) if (start_match + bmtable[256] > end_subject) if (start_match > match_block.start_subject + start_offset) if (using_temporary_offsets) if (using_temporary_offsets) if certain parts of the pattern were not used. */ if the malloc fails ... there is no way of returning to the top level with implied in the second condition, because start_offset > 0. */ ims current /i, /m, and /s options ims the ims flags ims = (ims & ~PCRE_IMS) | ecode[4]; ims = ecode[1]; ims = original_ims; ims = re->options & (PCRE_CASELESS | PCRE_MULTILINE | PCRE_DOTALL); in the pattern. */ in the subject string, while eptrb holds the value of eptr at the start of the initialize them to avoid reading uninitialized locations. */ inline, and there are *still* stupid compilers about that don't like indented inside the group. int int *offsets; int *save; int c; int first_char = -1; int flags; int length; int length; int length; int length; int min, max, ctype; int number = *prev - OP_BRA; int number = op - OP_BRA; int offset = (ecode[1] << 9) | (ecode[2] << 1); /* Doubled reference number */ int offset = (ecode[4] << 9) | (ecode[5] << 1); /* Doubled reference number */ int offset; int offset; int offset; int offset_top; int offsetcount; int op = (int) *ecode; int options; int rc; int req_char = -1; int req_char2 = -1; int resetcount, ocount; 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 skipped_chars = 0; int stacksave[15]; int start_offset; is a bit large to put on the stack, but using malloc for small numbers is_subject TRUE if printing from within md->start_subject it as matched, any number of times (otherwise there could be infinite item to see if there is repeat information following. The code is similar item to see if there is repeat information following. Then obey similar last bracketed group - used for breaking infinite loops matching zero-length later in the subject; otherwise the test starts at the match point. This length length of subject string (may contain binary zeros) length length to be matched length number to print length = (offset >= offset_top || md->offset_vector[offset] < 0) ? length = md->end_subject - p; level without recursing. Otherwise, if minimizing, keep trying the rest of level without recursing. Otherwise, if minimizing, keep trying the rest of loop. */ loops). */ main loop. */ majority of cases. It will be suboptimal when the case flag changes in a regex mark, since extracts may have been taken during the assertion. */ mark, since extracts may have been taken. */ match (eptr, ecode + 3, offset_top, md, ims, eptrb, 0)) match (eptr, ecode + 3, offset_top, md, ims, eptrb, 0)) match (eptr, ecode, offset_top, md, ims, eptrb, flags) match (eptr, prev, offset_top, md, ims, eptrb, match_isgroup)) match (eptr, prev, offset_top, md, ims, eptrb, match_isgroup)) match_block.ctypes = re->tables + ctypes_offset; match_block.end_subject = match_block.start_subject + length; match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; match_block.errorcode = PCRE_ERROR_NOMATCH; /* Default error */ match_block.errorcode == PCRE_ERROR_NOMATCH && match_block.lcc = re->tables + lcc_offset; match_block.lcc[*start_match] != first_char) match_block.notbol = (options & PCRE_NOTBOL) != 0; match_block.notempty = (options & PCRE_NOTEMPTY) != 0; match_block.noteol = (options & PCRE_NOTEOL) != 0; match_block.offset_end = ocount; match_block.offset_max = (2 * ocount) / 3; match_block.offset_overflow = FALSE; match_block.offset_overflow = TRUE; match_block.offset_vector = (int *) (pcre_malloc) (ocount * sizeof (int)); match_block.offset_vector = offsets; match_block.start_match = start_match; match_block.start_pattern = re->code; match_block.start_subject = (const uschar *) subject; match_condassert - this is an assertion condition match_condassert | match_isgroup)) match_data *md; match_data *md; match_data *md; match_data match_block; match_isgroup - this is the start of a bracketed group match_isgroup); match_ref (offset, eptr, length, md, ims) matches, we carry on as at the end of a normal bracket, leaving the subject matching won't pass the KET for an assertion. If any one branch matches, matching won't pass the KET for this kind of subpattern. If any one branch max = (ecode[1] << 8) + ecode[2]; max = (ecode[1] << 8) + ecode[2]; max = (ecode[1] << 8) + ecode[2]; max = (ecode[3] << 8) + ecode[4]; max = (ecode[3] << 8) + ecode[4]; max = INT_MAX; max = INT_MAX; max = INT_MAX; max = INT_MAX; max = INT_MAX; max = INT_MAX; max = INT_MAX; max = rep_max[c]; /* zero for max => infinity */ max = rep_max[c]; /* zero for max => infinity */ max = rep_max[c]; /* zero for max => infinity */ max = rep_max[c]; /* zero for max => infinity */ max = rep_max[c]; /* zero for max => infinity */ max, eptr)); max, eptr)); maximum. Alternatively, if maximizing, find the maximum number of maximum. Alternatively, if maximizing, find the maximum number of may be wrong. */ md pointer to "static" info for the match md pointer to matching data block, if is_subject is TRUE md points to match data block md->end_match_ptr = eptr; /* For ONCE */ md->end_match_ptr = eptr; /* Record where we ended */ md->end_offset_top = offset_top; /* and how many extracts were taken */ md->end_offset_top = offset_top; md->end_subject - eptr + 1 : md->errorcode = PCRE_ERROR_UNKNOWN_NODE; md->offset_overflow = TRUE; md->offset_vector[md->offset_end - i] = save[i]; md->offset_vector[md->offset_end - number] = eptr - md->start_subject; md->offset_vector[md->offset_end - number] = save_offset3; md->offset_vector[md->offset_end - number]; md->offset_vector[offset + 1] - md->offset_vector[offset]; md->offset_vector[offset + 1] = eptr - md->start_subject; md->offset_vector[offset + 1] = save_offset2; md->offset_vector[offset] = md->offset_vector[offset] = save_offset1; memcpy (offsets + 2, match_block.offset_vector + 2, min = (ecode[1] << 8) + ecode[2]; min = (ecode[1] << 8) + ecode[2]; min = 0; min = 0; min = 0; min = max = (ecode[1] << 8) + ecode[2]; min = max = (ecode[1] << 8) + ecode[2]; min = max = (ecode[1] << 8) + ecode[2]; min = max = 1; min = rep_min[c]; /* Pick up values from tables; */ min = rep_min[c]; /* Pick up values from tables; */ min = rep_min[c]; /* Pick up values from tables; */ min = rep_min[c]; /* Pick up values from tables; */ min = rep_min[c]; /* Pick up values from tables; */ minima. */ minimize = (*ecode == OP_CRMINRANGE); minimize = (*ecode == OP_CRMINRANGE); minimize = (c & 1) != 0; minimize = (c & 1) != 0; minimize = (c & 1) != 0; minimize = (c & 1) != 0; minimize = (c & 1) != 0; minimize = *ecode == OP_MINUPTO; minimize = *ecode == OP_NOTMINUPTO; minimize = *ecode == OP_TYPEMINUPTO; minimize = TRUE; minimum number of matches are present. If min = max, continue at the same minimum number of matches are present. If min = max, continue at the same misrepresented as being the original software. move back, this match function fails. */ mustn't change the current values of the data slot, because they may be set need to recurse. */ never be used unless previously set, but they get saved and restored, and so we never set for an anchored regular expression, but the anchoring may be forced newline unless endonly is set, else end of subject unless noteol is set. */ newptrb.prev = eptrb; newptrb.saved_eptr = eptr; next += (next[1] << 8) + next[2]; next += (next[1] << 8) + next[2]; non-capturing bracket. Don't worry about setting the flag for the error case number = (ecode[4] << 8) | ecode[5]; number = (prev[4] << 8) | prev[5]; number from a dummy opcode at the start. */ number, then move along the subject till after the recursive match, ocount = offsetcount - (offsetcount % 3); ocount = re->top_backref * 3 + 3; of (?ims) items in the pattern. They are kept in a local variable so that of 3. */ of subject left; this ensures that every attempt at a match fails. We offset index into the offset vector offset = number << 1; offset = number << 1; offset_top current top pointer offset_top = md->end_offset_top; offset_top = md->end_offset_top; offset_top = md->end_offset_top; offset_top = offset + 2; offset_top, md, ims, eptrb, match_isgroup); offsetcount the number of elements in the vector offsets points to a vector of ints to be filled in with offsets offsets[0] = start_match - match_block.start_subject; offsets[1] = match_block.end_match_ptr - match_block.start_subject; op = OP_BRA; opcode. */ optimization can save a huge amount of backtracking in patterns with nested option for each character match. Maybe that wouldn't add very much to the options option bits p points to characters p--; p--; past the end if there is only one branch, but that's OK because that is pchars (ecode, length, FALSE, md); pchars (eptr, 16, TRUE, md); pchars (eptr, length, TRUE, md); pchars (eptr, length, TRUE, md); pchars (p, length, FALSE, md); pchars (p, length, is_subject, md) pchars (start_match, end_subject - start_match, TRUE, &match_block); pcre_exec (re, extra, subject, length, start_offset, options, offsets, offsetcount) place we found it at last time. */ pointer. */ portions of the string if it matches. Two elements in the vector are set for pre-processor statements. I suppose it's only been 10 years... */ preceded by BRAZERO or BRAMINZERO. */ preceding bracket, in the appropriate order. */ preceding bracket, in the appropriate order. We need to reset any options printf (" against backref "); printf (" against pattern "); printf ("%c", c); printf (">>>> Match against: "); printf (">>>>> Skipped %d chars to reach first character\n", printf ("\\x%02x", c); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("end bracket %d", number); printf ("matching subject "); printf ("matching subject "); printf ("matching subject against pattern "); printf ("matching subject "); printf ("start bracket %d subject=", number); rc = 0; rc = match (eptr, md->start_pattern, offset_top, md, ims, eptrb, rc = match_block.offset_overflow ? 0 : match_block.end_offset_top / 2; register const uschar *ecode; register const uschar *eptr; register const uschar *eptr; register const uschar *p = start_match + ((first_char >= 0) ? 1 : 0); register int *iend = iptr + resetcount; register int *iend = iptr - resetcount / 2 + 1; register int *iptr = match_block.offset_vector + ocount; register int *iptr = match_block.offset_vector; register int c = *start_match; register int c; register int i; register int length = ecode[1]; register int pp = *p++; repeat it in the interests of efficiency. */ repeat limits are compiled as a number of copies, with the optional ones req_char = re->req_char; req_char2 = ((re->options & (PCRE_CASELESS | PCRE_ICHANGED)) != 0) ? req_char_ptr = p; resetcount = 2 + re->top_bracket * 2; resetcount = ocount; restoring at the exit of a group is easy. */ restrictions: return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return FALSE; return PCRE_ERROR_BADMAGIC; return PCRE_ERROR_BADOPTION; return PCRE_ERROR_NOMATCH; return PCRE_ERROR_NOMEMORY; return PCRE_ERROR_NULL; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return TRUE; return match (eptr, return match (eptr, ecode + 3, offset_top, md, ims, eptrb, match_isgroup); return match_block.errorcode; return rc; save = (int *) (pcre_malloc) ((c + 1) * sizeof (int)); save = stacksave; save = stacksave; save[i] = md->offset_vector[md->offset_end - i]; seems expensive. As a compromise, the stack is used when there are fewer share code. This is very similar to the code for single characters, but we similar code to character type repeats - written out again for speed. since matching characters is likely to be quite common. First, ensure the since matching characters is likely to be quite common. First, ensure the skipped_chars += bmtable[*start_match], skipped_chars += bmtable[256] - 1; skipped_chars -= bmtable[256] - 1; skipped_chars); skipped_chars++, skipped_chars++, skipped_chars++, skipped_chars++, stack of such pointers, to be re-instated at the end of the group when we hit stack, for holding the values of the subject pointer at the start of each start of each branch to move the current point backwards, so the code at start_bits = extra->data.start_bits; start_match += bmtable[*start_match]; start_match += bmtable[256] - 1; start_match -= bmtable[256] - 1; start_match = (const uschar *) subject + length - re->max_match_size; start_match++ < end_subject); start_match++; start_match++; start_match++; start_match++; start_offset where to start in the subject string startline = (re->options & PCRE_STARTLINE) != 0; static BOOL static BOOL static const char rep_max[] = static const char rep_min[] = static void strings. struct eptrblock *prev; studied, there may be a bitmap of possible first characters. */ subject points to the subject string subject if the requested. subpattern - to break infinite loops. */ subpattern, so as to detect when an empty string has been matched by a subsequent match. */ such there are (offset_top records the completed total) so we just have supersede any condition above with which it is incompatible. switch (*ecode) switch (*ecode) switch (ctype) switch (ctype) switch (ctype) switch (op) test once at the start (i.e. keep it out of the loop). */ than 16 values to store; otherwise malloc is used. A problem is what to do than the number of characters left in the string, so the match fails. that "continue" in the code above comes out to here to repeat the main that changed within the bracket before re-running it, so check the next that it may occur zero times. It may repeat infinitely, or not at all - the assertion is true. Lookbehind assertions have an OP_REVERSE item at the the closing ket. When match() is called in other circumstances, we don't add to the code for a repeated single character, but I haven't found a nice way of the current subject position in the working slot at the top of the vector. We the expression and advancing one matching character if failing, up to the the expression and advancing one matching character if failing, up to the the external pcre header. */ the file Tech.Notes for some information on the internals. the final argument TRUE causes it to stop at the end of an assertion. */ the group. */ the length of the reference string explicitly rather than passing the the loop runs just once. */ the minimum number of bytes before we start. */ the number from a dummy opcode at the start. */ the point in the subject string is not moved back. Thus there can never be the pointer while it matches the class. */ the same bracket. the stack. */ the start hasn't passed this character yet. */ the subject. */ the subject. */ there were too many extractions, set the return code to zero. In the case this level is identical to the lookahead case. */ this makes a huge difference to execution time when there aren't many brackets those back references that we can. In this case there need not be overflow time taken, but character matching *is* what this is all about... */ to save all the potential data. There may be up to 99 such values, which to that for character classes, but repeated for efficiency. Then obey two branches. If the condition is false, skipping the first branch takes us typedef struct eptrblock unless PCRE_CASELESS was given or the casing state changes within the regex. unlimited repeats that aren't going to match. We don't know what the state of unsigned long int ims = 0; unsigned long int ims; unsigned long int ims; unsigned long int original_ims = ims; /* Save for resetting on ')' */ up quickly if there are fewer than the minimum number of characters left in up quickly if there are fewer than the minimum number of characters left in using_temporary_offsets = TRUE; values of the final offsets, in case they were set by a previous iteration of we just need to set up the whole thing as substring 0 before returning. If where we had to get some local store to hold offsets for backreferences, copy while (!anchored && while (*ecode == OP_ALT) while (*ecode == OP_ALT); while (*ecode == OP_ALT); while (*ecode == OP_ALT); while (*ecode == OP_ALT); while (*ecode == OP_ALT); while (*ecode == OP_ALT); while (*ecode == OP_ALT); while (*ecode == OP_ALT); while (*next == OP_ALT); while (*next == OP_ALT); while (--iptr >= iend) while (eptr >= pp) while (eptr >= pp) while (eptr >= pp) while (eptr >= pp) while (eptr >= pp) while (eptr >= pp) while (eptr >= pp) while (iptr < iend) while (length-- > 0) while (length-- > 0) while (length-- > 0) while (length-- > 0) while (length-- > 0) while (p < end_subject) while (p < end_subject) while (start_match < end_subject && while (start_match < end_subject && *start_match != first_char) while (start_match < end_subject && start_match[-1] != '\n') while (start_match < end_subject) while (start_match < end_subject) { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { {0, 0, 0, 0, 1, 1}; {0, 0, 1, 1, 0, 0}; } /* End of main loop */ } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } kbuild-3686/src/oldsed/testsuite/tst-boost.c0000664000175000017500000001065115053010105021101 0ustar locutuslocutus/* Regular expression tests. Copyright (C) 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2003. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #ifdef HAVE_MCHECK_H #include #endif #include #include #include #include void frob_escapes (char *src, int pattern) { char *dst; for (dst = src; *src != '\0'; dst++, src++) { if (*src == '\\') { switch (src[1]) { case 't': src++; *dst = '\t'; continue; case 'n': src++; *dst = '\n'; continue; case 'r': src++; *dst = '\r'; continue; case '\\': case '^': case '{': case '|': case '}': if (!pattern) { src++; *dst = *src; continue; } break; } } if (src != dst) *dst = *src; } *dst = '\0'; } int main (int argc, char **argv) { int ret = 0, n; char *line = NULL; size_t line_len = 0; ssize_t len; FILE *f; char *pattern, *string; int flags = REG_EXTENDED; int eflags = 0; regex_t re; regmatch_t rm[20]; #ifdef HAVE_MCHECK_H mtrace (); #endif if (argc < 2) { fprintf (stderr, "Missing test filename\n"); return 1; } f = fopen (argv[1], "r"); if (f == NULL) { fprintf (stderr, "Couldn't open %s\n", argv[1]); return 1; } while ((len = getline (&line, &line_len, f)) > 0) { char *p, *q; int i; if (line[len - 1] == '\n') line[--len] = '\0'; puts (line); if (line[0] == ';') continue; if (line[0] == '\0') continue; if (line[0] == '-') { if (strstr (line, "REG_BASIC")) flags = 0; else flags = REG_EXTENDED; if (strstr (line, "REG_ICASE")) flags |= REG_ICASE; if (strstr (line, "REG_NEWLINE")) flags |= REG_NEWLINE; eflags = 0; if (strstr (line, "REG_NOTBOL")) eflags |= REG_NOTBOL; if (strstr (line, "REG_NOTEOL")) eflags |= REG_NOTEOL; continue; } pattern = line + strspn (line, " \t"); if (*pattern == '\0') continue; p = pattern + strcspn (pattern, " \t"); if (*p == '\0') continue; *p++ = '\0'; string = p + strspn (p, " \t"); if (*string == '\0') continue; if (*string == '"') { string++; p = strchr (string, '"'); if (p == NULL) continue; *p++ = '\0'; } else { p = string + strcspn (string, " \t"); if (*string == '!') string = NULL; else if (*p == '\0') continue; else *p++ = '\0'; } frob_escapes (pattern, 1); if (string != NULL) frob_escapes (string, 0); n = regcomp (&re, pattern, flags); if (n != 0) { if (string != NULL) { char buf[500]; regerror (n, &re, buf, sizeof (buf)); printf ("FAIL regcomp unexpectedly failed: %s\n", buf); ret = 1; } continue; } else if (string == NULL) { regfree (&re); puts ("FAIL regcomp unpexpectedly succeeded"); ret = 1; continue; } if (regexec (&re, string, 20, rm, eflags)) { for (i = 0; i < 20; ++i) { rm[i].rm_so = -1; rm[i].rm_eo = -1; } } regfree (&re); for (i = 0; i < 20 && *p != '\0'; ++i) { int rm_so, rm_eo; rm_so = strtol (p, &q, 10); if (p == q) break; p = q; rm_eo = strtol (p, &q, 10); if (p == q) break; p = q; if (rm[i].rm_so != rm_so || rm[i].rm_eo != rm_eo) { printf ("FAIL rm[%d] %d..%d != expected %d..%d\n", i, rm[i].rm_so, rm[i].rm_eo, rm_so, rm_eo); ret = 1; break; } } } free (line); fclose (f); return ret; } kbuild-3686/src/oldsed/testsuite/dc.good0000664000175000017500000000003215053010105020227 0ustar locutuslocutus31 March 2002 1.6A09E667A kbuild-3686/src/oldsed/testsuite/sep.inp0000664000175000017500000000027315053010105020275 0ustar locutuslocutusmiss mary mack mack//mack/ran down/the track track track slashes\aren't%used enough/in/casual-conversation/// possibly sentences would be more attractive if they ended in two slashes// kbuild-3686/src/oldsed/testsuite/SPENCER.tests0000664000175000017500000003413015053010105021160 0ustar locutuslocutus# regular expression test set # Lines are at least three fields, separated by one or more tabs. "" stands # for an empty field. First field is an RE. Second field is flags. If # C flag given, regcomp() is expected to fail, and the third field is the # error name (minus the leading REG_). # # Otherwise it is expected to succeed, and the third field is the string to # try matching it against. If there is no fourth field, the match is # expected to fail. If there is a fourth field, it is the substring that # the RE is expected to match. If there is a fifth field, it is a comma- # separated list of what the subexpressions should match, with - indicating # no match for that one. In both the fourth and fifth fields, a (sub)field # starting with @ indicates that the (sub)expression is expected to match # a null string followed by the stuff after the @; this provides a way to # test where null strings match. The character `N' in REs and strings # is newline, `S' is space, `T' is tab, `Z' is NUL. # # The full list of flags: # - placeholder, does nothing # b RE is a BRE, not an ERE # & try it as both an ERE and a BRE # C regcomp() error expected, third field is error name # i REG_ICASE # m ("mundane") REG_NOSPEC # s REG_NOSUB (not really testable) # n REG_NEWLINE # ^ REG_NOTBOL # $ REG_NOTEOL # # REG_STARTEND (see below) # p REG_PEND # # For REG_STARTEND, the start/end offsets are those of the substring # enclosed in (). # basics a & a a abc & abc abc abc|de - abc abc a|b|c - abc a # parentheses and perversions thereof a(b)c - abc abc a\(b\)c b abc abc a( C EPAREN a( b a( a( a\( - a( a( a\( bC EPAREN a\(b bC EPAREN a(b C EPAREN a(b b a(b a(b # gag me with a right parenthesis -- 1003.2 goofed here (my fault, partly) a) - a) a) ) - ) ) # end gagging (in a just world, those *should* give EPAREN) a) b a) a) a\) bC EPAREN \) bC EPAREN a()b - ab ab a\(\)b b ab ab # anchoring and REG_NEWLINE ^abc$ & abc abc a^b - a^b a^b b a^b a^b a$b - a$b a$b b a$b a$b ^ & abc @abc $ & abc @ ^$ & "" @ $^ - "" @ \($\)\(^\) b "" @ # stop retching, those are legitimate (although disgusting) ^^ - "" @ $$ - "" @ b$ & abNc b$ &n abNc b ^b$ & aNbNc ^b$ &n aNbNc b ^$ &n aNNb @Nb ^$ n abc ^$ n abcN @ $^ n aNNb @Nb \($\)\(^\) bn aNNb @Nb ^^ n^ aNNb @Nb $$ n aNNb @NN ^a ^ a a$ $ a ^a ^n aNb ^b ^n aNb b a$ $n bNa b$ $n bNa b a*(^b$)c* - b b a*\(^b$\)c* b b b # certain syntax errors and non-errors | C EMPTY | b | | * C BADRPT * b * * + C BADRPT ? C BADRPT "" &C EMPTY () - abc @abc \(\) b abc @abc a||b C EMPTY |ab C EMPTY ab| C EMPTY (|a)b C EMPTY (a|)b C EMPTY (*a) C BADRPT (+a) C BADRPT (?a) C BADRPT ({1}a) C BADRPT \(\{1\}a\) bC BADRPT (a|*b) C BADRPT (a|+b) C BADRPT (a|?b) C BADRPT (a|{1}b) C BADRPT ^* C BADRPT ^* b * * ^+ C BADRPT ^? C BADRPT ^{1} C BADRPT ^\{1\} bC BADRPT # metacharacters, backslashes a.c & abc abc a[bc]d & abd abd a\*c & a*c a*c a\\b & a\b a\b a\\\*b & a\*b a\*b # The following test is wrong. Using \b in an BRE or ERE is undefined. # a\bc & abc abc a\ &C EESCAPE a\\bc & a\bc a\bc \{ bC BADRPT a\[b & a[b a[b a[b &C EBRACK # trailing $ is a peculiar special case for the BRE code a$ & a a a$ & a$ a\$ & a a\$ & a$ a$ a\\$ & a a\\$ & a$ a\\$ & a\$ a\\$ & a\ a\ # back references, ugh a\(b\)\2c bC ESUBREG a\(b\1\)c bC ESUBREG a\(b*\)c\1d b abbcbbd abbcbbd bb a\(b*\)c\1d b abbcbd a\(b*\)c\1d b abbcbbbd ^\(.\)\1 b abc a\([bc]\)\1d b abcdabbd abbd b a\(\([bc]\)\2\)*d b abbccd abbccd a\(\([bc]\)\2\)*d b abbcbd # actually, this next one probably ought to fail, but the spec is unclear a\(\(b\)*\2\)*d b abbbd abbbd # here is a case that no NFA implementation does right \(ab*\)[ab]*\1 b ababaaa ababaaa a # check out normal matching in the presence of back refs \(a\)\1bcd b aabcd aabcd \(a\)\1bc*d b aabcd aabcd \(a\)\1bc*d b aabd aabd \(a\)\1bc*d b aabcccd aabcccd \(a\)\1bc*[ce]d b aabcccd aabcccd ^\(a\)\1b\(c\)*cd$ b aabcccd aabcccd # ordinary repetitions ab*c & abc abc ab+c - abc abc ab?c - abc abc a\(*\)b b a*b a*b a\(**\)b b ab ab a\(***\)b bC BADRPT *a b *a *a **a b a a ***a bC BADRPT # the dreaded bounded repetitions # The following two tests are not correct: #{ & { { #{abc & {abc {abc # '{' is always a special char outside bracket expressions. So test ony BRE: { b { { {abc b {abc {abc {1 C BADRPT {1} C BADRPT # Same reason as for the two tests above: #a{b & a{b a{b a{b b a{b a{b a{1}b - ab ab a\{1\}b b ab ab a{1,}b - ab ab a\{1,\}b b ab ab a{1,2}b - aab aab a\{1,2\}b b aab aab a{1 C EBRACE a\{1 bC EBRACE a{1a C EBRACE a\{1a bC EBRACE a{1a} C BADBR a\{1a\} bC BADBR # These four tests checks for undefined behavior. Our implementation does # something different. #a{,2} - a{,2} a{,2} #a\{,2\} bC BADBR #a{,} - a{,} a{,} #a\{,\} bC BADBR a{1,x} C BADBR a\{1,x\} bC BADBR a{1,x C EBRACE a\{1,x bC EBRACE # These two tests probably fails due to an arbitrary limit on the number of # repetitions in the other implementation. #a{300} C BADBR #a\{300\} bC BADBR a{1,0} C BADBR a\{1,0\} bC BADBR ab{0,0}c - abcac ac ab\{0,0\}c b abcac ac ab{0,1}c - abcac abc ab\{0,1\}c b abcac abc ab{0,3}c - abbcac abbc ab\{0,3\}c b abbcac abbc ab{1,1}c - acabc abc ab\{1,1\}c b acabc abc ab{1,3}c - acabc abc ab\{1,3\}c b acabc abc ab{2,2}c - abcabbc abbc ab\{2,2\}c b abcabbc abbc ab{2,4}c - abcabbc abbc ab\{2,4\}c b abcabbc abbc ((a{1,10}){1,10}){1,10} - a a a,a # multiple repetitions # Wow, there is serious disconnect here. The ERE grammar is like this: # ERE_expression : one_char_or_coll_elem_ERE # | '^' # | '$' # | '(' extended_reg_exp ')' # | ERE_expression ERE_dupl_symbol # ; # where ERE_dupl_symbol is any of the repetition methods. It is clear from # this that consecutive repetition is OK. On top of this, the one test not # marked as failing must fail. For BREs the situation is different, so we # use the four tests. #a** &C BADRPT a** bC BADRPT #a++ C BADRPT #a?? C BADRPT #a*+ C BADRPT #a*? C BADRPT #a+* C BADRPT #a+? C BADRPT #a?* C BADRPT #a?+ C BADRPT #a{1}{1} C BADRPT #a*{1} C BADRPT #a+{1} C BADRPT #a?{1} C BADRPT #a{1}* C BADRPT #a{1}+ C BADRPT #a{1}? C BADRPT #a*{b} - a{b} a{b} a\{1\}\{1\} bC BADRPT a*\{1\} bC BADRPT a\{1\}* bC BADRPT # brackets, and numerous perversions thereof a[b]c & abc abc a[ab]c & abc abc a[^ab]c & adc adc a[]b]c & a]c a]c a[[b]c & a[c a[c a[-b]c & a-c a-c a[^]b]c & adc adc a[^-b]c & adc adc a[b-]c & a-c a-c a[b &C EBRACK a[] &C EBRACK a[1-3]c & a2c a2c a[3-1]c &C ERANGE a[1-3-5]c &C ERANGE a[[.-.]--]c & a-c a-c # I don't thing the error value should be ERANGE since a[1-] would be # valid, too. Expect EBRACK. #a[1- &C ERANGE a[1- &C EBRACK a[[. &C EBRACK a[[.x &C EBRACK a[[.x. &C EBRACK a[[.x.] &C EBRACK a[[.x.]] & ax ax a[[.x,.]] &C ECOLLATE # This test is invalid. "one" is no collating symbol in any standardized # locale. # a[[.one.]]b & a1b a1b a[[.notdef.]]b &C ECOLLATE a[[.].]]b & a]b a]b a[[:alpha:]]c & abc abc a[[:notdef:]]c &C ECTYPE a[[: &C EBRACK a[[:alpha &C EBRACK a[[:alpha:] &C EBRACK a[[:alpha,:] &C ECTYPE a[[:]:]]b &C ECTYPE a[[:-:]]b &C ECTYPE a[[:alph:]] &C ECTYPE a[[:alphabet:]] &C ECTYPE [[:alnum:]]+ - -%@a0X- a0X [[:alpha:]]+ - -%@aX0- aX [[:blank:]]+ - aSSTb SST [[:cntrl:]]+ - aNTb NT [[:digit:]]+ - a019b 019 [[:graph:]]+ - Sa%bS a%b [[:lower:]]+ - AabC ab [[:print:]]+ - NaSbN aSb [[:punct:]]+ - S%-&T %-& [[:space:]]+ - aSNTb SNT [[:upper:]]+ - aBCd BC [[:xdigit:]]+ - p0f3Cq 0f3C a[[=b=]]c & abc abc a[[= &C EBRACK a[[=b &C EBRACK a[[=b= &C EBRACK a[[=b=] &C EBRACK a[[=b,=]] &C ECOLLATE # This test is invalid. "one" is no collating symbol in any standardized # locale. #a[[=one=]]b & a1b a1b # complexities a(((b)))c - abc abc a(b|(c))d - abd abd a(b*|c)d - abbd abbd # just gotta have one DFA-buster, of course a[ab]{20} - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab # and an inline expansion in case somebody gets tricky a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab] - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab # and in case somebody just slips in an NFA... a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night) - aaaaabaaaabaaaabaaaabweeknights aaaaabaaaabaaaabaaaabweeknights # fish for anomalies as the number of states passes 32 12345678901234567890123456789 - a12345678901234567890123456789b 12345678901234567890123456789 123456789012345678901234567890 - a123456789012345678901234567890b 123456789012345678901234567890 1234567890123456789012345678901 - a1234567890123456789012345678901b 1234567890123456789012345678901 12345678901234567890123456789012 - a12345678901234567890123456789012b 12345678901234567890123456789012 123456789012345678901234567890123 - a123456789012345678901234567890123b 123456789012345678901234567890123 # and one really big one, beyond any plausible word width 1234567890123456789012345678901234567890123456789012345678901234567890 - a1234567890123456789012345678901234567890123456789012345678901234567890b 1234567890123456789012345678901234567890123456789012345678901234567890 # fish for problems as brackets go past 8 [ab][cd][ef][gh][ij][kl][mn] - xacegikmoq acegikm [ab][cd][ef][gh][ij][kl][mn][op] - xacegikmoq acegikmo [ab][cd][ef][gh][ij][kl][mn][op][qr] - xacegikmoqy acegikmoq [ab][cd][ef][gh][ij][kl][mn][op][q] - xacegikmoqy acegikmoq # subtleties of matching abc & xabcy abc a\(b\)?c\1d b acd aBc i Abc Abc a[Bc]*d i abBCcd abBCcd 0[[:upper:]]1 &i 0a1 0a1 0[[:lower:]]1 &i 0A1 0A1 a[^b]c &i abc a[^b]c &i aBc a[^b]c &i adc adc [a]b[c] - abc abc [a]b[a] - aba aba [abc]b[abc] - abc abc [abc]b[abd] - abd abd a(b?c)+d - accd accd (wee|week)(knights|night) - weeknights weeknights (we|wee|week|frob)(knights|night|day) - weeknights weeknights a[bc]d - xyzaaabcaababdacd abd a[ab]c - aaabc abc abc s abc abc () s abc @abc a* & b @b # Let's have some fun -- try to match a C comment. # first the obvious, which looks okay at first glance... /\*.*\*/ - /*x*/ /*x*/ # but... /\*.*\*/ - /*x*/y/*z*/ /*x*/y/*z*/ # okay, we must not match */ inside; try to do that... /\*([^*]|\*[^/])*\*/ - /*x*/ /*x*/ /\*([^*]|\*[^/])*\*/ - /*x*/y/*z*/ /*x*/ # but... /\*([^*]|\*[^/])*\*/ - /*x**/y/*z*/ /*x**/y/*z*/ # and a still fancier version, which does it right (I think)... /\*([^*]|\*+[^*/])*\*+/ - /*x*/ /*x*/ /\*([^*]|\*+[^*/])*\*+/ - /*x*/y/*z*/ /*x*/ /\*([^*]|\*+[^*/])*\*+/ - /*x**/y/*z*/ /*x**/ /\*([^*]|\*+[^*/])*\*+/ - /*x****/y/*z*/ /*x****/ /\*([^*]|\*+[^*/])*\*+/ - /*x**x*/y/*z*/ /*x**x*/ /\*([^*]|\*+[^*/])*\*+/ - /*x***x/y/*z*/ /*x***x/y/*z*/ # subexpressions .* - abc abc - a(b)(c)d - abcd abcd b,c a(((b)))c - abc abc b,b,b a(b|(c))d - abd abd b,- a(b*|c|e)d - abbd abbd bb a(b*|c|e)d - acd acd c a(b*|c|e)d - ad ad @d a(b?)c - abc abc b a(b?)c - ac ac @c a(b+)c - abc abc b a(b+)c - abbbc abbbc bbb a(b*)c - ac ac @c (a|ab)(bc([de]+)f|cde) - abcdef abcdef a,bcdef,de # the regression tester only asks for 9 subexpressions a(b)(c)(d)(e)(f)(g)(h)(i)(j)k - abcdefghijk abcdefghijk b,c,d,e,f,g,h,i,j a(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)l - abcdefghijkl abcdefghijkl b,c,d,e,f,g,h,i,j,k a([bc]?)c - abc abc b a([bc]?)c - ac ac @c a([bc]+)c - abc abc b a([bc]+)c - abcc abcc bc a([bc]+)bc - abcbc abcbc bc a(bb+|b)b - abb abb b a(bbb+|bb+|b)b - abb abb b a(bbb+|bb+|b)b - abbb abbb bb a(bbb+|bb+|b)bb - abbb abbb b (.*).* - abcdef abcdef abcdef (a*)* - bc @b @b # do we get the right subexpression when it is used more than once? a(b|c)*d - ad ad - a(b|c)*d - abcd abcd c a(b|c)+d - abd abd b a(b|c)+d - abcd abcd c a(b|c?)+d - ad ad @d a(b|c?)+d - abcd abcd c a(b|c){0,0}d - ad ad - a(b|c){0,1}d - ad ad - a(b|c){0,1}d - abd abd b a(b|c){0,2}d - ad ad - a(b|c){0,2}d - abcd abcd c a(b|c){0,}d - ad ad - a(b|c){0,}d - abcd abcd c a(b|c){1,1}d - abd abd b a(b|c){1,1}d - acd acd c a(b|c){1,2}d - abd abd b a(b|c){1,2}d - abcd abcd c a(b|c){1,}d - abd abd b a(b|c){1,}d - abcd abcd c a(b|c){2,2}d - acbd acbd b a(b|c){2,2}d - abcd abcd c a(b|c){2,4}d - abcd abcd c a(b|c){2,4}d - abcbd abcbd b a(b|c){2,4}d - abcbcd abcbcd c a(b|c){2,}d - abcd abcd c a(b|c){2,}d - abcbd abcbd b a(b+|((c)*))+d - abd abd b,-,- a(b+|((c)*))+d - abcd abcd c,c,c # check out the STARTEND option [abc] &# a(b)c b [abc] &# a(d)c [abc] &# a(bc)d b [abc] &# a(dc)d c . &# a()c b.*c &# b(bc)c bc b.* &# b(bc)c bc .*c &# b(bc)c bc # plain strings, with the NOSPEC flag abc m abc abc abc m xabcy abc abc m xyz a*b m aba*b a*b a*b m ab "" mC EMPTY # cases involving NULs aZb & a a aZb &p a aZb &p# (aZb) aZb aZ*b &p# (ab) ab a.b &# (aZb) aZb a.* &# (aZb)c aZb # word boundaries (ick) [[:<:]]a & a a [[:<:]]a & ba [[:<:]]a & -a a a[[:>:]] & a a a[[:>:]] & ab a[[:>:]] & a- a [[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc abc [[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc-q abc [[:<:]]a.c[[:>:]] & axc-dayc-dazce-abc axc [[:<:]]b.c[[:>:]] & a_bxc-byc_d-bzc-q bzc [[:<:]].x..[[:>:]] & y_xa_-_xb_y-_xc_-axdc _xc_ [[:<:]]a_b[[:>:]] & x_a_b # past problems, and suspected problems (A[1])|(A[2])|(A[3])|(A[4])|(A[5])|(A[6])|(A[7])|(A[8])|(A[9])|(A[A]) - A1 A1 abcdefghijklmnop i abcdefghijklmnop abcdefghijklmnop abcdefghijklmnopqrstuv i abcdefghijklmnopqrstuv abcdefghijklmnopqrstuv (ALAK)|(ALT[AB])|(CC[123]1)|(CM[123]1)|(GAMC)|(LC[23][EO ])|(SEM[1234])|(SL[ES][12])|(SLWW)|(SLF )|(SLDT)|(VWH[12])|(WH[34][EW])|(WP1[ESN]) - CC11 CC11 CC[13]1|a{21}[23][EO][123][Es][12]a{15}aa[34][EW]aaaaaaa[X]a - CC11 CC11 Char \([a-z0-9_]*\)\[.* b Char xyz[k Char xyz[k xyz a?b - ab ab -\{0,1\}[0-9]*$ b -5 -5 a*a*a*a*a*a*a* & aaaaaa aaaaaa (\b){0} - x @x - \(\b\)\{0,0\} b abc @abc - a(\b){0}c - ac ac - a(.*)b(\1){0}c - abc abc @bc,- a(.*)b(\1){0}c - axbc axbc x,- a\(\(b*\)\)c\1d b abbcbbd abbcbbd bb,bb a\(\([bc]\)\)\2d b abcdabbd abbd b,b a\(\(\(\([bc]\)\)\3\)\)*d b abbccd abbccd cc,cc,c,c a(b)(c)d - abcd abcd b,c a(((b)))c - abc abc b,b,b a(((b|(((c))))))d - abd abd b,b,b,-,-,- a(((b*|c|e)))d - abbd abbd bb,bb,bb a((b|c)){0,0}d - ad ad -,- a((b|c)){0,1}d - abd abd b,b a((b|c)){0,2}d - abcd abcd c,c a((b+|((c)*)))+d - abd abd b,b,-,- a((b+|((c)*)))+d - abcd abcd c,c,c,c (((\b))){0} - x @x -,-,- a(((.*)))b((\2)){0}c - abc abc @bc,@bc,@bc,-,- a(((.*)))b((\1)){0}c - axbc axbc x,x,x,-,- \b & SaT @aT \b & aT @aT a.*\b & abT ab \b & STSS \B & abc @bc \B & aSbTc \B & SaT @SaT \B & aSTSb @TSb kbuild-3686/src/oldsed/testsuite/noeol.sed0000664000175000017500000000001715053010105020603 0ustar locutuslocutuss/$/wakuwaku/g kbuild-3686/src/oldsed/testsuite/dollar.inp0000664000175000017500000000015615053010105020763 0ustar locutuslocutusI can't quite remember where I heard it, but I can't seem to get out of my head the phrase the final frontier kbuild-3686/src/oldsed/testsuite/mac-mf.sed0000664000175000017500000001074015053010105020633 0ustar locutuslocutus# Rewrite default rules from .c.o: to .c.o: .c /^\./s/^\(\.[a-z]*\)\(\.[a-z]*\)\( *: *\)$/\1\2\3 \1/ # Change dependency char. /::/s/::/ \\Option-f\\Option-f /g /:/s/:/ \\Option-f /g /^[SU]=/s/ \\Option-f /:/g # Change syntax of Makefile vars. /\$/s/\${\([a-zA-Z0-9_]*\)}/{\1}/g /\$/s/\$(\([a-zA-Z0-9_]*\))/{\1}/g # Change $@ to {targ} /\$@/s/\$@/{targ}/g # Change pathname syntax. # # If line ends with .. then assume it sets a variable that will # be used to prefix something else -- eliminate one colon, assuming # that a slash after the ${name} will turn into the missing colon. # Mac pathname conventions are IRREGULAR and UGLY! /\./s,\.\./\.\.$,::, /\./s,\.\.$,:, # Same if it ends with . (a single dot); turn it into nothing. /\./s,\.$,,g # Rules for .. and . elsewhere in the line # Convert ../: to ::, recur to get whole paths. /\./s,\.\./:,::,g # Convert ../../ to ::: /\./s,\.\./\.\./,:::,g /\./s,\.\./,::,g /\.\//s,\./,:,g /\//s,/,:,g /=/s/ = \.$/ = :/ # Comment out any explicit srcdir setting. # /srcdir/s/^srcdir/# srcdir/ /version/s/^version=/# version=/ /BASEDIR/s/^BASEDIR =.*$/BASEDIR = "{srcroot}"/ /{BASEDIR}:/s/{BASEDIR}:/{BASEDIR}/g # The original lines screw up -I$(srcdir)/../des by eliminating a colon. # Proposed fix: Eliminate srcdir prefixes totally. #/{srcdir}:/s/{srcdir}:/"{srcdir}"/g /{srcdir}:/s/{srcdir}://g #/"{srcdir}":/s/"{srcdir}":/"{srcdir}"/g # Comment out settings of anything set by mpw host config. ##/CC/s/^CC *=/#CC =/ ##/CFLAGS/s/^CFLAGS *=/#CFLAGS =/ ##/LDFLAGS/s/^LDFLAGS *=/#LDFLAGS =/ # Change -I usage. /-I/s/-I\./-i :/g /-I/s/-I::bfd/-i ::bfd:/g /-I/s/-I::include/-i ::include:/g /-I/s/-I/-i /g # Change -D usage. /-D/s/\([ =]\)-D\([^ ]*\)/\1-d \2/g # Change continuation char. /\\$/s/\\$/\\Option-d/ # Change wildcard char. /^[^#]/s/\*/\\Option-x/g # Change path of various types of source files. #/\.[chly]/s/\([ ><=]\)\([-a-zA-Z0-9_$:"]*\)\.\([chly]\)/\1"{s}"\2.\3/g #/\.[chly]/s/^\([-a-zA-Z0-9_${}:"]*\)\.\([chly]\)/"{s}"\1.\2/g # Skip the {s} and {o} business for now... # Fix some overenthusiasms. #/{s}/s/"{s}""{srcdir}"/"{srcdir}"/g #/{s}/s/"{s}"{\([a-zA-Z0-9_]*\)dir}/"{\1dir}"/g #/{s}/s/"{s}"{\([a-zA-Z0-9_]*\)DIR}/"{\1DIR}"/g #/{s}/s/"{s}""{\([a-zA-Z0-9_]*\)dir}"/"{\1dir}"/g #/{s}/s/"{s}""{\([a-zA-Z0-9_]*\)DIR}"/"{\1DIR}"/g #/{s}/s/"{s}":/:/g #/{s}/s/^"{s}"//g #/^\./s/"{s}"\././g # Change extension and path of objects, except in the OBJEXT line. #/^OBJEXT/!s/\([ =]\)\([-a-zA-Z0-9_${}:"]*\)\.o/\1"{o}"\2.c.o/g #/\.o/s/^\([-a-zA-Z0-9_${}:"]*\)\.o/"{o}"\1.c.o/g # Skip the {o} stuff for now... /^OBJEXT/!s/\([ =]\)\([-a-zA-Z0-9_${}:"]*\)\.o/\1\2.c.o/g /\.o/s/^\([-a-zA-Z0-9_${}:"]*\)\.o/\1.c.o/g # Clean up. #/\.o/s/"{o}""{o}"/"{o}"/g #/{o}/s/^"{o}"\([a-zA-Z0-9_]*\)=/\1=/g # Change extension of libs. # /\.a/s/lib\([a-z]*\)\.a/lib\1.o/g # Remove non-echo option. /^ -/s/^ -/ / # Change cp to duplicate. # /cp/s/^\([ ]*\)cp /\1Duplicate -d -y / # Change mv to rename. # /mv/s/^\([ ]*\)mv /\1Rename -y / # /Rename/s/^\([ ]*\)Rename -y -f/\1Rename -y/ # Change rm to delete. /^RM=/s/rm -f/Delete -i -y/ # /rm/s/^\([ ]*\)rm /\1Delete -y / # /Delete/s/^\([ ]*\)Delete -y -f/\1Delete -y/ # Comment out symlinking. # /ln/s/^\([ ]*\)ln /\1# ln / # Remove -c from explicit compiler calls. # /-c/s/{CC}\(.*\) -c \(.*\)\([-a-z]*\)\.c/{CC}\1 \2\3.c -o "{o}"\3.c.o/g # Don't ask... prev subst seems to omit the second filename. # /-o/s/\([-a-z]*\)\.c -o "{o}".c.o/\1\.c -o "{o}"\1.c.o/ # Change linking cc to link. /LDFLAGS/ s/{CC} \(.*\){CFLAGS}\(.*\){LDFLAGS}/Link \1 \2 {LDFLAGS}/ /CFLAGS_LINK/s/{CC} \(.*\){CFLAGS_LINK}\(.*\){LDFLAGS}/Link \1 \2 {LDFLAGS}/ # Comment out .PHONY rules. /\.PHONY/s/^\.PHONY/# \.PHONY/ # Comment out .SUFFIXES rules. /\.SUFFIXES/s/^\.SUFFIXES/# \.SUFFIXES/ # Comment out .PRECIOUS rules. /\.PRECIOUS/s/^\.PRECIOUS/# \.PRECIOUS/ ## Comment out default rules. ##/^\./s/^\(\.[a-z]*\.[a-z]* \)/# \1/ # # End of original hack-mf.sed # # Begin original hack-mf2.sed # # Transform expressions. # Set the install program appropriate. # /INSTALL/s/^INSTALL *= *`.*`:install.sh -c/INSTALL = Duplicate -y/ # Include from the extra-include dir. # /^INCLUDES = /s/^INCLUDES = /INCLUDES = -i "{srcroot}"extra-include / # Yuck - remove unconverted autoconf things. # /@/s/@[^ ]*@//g # Hackery, pure and simple # To speed up compiles, remove duplicated -i options. /-i/s/\(-i [^ ]*\) \1 /\1 /g # Note! There are 8-bit characters in the three lines below: # 0xc4, 0xb6, 0xc5. /Option/s/\\Option-f/Ä/g /Option/s/\\Option-d/¶/g /Option/s/\\Option-x/Å/g kbuild-3686/src/oldsed/testsuite/uniq.sed0000664000175000017500000000046515053010105020452 0ustar locutuslocutush :b # On the last line, print and exit $b N /^\(.*\)\n\1$/ { # The two lines are identical. Undo the effect of # the n command. g bb } # If the @code{N} command had added the last line, print and exit $b # The lines are different; print the first and go # back working on the second. P D kbuild-3686/src/oldsed/testsuite/space.inp0000664000175000017500000000004415053010105020575 0ustar locutuslocutusHello World ! Second_line_ of tests kbuild-3686/src/oldsed/testsuite/cv-vars.sed0000664000175000017500000000016315053010105021052 0ustar locutuslocutus# inspired by an autoconf generated configure script. s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/: \${\1='\2'}/p kbuild-3686/src/oldsed/testsuite/enable.inp0000664000175000017500000000016515053010105020734 0ustar locutuslocutus--enable-targets=sparc-sun-sunos4.1.3,srec --enable-x11-testing=on --enable-wollybears-in-minnesota=yes-id-like-that kbuild-3686/src/oldsed/testsuite/manis.sed0000664000175000017500000000043015053010105020575 0ustar locutuslocutus# straight out of an autoconf-generated configure. # The input should look just like the input after this is run. # # Protect against being on the right side of a sed subst in config.status. s/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\\\&%]/\\\\&/g; s/@@/%@/; s/@@/@%/; s/@g$/%g/ kbuild-3686/src/oldsed/testsuite/noeolw.2good0000664000175000017500000000006515053010105021234 0ustar locutuslocutusThis file is unique in that it does end in a newline.kbuild-3686/src/oldsed/testsuite/fasts.sed0000664000175000017500000000031515053010105020610 0ustar locutuslocutus# test `fast' substitutions h s/a// p g s/a//g p g s/^a//p g s/^a//g p g s/not present//g p g s/^[a-z]//g p g s/a$// p g y/a/b/ h s/b// p g s/b//g p g s/^b//p g s/^b//g p g s/^[a-z]//g p g s/b$// p g kbuild-3686/src/oldsed/testsuite/allsub.sed0000664000175000017500000000001415053010105020746 0ustar locutuslocutuss/foo/bar/g kbuild-3686/src/oldsed/testsuite/numsub5.good0000664000175000017500000000000015053010105021232 0ustar locutuslocutuskbuild-3686/src/oldsed/testsuite/8bit.good0000664000175000017500000000026015053010105020512 0ustar locutuslocutus䯤â¤è ¤ß䯻ý¤Á ·¡¶ú¤â¤è ¤ß·¡¶ú»ý¤Á ¤³¤ÎµÖ¤Ë ºÚŦ¤Þ¤¹»ù ²È´Ö¤«¤Ê ¹ð¤é¤µ¤Í ¤½¤é¤ß¤Ä ÆüËܤιñ¤Ï ¤ª¤·¤ã¤Ê¤Ù¤Æ ¤ï¤ì¤³¤½µï¤ì ¤·¤­¤Ê¤Ù¤Æ ¤ï¤ì¤³¤½ ºÂ¤» ¤ï¤Ë¤³¤½¤Ï ¹ð¤é¤á ²È¤ò¤â̾¤ò¤â kbuild-3686/src/oldsed/testsuite/y-bracket.good0000664000175000017500000000003115053010105021521 0ustar locutuslocutusAre you sure (y/n)? y] kbuild-3686/src/oldsed/testsuite/khadafy.sed0000664000175000017500000000025715053010105021104 0ustar locutuslocutus# The Khadafy test is brought to you by Scott Anderson . . . /M[ou]'\{0,1\}am\{1,2\}[ae]r .*\([AEae]l[- ]\)\{0,1\}[GKQ]h\{0,1\}[aeu]\{1,\}\([dtz][dhz]\{0,1\}\)\{1,\}af[iy]/!d kbuild-3686/src/oldsed/testsuite/distrib.good0000664000175000017500000000204315053010105021305 0ustar locutuslocutusPath: mailnewsgateway From crash@cygnus.com Wed Mar 8 18: 02:42 1995 From: crash@cygnus.com (Jason Molenda) Message-ID: <9503090202.AA06931.alt.buddha.fat.short.guy@phydeaux.cygnus.com> Subject: Note for sed testsuite Original-To: molenda@msi.umn.edu Date: Wed, 8 Mar 1995 18:02:24 -0800 (PST) X-Mailer: ELM [version 2.4 PL23] Newsgroups: alt.buddha.short.fat.guy Distribution: world Sender: news@cygnus.com Approved: alt.buddha.short.fat.guy@cygnus.com _Summum Bonum_ All the breath and the bloom of the year in the bag of one bee: All the wonder and wealth of the mine in the heart of one gem: In the core of one pearl all the shade and the shine of the sea: Breath and bloom, shade and shine, -- wonder, wealth, and -- how far above them -- Truth, thats brighter than gem, Trust, that's purer than pearl, -- Brightest truth, purest trust in the universe -- all were for me In the kiss of one girl. -- Robert Browning kbuild-3686/src/oldsed/testsuite/subwrt2.good0000664000175000017500000000010715053010105021254 0ustar locutuslocutusWho YoU are, and when you lose, Comes only from the things YoU choose. kbuild-3686/src/oldsed/testsuite/fasts.good0000664000175000017500000000037215053010105020770 0ustar locutuslocutusaaaaaabbbbbbaaaaaaa bbbbbb aaaaaabbbbbbaaaaaaa aaaaaabbbbbbaaaaaaa aaaaaaabbbbbbaaaaaaa aaaaaabbbbbbaaaaaaa aaaaaaabbbbbbaaaaaa bbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbb kbuild-3686/src/oldsed/testsuite/head.sed0000664000175000017500000000000315053010105020363 0ustar locutuslocutus3q kbuild-3686/src/oldsed/testsuite/numsub5.sed0000664000175000017500000000001215053010105021060 0ustar locutuslocutuss/a*/b/3p kbuild-3686/src/oldsed/testsuite/distrib.sh0000664000175000017500000000301515053010105020767 0ustar locutuslocutus#! /bin/sh # # This is stolen from C News # # # All this does is massage the headers so they look like what news # software expects. To:, Cc: and Resent-*: headers are masked. # Reply-To: is turned into references, which is questionable (could # just as well be dropped. # # The From: line is rewritten to use the "address (comments)" form # instead of "phrase " form our mailer uses. Also, addresses # with no "@domainname" are assumed to originate locally, and so are # given a domain. # # The Sender: field below reflects the address of the person who # maintains our mailing lists. The Approved: field is in a special # form, so that we can do bidirectional gatewaying. Any message # in a newsgroup that bears this stamp will not be fed into the # matching mailing list. sed=${1-sed} $sed -n -e "1{i\\ Path: mailnewsgateway }" \ -e ":a /^[Rr]eceived:/b r /^[Nn]ewsgroups:/b r /^[Pp]ath:/b r /^[Tt][Oo]:/s/^/Original-/ /^[Cc][Cc]:/s/^/Original-/ /^[Rr][Ee][Ss][Ee][Nn][Tt]-.*/s/^/Original-/ /^[Mm][Ee][Ss][Ss][Aa][Gg][Ee]-[Ii][Dd]:/s/@/.alt.buddha.fat.short.guy@/ s/^[Ii]n-[Rr]eply-[Tt]o:/References:/ /^From:/{ s/<\([^@]*\)>\$/<\1@$thissite>/ s/^From:[ ][ ]*\(.*\) *<\(.*\)>\$/From: \2 (\1)/ } s/-[Ii]d:/-ID:/ s/^[Ss][Uu][Bb][Jj][Ee][Cc][Tt]:[ ]*$/Subject: (none)/ s/^\([^:]*:\)[ ]*/\1 / /^\$/{i\\ Newsgroups: alt.buddha.short.fat.guy\\ Distribution: world\\ Sender: news@cygnus.com\\ Approved: alt.buddha.short.fat.guy@cygnus.com b e } p n b a :r s/.*//g n /^[ ]/b r b a :e p n b e" kbuild-3686/src/oldsed/testsuite/xemacs.inp0000664000175000017500000000471215053010105020770 0ustar locutuslocutus# Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Automake requirements SHELL = @SHELL@ PACKAGE = sed EXTRA_DIST = BUGS THANKS README.boot bootstrap.sh dc.sed autogen \ m4/codeset.m4 m4/gettext.m4 m4/iconv.m4 m4/lcmessage.m4 \ m4/getline.m4 m4/glibc21.m4 m4/isc-posix.m4 m4/progtest.m4 \ m4/obstack.m4 subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = bootstrap.sh intl/Makefile DIST_SOURCES = DATA = $(noinst_DATA) HEADERS = $(noinst_HEADERS) RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ uninstall-info-recursive all-recursive install-data-recursive \ install-exec-recursive installdirs-recursive install-recursive \ uninstall-recursive check-recursive installcheck-recursive DIST_COMMON = README $(noinst_HEADERS) ./stamp-h.in ABOUT-NLS AUTHORS \ COPYING ChangeLog INSTALL Makefile.am Makefile.in NEWS THANKS \ TODO acconfig.h aclocal.m4 bootstrap.sh.in config.guess \ config.sub config_h.in configure configure.ac depcomp \ install-sh missing mkinstalldirs DIST_SUBDIRS = $(SUBDIRS) all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$@ $(SHELL) ./config.status $(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(srcdir)/configure: $(srcdir)/configure.ac $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): configure.ac m4/codeset.m4 m4/getline.m4 m4/gettext.m4 m4/glibc21.m4 m4/iconv.m4 m4/isc-posix.m4 m4/lcmessage.m4 m4/obstack.m4 m4/progtest.m4 cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) config.h: stamp-hkbuild-3686/src/oldsed/testsuite/appquit.good0000664000175000017500000000000715053010105021326 0ustar locutuslocutusdoh ok kbuild-3686/src/oldsed/testsuite/khadafy.good0000664000175000017500000000133115053010105021253 0ustar locutuslocutus1) Muammar Qaddafi 2) Mo'ammar Gadhafi 3) Muammar Kaddafi 4) Muammar Qadhafi 5) Moammar El Kadhafi 6) Muammar Gadafi 7) Mu'ammar al-Qadafi 8) Moamer El Kazzafi 9) Moamar al-Gaddafi 10) Mu'ammar Al Qathafi 11) Muammar Al Qathafi 12) Mo'ammar el-Gadhafi 13) Moamar El Kadhafi 14) Muammar al-Qadhafi 15) Mu'ammar al-Qadhdhafi 16) Mu'ammar Qadafi 17) Moamar Gaddafi 18) Mu'ammar Qadhdhafi 19) Muammar Khaddafi 20) Muammar al-Khaddafi 21) Mu'amar al-Kadafi 22) Muammar Ghaddafy 23) Muammar Ghadafi 24) Muammar Ghaddafi 25) Muamar Kaddafi 26) Muammar Quathafi 27) Muammar Gheddafi 28) Muamar Al-Kaddafi 29) Moammar Khadafy 30) Moammar Qudhafi 31) Mu'ammar al-Qaddafi 32) Mulazim Awwal Mu'ammar Muhammad Abu Minyar al-Qadhafi kbuild-3686/src/oldsed/testsuite/numsub4.sed0000664000175000017500000000001315053010105021060 0ustar locutuslocutuss/^a*/b/2p kbuild-3686/src/oldsed/testsuite/readin.in20000664000175000017500000000000415053010105020642 0ustar locutuslocutusMOO kbuild-3686/src/oldsed/testsuite/tst-pcre.c0000664000175000017500000001245415053010105020707 0ustar locutuslocutus/* Regular expression tests. Copyright (C) 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2003. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #ifdef HAVE_MCHECK_H #include #endif #include #include #include #include int main (int argc, char **argv) { int ret = 0; char *line = NULL; size_t line_len = 0; ssize_t len; FILE *f; char *pattern = NULL, *string = NULL; regmatch_t rm[20]; size_t pattern_alloced = 0, string_alloced = 0; int ignorecase = 0; int pattern_valid = 0, rm_valid = 0; size_t linenum; #ifdef HAVE_MCHECK_H mtrace (); #endif if (argc < 2) { fprintf (stderr, "Missing test filename\n"); return 1; } f = fopen (argv[1], "r"); if (f == NULL) { fprintf (stderr, "Couldn't open %s\n", argv[1]); return 1; } if ((len = getline (&line, &line_len, f)) <= 0 || strncmp (line, "# PCRE", 6) != 0) { fprintf (stderr, "Not a PCRE test file\n"); fclose (f); free (line); return 1; } linenum = 1; while ((len = getline (&line, &line_len, f)) > 0) { char *p; unsigned long num; ++linenum; if (line[len - 1] == '\n') line[--len] = '\0'; if (line[0] == '#') continue; if (line[0] == '\0') { /* End of test. */ ignorecase = 0; pattern_valid = 0; rm_valid = 0; continue; } if (line[0] == '/') { /* Pattern. */ p = strrchr (line + 1, '/'); pattern_valid = 0; rm_valid = 0; if (p == NULL) { printf ("%lu: Invalid pattern line: %s\n", linenum, line); ret = 1; continue; } if (p[1] == 'i' && p[2] == '\0') ignorecase = 1; else if (p[1] != '\0') { printf ("%lu: Invalid pattern line: %s\n", linenum, line); ret = 1; continue; } if (pattern_alloced < (size_t) (p - line)) { pattern = realloc (pattern, p - line); if (pattern == NULL) { printf ("%lu: Cannot record pattern: %m\n", linenum); ret = 1; break; } pattern_alloced = p - line; } memcpy (pattern, line + 1, p - line - 1); pattern[p - line - 1] = '\0'; pattern_valid = 1; continue; } if (strncmp (line, " ", 4) == 0) { regex_t re; int n; if (!pattern_valid) { printf ("%lu: No previous valid pattern %s\n", linenum, line); continue; } if (string_alloced < (size_t) (len - 3)) { string = realloc (string, len - 3); if (string == NULL) { printf ("%lu: Cannot record search string: %m\n", linenum); ret = 1; break; } string_alloced = len - 3; } memcpy (string, line + 4, len - 3); n = regcomp (&re, pattern, REG_EXTENDED | (ignorecase ? REG_ICASE : 0)); if (n != 0) { char buf[500]; regerror (n, &re, buf, sizeof (buf)); printf ("%lu: regcomp failed for %s: %s\n", linenum, pattern, buf); ret = 1; continue; } if (regexec (&re, string, 20, rm, 0)) { rm[0].rm_so = -1; rm[0].rm_eo = -1; } regfree (&re); rm_valid = 1; continue; } if (!rm_valid) { printf ("%lu: No preceeding pattern or search string\n", linenum); ret = 1; continue; } if (strcmp (line, "No match") == 0) { if (rm[0].rm_so != -1 || rm[0].rm_eo != -1) { printf ("%lu: /%s/ on %s unexpectedly matched %d..%d\n", linenum, pattern, string, rm[0].rm_so, rm[0].rm_eo); ret = 1; } continue; } p = line; if (*p == ' ') ++p; num = strtoul (p, &p, 10); if (num >= 20 || *p != ':' || p[1] != ' ') { printf ("%lu: Invalid line %s\n", linenum, line); ret = 1; continue; } if (rm[num].rm_so == -1 || rm[num].rm_eo == -1) { if (strcmp (p + 2, "") != 0) { printf ("%lu: /%s/ on %s unexpectedly failed to match register %ld %d..%d\n", linenum, pattern, string, num, rm[num].rm_so, rm[num].rm_eo); ret = 1; } continue; } if (rm[num].rm_eo < rm[num].rm_so || rm[num].rm_eo - rm[num].rm_so != len - (p + 2 - line) || strncmp (p + 2, string + rm[num].rm_so, rm[num].rm_eo - rm[num].rm_so) != 0) { printf ("%lu: /%s/ on %s unexpectedly failed to match %s for register %ld %d..%d\n", linenum, pattern, string, p + 2, num, rm[num].rm_so, rm[num].rm_eo); ret = 1; continue; } } free (pattern); free (string); free (line); fclose (f); return ret; } kbuild-3686/src/oldsed/testsuite/noeol.inp0000664000175000017500000000006515053010105020621 0ustar locutuslocutusThis file is unique in that it does end in a newline.kbuild-3686/src/oldsed/testsuite/numsub3.sed0000664000175000017500000000001215053010105021056 0ustar locutuslocutuss/^a*/b/2 kbuild-3686/src/oldsed/testsuite/runtest0000775000175000017500000000055615053010105020434 0ustar locutuslocutus#! /bin/sh : ${MAKE=make} : ${srcdir=.} : ${SED="../sed/sed"} makefile="$srcdir/Makefile.tests" test=`echo "$@"| sed 's,.*/,,'` # As a convenience, suppress the output of make if the test passes if $MAKE SED="$SED" srcdir="$srcdir" -f "$makefile" $test > tmp.test 2>&1; then rm -f tmp.test else exitcode=$? cat tmp.test rm -f tmp.test exit $exitcode fi kbuild-3686/src/oldsed/testsuite/bug-regex13.c0000664000175000017500000000707715053010105021204 0ustar locutuslocutus/* Regular expression tests. Copyright (C) 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa , 2002. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #ifdef HAVE_MCHECK_H #include #endif #include #include #include #include static struct { int syntax; const char *pattern; const char *string; int start; } tests[] = { {RE_BACKSLASH_ESCAPE_IN_LISTS, "[0\\-9]", "1", -1}, /* It should not match. */ {RE_BACKSLASH_ESCAPE_IN_LISTS, "[0\\-9]", "-", 0}, /* It should match. */ {RE_SYNTAX_POSIX_BASIC, "s1\n.*\ns3", "s1\ns2\ns3", 0}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}c", "ac", 0}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}c", "abc", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}c", "abbc", -1}, /* Nested duplication. */ {RE_SYNTAX_POSIX_EXTENDED, "ab{1}{1}c", "ac", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{1}{1}c", "abc", 0}, {RE_SYNTAX_POSIX_EXTENDED, "ab{1}{1}c", "abbc", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{2}{2}c", "ac", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{2}{2}c", "abbc", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{2}{2}c", "abbbbc", 0}, {RE_SYNTAX_POSIX_EXTENDED, "ab{2}{2}c", "abbbbbc", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}{1}c", "ac", 0}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}{1}c", "abc", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}{1}c", "abbc", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{1}{0}c", "ac", 0}, {RE_SYNTAX_POSIX_EXTENDED, "ab{1}{0}c", "abc", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{1}{0}c", "abbc", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}*c", "ac", 0}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}*c", "abc", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}*c", "abbc", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}?c", "ac", 0}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}?c", "abc", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}?c", "abbc", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}+c", "ac", 0}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}+c", "abc", -1}, {RE_SYNTAX_POSIX_EXTENDED, "ab{0}+c", "abbc", -1}, }; int main (void) { struct re_pattern_buffer regbuf; const char *err; size_t i; int ret = 0; #ifdef HAVE_MCHECK_H mtrace (); #endif for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i) { int start; re_set_syntax (tests[i].syntax); memset (®buf, '\0', sizeof (regbuf)); err = re_compile_pattern (tests[i].pattern, strlen (tests[i].pattern), ®buf); if (err != NULL) { printf ("re_compile_pattern failed: %s\n", err); ret = 1; continue; } start = re_search (®buf, tests[i].string, strlen (tests[i].string), 0, strlen (tests[i].string), NULL); if (start != tests[i].start) { printf ("re_search failed %d\n", start); ret = 1; regfree (®buf); continue; } regfree (®buf); } return ret; } kbuild-3686/src/oldsed/testsuite/mac-mf.good0000664000175000017500000001413215053010105021007 0ustar locutuslocutus## config:mac-pre.in ## common Macintosh prefix for all Makefile.in in the Kerberos V5 tree # # MPW-style lines for the MakeFile # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # This first part is long enough that NFS:Share doesn't notice the non-ASCII # characters in the rest of the file, so it claims that the file is type # TEXT, which is what we want. The non-ASCII chars are necessary for MPW # Make # # End of MPW-style lines for MakeFile # WHAT = mac # Directory syntax Ä R= C= S=: U=: BUILDTOP = ::: srcdir = # FIXME Ä This doesn't translate to MPW yet, srcdir must be same as objdir # File in object dir can come from either the current dir or srcdir # # . Ä . "{srcdir}" # Default rule that puts each file into separate segment .c.o Ä .c {CC} {DepDir}{Default}.c {CFLAGS} -s {Default} -o {TargDir}{Default}.c.o CPPFLAGS = -i {SRCTOP}:include -i {BUILDTOP}:include -i {SRCTOP}:include:krb5 -i {BUILDTOP}:include:krb5 -i {CIncludes} DEFS = {CPPFLAGS} CC = c LD = link # The funny quoting in the LDFLAGS is to avoid xxx.c.o being mangled by # mac-mf.sed into xxx.c.o LDFLAGS=-t MPST -c "MPS " -sym on {Libraries}"Runtime."o {CLibraries}"StdClib."o {Libraries}"ToolLibs."o {Libraries}"Interface."o CCOPTS = LIBS = KRB5ROOT= @KRB5ROOT@ KRB4=@KRB4@ INSTALL=Duplicate -y INSTALL_PROGRAM=Duplicate -y INSTALL_DATA=Duplicate -y INSTALL_SETUID=Duplicate -y KRB5MANROOT = {KRB5ROOT}{S}man ADMIN_BINDIR = {KRB5ROOT}{S}admin SERVER_BINDIR = {KRB5ROOT}{S}sbin CLIENT_BINDIR = {KRB5ROOT}{S}bin ADMIN_MANDIR = {KRB5MANROOT}{S}man8 SERVER_MANDIR = {KRB5MANROOT}{S}man8 CLIENT_MANDIR = {KRB5MANROOT}{S}man1 FILE_MANDIR = {KRB5MANROOT}{S}man5 KRB5_LIBDIR = {KRB5ROOT}{S}lib KRB5_INCDIR = {KRB5ROOT}{S}include KRB5_INCSUBDIRS = ¶ {KRB5_INCDIR}{S}krb5 ¶ {KRB5_INCDIR}{S}asn.1 ¶ {KRB5_INCDIR}{S}kerberosIV RM = Delete -y -i CP = Duplicate -y MV = mv -f CHMOD=chmod RANLIB = @RANLIB@ ARCHIVE = @ARCHIVE@ ARADD = @ARADD@ LN = @LN_S@ AWK = @AWK@ LEX = @LEX@ LEXLIB = @LEXLIB@ YACC = @YACC@ # FIXME Ä This won't work for srcdir != objdir. But on the Mac, there # is no easy way to build a relative or absolute path, because Ä means # both the path separator, and the "go up a directory" indicator #SRCTOP = {srcdir}{S}{BUILDTOP} SRCTOP = {BUILDTOP} SUBDIRS = @subdirs@ TOPLIBD = {BUILDTOP}{S}lib OBJEXT = c.o LIBEXT = a EXEEXT = all ÄÄ # Generated automatically from Makefile.in by configure CFLAGS = {CCOPTS} {DEFS} -i ::des ##DOSBUILDTOP = ..\..\: ##DOSLIBNAME=..\crypto.lib ##DOS!include {BUILDTOP}\config\windows.in OBJS= md5.{OBJEXT} md5glue.{OBJEXT} md5crypto.{OBJEXT} SRCS= md5.c md5glue.c md5crypto.c all ÄÄ {OBJS} t_mddriver Ä t_mddriver.c.o md5.c.o Link {LDFLAGS} -o t_mddriver t_mddriver.c.o md5.c.o t_mddriver.exe Ä {CC} {CFLAGS2} -o t_mddriver.exe t_mddriver.c md5.c check ÄÄ t_mddriver{EXEEXT} {C}t_mddriver{EXEEXT} -x clean ÄÄ {RM} t_mddriver{EXEEXT} t_mddriver.{OBJEXT} # config:post.in # put all ÄÄ first just in case no other rules occur here # all ÄÄ check ÄÄ clean ÄÄ clean-{WHAT} {RM} config.log pre.c.out post.c.out Makefile.c.out clean-unix ÄÄ if test -n "{OBJS}" ; then {RM} {OBJS}; else Ä ; fi clean-windows ÄÄ {RM} Å.{OBJEXT} {RM} msvc.pdb Å.err kbuild-3686/src/oldsed/testsuite/linecnt.inp0000664000175000017500000000370415053010105021144 0ustar locutuslocutusA dialogue on poverty On the night when the rain beats, Driven by the wind, On the night when the snowflakes mingle With a sleety rain, I feel so helplessly cold. I nibble at a lump of salt, Sip the hot, oft-diluted dregs of _sake_; And coughing, snuffling, And stroking my scanty beard, I say in my pride, "There's none worthy, save I!" But I shiver still with cold. I pull up my hempen bedclothes, Wear what few sleeveless clothes I have, But cold and bitter is the night! As for those poorer than myself, Their parents must be cold and hungry, Their wives and children beg and cry. Then, how do you struggle through life? Wide as they call the heaven and earth, For me they have shrunk quite small; Bright though they call the sun and moon, They never shine for me. Is it the same with all men, Or for me alone? By rare chance I was born a man And no meaner than my fellows, But, wearing unwadded sleeveless clothes In tatters, like weeds waving in the sea, Hanging from my shoulders, And under the sunken roof, Within the leaning walls, Here I lie on straw Spread on bare earth, With my parents at my pillow, And my wife and children at my feet, All huddled in grief and tears. No fire sends up smoke At the cooking-place, And in the cauldron A spider spins its web. With not a grain to cook, We moan like the night thrush. Then, "to cut," as the saying is, "The ends of what is already too short," The village headman comes, With rod in hand, to our sleeping place, Growling for his dues. Must it be so hopeless -- The way of this world? -- Yamanoue Okura kbuild-3686/src/oldsed/testsuite/inclib.sed0000664000175000017500000000010515053010105020725 0ustar locutuslocutus# inspired by an autoconf generated configure script. s;lib;include; kbuild-3686/src/oldsed/testsuite/recall.sed0000664000175000017500000000017215053010105020733 0ustar locutuslocutus# Check that the empty regex recalls the last *executed* regex, # not the last *compiled* regex p s/e/X/p :x s//Y/p /f/bx kbuild-3686/src/oldsed/testsuite/8bit.inp0000664000175000017500000000026015053010105020350 0ustar locutuslocutus䯤â¤è ¤ß䯻ý¤Á ·¡¶ú¤â¤è ¤ß·¡¶ú»ý¤Á ¤³¤ÎµÖ¤Ë ºÚŦ¤Þ¤¹»ù ²È´Ö¤«¤Ê ¹ð¤é¤µ¤Í ¤½¤é¤ß¤Ä ÂçϤιñ¤Ï ¤ª¤·¤ã¤Ê¤Ù¤Æ ¤ï¤ì¤³¤½µï¤ì ¤·¤­¤Ê¤Ù¤Æ ¤ï¤ì¤³¤½ ºÂ¤» ¤ï¤Ë¤³¤½¤Ï ¹ð¤é¤á ²È¤ò¤â̾¤ò¤â kbuild-3686/src/oldsed/testsuite/inclib.good0000664000175000017500000000140315053010105021104 0ustar locutuslocutus /usr/X11R6/include /usr/X11R5/include /usr/X11R4/include /usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 /usr/local/X11R6/include /usr/local/X11R5/include /usr/local/X11R4/include /usr/local/include/X11R6 /usr/local/include/X11R5 /usr/local/include/X11R4 /usr/X11/include /usr/include/X11 /usr/local/X11/include /usr/local/include/X11 /usr/X386/include /usr/x386/include /usr/XFree86/include/X11 /usr/include /usr/local/include /usr/unsupported/include /usr/athena/include /usr/local/x11r5/include /usr/lpp/Xamples/include /usr/openwin/include /usr/openwin/share/include kbuild-3686/src/oldsed/testsuite/bsd.sh0000775000175000017500000002261715053010105020113 0ustar locutuslocutus#!/bin/sh - # $NetBSD: sed.test,v 1.3 1997/01/09 20:21:37 tls Exp $ # # Copyright (c) 1992 Diomidis Spinellis. # Copyright (c) 1992, 1993 # 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. # # from: @(#)sed.test 8.1 (Berkeley) 6/6/93 # $NetBSD: sed.test,v 1.3 1997/01/09 20:21:37 tls Exp $ # # sed Regression Tests # Modified by Paolo Bonzini to: # - not warn about buggy seds # - run tests once instead of comparing them to the system sed # - remove most uses of awk # - cleanup at exit # - comment tests that broke because of extensions main() { TEST="${1-../sed/sed}" TESTLOG="${2-sed.out}" # DICT="${3-/usr/share/dict/words}" : > lines1 : > lines2 for i in 1 2 3 4 5 6 7 8 9; do echo l1_$i >> lines1 echo l2_$i >> lines2 done for i in 10 11 12 13 14; do echo l1_$i >> lines1 done # Set these flags to get messages about known problems tests "$TEST" "$TESTLOG" rm -f lines[1234] script[12] } tests() { SED="$1" LOG="$2" MARK=100 rm -f "$LOG" exec 3>&0 4>&1 5>&2 exec 0/dev/null 2>/dev/null test_error exec 0>&3 1>&4 2>&5 exec 4>&1 5>&2 test_args test_addr test_group test_acid test_branch test_pattern test_print test_subst exec 1>&4 2>&5 } mark() { exec 2>&1 >>$LOG test $MARK = 100 || echo MARK=`expr $MARK + 1` echo "Test $1:$MARK" | sed 's/./=/g' echo "Test $1:$MARK" echo "Test $1:$MARK" | sed 's/./=/g' } test_args() { mark '1.1' echo Testing argument parsing echo First type $SED 's/^/e1_/p' lines1 mark '1.2' ; $SED -n 's/^/e1_/p' lines1 mark '1.3' ; $SED 's/^/e1_/p' script1 echo 's/^/s2_/p' >script2 mark '1.5' ; $SED -f script1 lines1 mark '1.6' ; $SED -f script1 script1 <lines3 mark '7.1' ; $SED -n l lines3 mark '7.2' ; $SED -e '/l2_/=' lines1 lines2 rm -f lines4 mark '7.3' ; $SED -e '3,12w lines4' lines1 echo w results cat lines4 mark '7.4' ; $SED -e '4r lines2' lines1 mark '7.5' ; $SED -e '5r /dev/dds' lines1 mark '7.6' ; $SED -e '6r /dev/null' lines1 # mark '7.7' # sed '200q' $DICT | sed 's$.*$s/^/&/w tmpdir/&$' >script1 # rm -rf tmpdir # mkdir tmpdir # $SED -f script1 lines1 # cat tmpdir/* # rm -rf tmpdir mark '7.8' echo line1 > lines3 echo "" >> lines3 $SED -n -e '$p' lines3 /dev/null } test_subst() { echo Testing substitution commands mark '8.1' ; $SED -e 's/./X/g' lines1 mark '8.2' ; $SED -e 's,.,X,g' lines1 mark '8.3' ; $SED -e 's.\..X.g' lines1 # POSIX does not say that this should work # mark '8.4' ; $SED -e 's/[/]/Q/' lines1 mark '8.4' ; $SED -e 's/[\/]/Q/' lines1 mark '8.5' ; $SED -e 's_\__X_' lines1 mark '8.6' ; $SED -e 's/./(&)/g' lines1 mark '8.7' ; $SED -e 's/./(\&)/g' lines1 mark '8.8' ; $SED -e 's/\(.\)\(.\)\(.\)/x\3x\2x\1/g' lines1 mark '8.9' ; $SED -e 's/_/u0\ u1\ u2/g' lines1 mark '8.10' ; $SED -e 's/./X/4' lines1 rm -f lines4 mark '8.11' ; $SED -e 's/1/X/w lines4' lines1 echo s wfile results cat lines4 mark '8.12' ; $SED -e 's/[123]/X/g' lines1 mark '8.13' ; $SED -e 'y/0123456789/9876543210/' lines1 mark '8.14' ; $SED -e 'y10\123456789198765432\101' lines1 mark '8.15' ; $SED -e '1N;2y/\n/X/' lines1 mark '8.16' echo 'eeefff' | $SED -e 'p' -e 's/e/X/p' -e ':x' \ -e 's//Y/p' -e '/f/bx' } test_error() { $SED -x && exit 1 $SED -f && exit 1 $SED -e && exit 1 $SED -f /dev/dds && exit 1 $SED p /dev/dds && exit 1 $SED -f /bin/sh && exit 1 $SED '{' && exit 1 $SED '{' && exit 1 $SED '/hello/' && exit 1 $SED '1,/hello/' && exit 1 $SED -e '-5p' && exit 1 $SED '/jj' && exit 1 # $SED 'a hello' && exit 1 # $SED 'a \ hello' && exit 1 $SED 'b foo' && exit 1 $SED 'd hello' && exit 1 $SED 's/aa' && exit 1 $SED 's/aa/' && exit 1 $SED 's/a/b' && exit 1 $SED 's/a/b/c/d' && exit 1 $SED 's/a/b/ 1 2' && exit 1 # $SED 's/a/b/ 1 g' && exit 1 $SED 's/a/b/w' && exit 1 $SED 'y/aa' && exit 1 $SED 'y/aa/b/' && exit 1 $SED 'y/aa/' && exit 1 $SED 'y/a/b' && exit 1 $SED 'y/a/b/c/d' && exit 1 $SED '!' && exit 1 $SED supercalifrangolisticexprialidociussupercalifrangolisticexcius } main ${1+"$@"} kbuild-3686/src/oldsed/testsuite/binary.inp0000664000175000017500000000031415053010105020766 0ustar locutuslocutus192.168.1.2 br b8dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP | DDD 24>dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP kbuild-3686/src/oldsed/testsuite/y-newline.inp0000664000175000017500000000003115053010105021405 0ustar locutuslocutusAre you sure (y/n)? [y] kbuild-3686/src/oldsed/testsuite/distrib.sed0000664000175000017500000000272015053010105021132 0ustar locutuslocutus# This is straight out of C News # # # All this does is massage the headers so they look like what news # software expects. To:, Cc: and Resent-*: headers are masked. # Reply-To: is turned into references, which is questionable (could # just as well be dropped. # # The From: line is rewritten to use the "address (comments)" form # instead of "phrase " form our mailer uses. Also, addresses # with no "@domainname" are assumed to originate locally, and so are # given a domain. # # The Sender: field below reflects the address of the person who # maintains our mailing lists. The Approved: field is in a special # form, so that we can do bidirectional gatewaying. Any message # in a newsgroup that bears this stamp will not be fed into the # matching mailing list. 1i\ Path: mailnewsgateway :a /^[Rr]eceived:/b r /^[Nn]ewsgroups:/b r /^[Pp]ath:/b r /^[Tt][Oo]:/s/^/Original-/ /^[Cc][Cc]:/s/^/Original-/ /^[Rr][Ee][Ss][Ee][Nn][Tt]-.*/s/^/Original-/ /^[Mm][Ee][Ss][Ss][Aa][Gg][Ee]-[Ii][Dd]:/s/@/.alt.buddha.fat.short.guy@/ s/^[Ii]n-[Rr]eply-[Tt]o:/References:/ /^From:/{ s/<\([^@]*\)>$/<\1@$thissite>/ s/^From:[ ][ ]*\(.*\) *<\(.*\)>$/From: \2 (\1)/ } s/-[Ii]d:/-ID:/ s/^[Ss][Uu][Bb][Jj][Ee][Cc][Tt]:[ ]*$/Subject: (none)/ s/^\([^:]*:\)[ ]*/\1 / /^$/{i\ Newsgroups: alt.buddha.short.fat.guy\ Distribution: world\ Sender: news@cygnus.com\ Approved: alt.buddha.short.fat.guy@cygnus.com b e } p n b a :r s/.*//g n /^[ ]/b r b a :e p n b e kbuild-3686/src/oldsed/testsuite/madding.inp0000664000175000017500000001250715053010105021114 0ustar locutuslocutusThe girl on the summit of the load sat motionless, surrounded by tables and chairs with their legs upwards, backed by an oak settle, and ornamented in front by pots of geraniums, myrtles, and cactuses, together with a caged canary -- all probably from the windows of the house just vacated. There was also a cat in a willow basket, from the partly-opened lid of which she gazed with half-closed eyes, and affectionately-surveyed the small birds around. The handsome girl waited for some time idly in her place, and the only sound heard in the stillness was the hopping of the canary up and down the perches of its prison. Then she looked attentively downwards. It was not at the bird, nor at the cat; it was at an oblong package tied in paper, and lying between them. She turned her head to learn if the waggoner were coming. He was not yet in sight; and her eyes crept back to the package, her thoughts seeming to run upon what was inside it. At length she drew the article into her lap, and untied the paper covering; a small swing looking- glass was disclosed, in which she proceeded to survey herself attentively. She parted her lips and smiled. It was a fine morning, and the sun lighted up to a scarlet glow the crimson jacket she wore, and painted a soft lustre upon her bright face and dark hair. The myrtles, geraniums, and cactuses packed around her were fresh and green, and at such a leafless season they invested the whole concern of horses, waggon, furniture, and girl with a peculiar vernal charm. What possessed her to indulge in such a performance in the sight of the sparrows, blackbirds, and unperceived farmer who were alone its spectators, -- whether the smile began as a factitious one, to test her capacity in that art, -- nobody knows; it ended certainly in a real smile. She blushed at herself, and seeing her reflection blush, blushed the more. The change from the customary spot and necessary occasion of such an act -- from the dressing hour in a bedroom to a time of travelling out of doors -- lent to the idle deed a novelty it did not intrinsically possess. The picture was a delicate one. Woman's prescriptive infirmity had stalked into the sunlight, which had clothed it in the freshness of an originality. A cynical inference was irresistible by Gabriel Oak as he regarded the scene, generous though he fain would have been. There was no necessity whatever for her looking in the glass. She did not adjust her hat, or pat her hair, or press a dimple into shape, or do one thing to signify that any such intention had been her motive in taking up the glass. She simply observed herself as a fair product of Nature in the feminine kind, her thoughts seeming to glide into far-off though likely dramas in which men would play a part -- vistas of probable triumphs -- the smiles being of a phase suggesting that hearts were imagined as lost and won. Still, this was but conjecture, and the whole series of actions was so idly put forth as to make it rash to assert that intention had any part in them at all. The waggoner's steps were heard returning. She put the glass in the paper, and the whole again into its place. When the waggon had passed on, Gabriel withdrew from his point of espial, and descending into the road, followed the vehicle to the turnpike-gate some way beyond the bottom of the hill, where the object of his contemplation now halted for the payment of toll. About twenty steps still remained between him and the gate, when he heard a dispute. It was a difference concerning twopence between the persons with the waggon and the man at the toll-bar. "Mis'ess's niece is upon the top of the things, and she says that's enough that I've offered ye, you great miser, and she won't pay any more." These were the waggoner's words. "Very well; then mis'ess's niece can't pass," said the turnpike-keeper, closing the gate. Oak looked from one to the other of the disputants, and fell into a reverie. There was something in the tone of twopence remarkably insignificant. Threepence had a definite value as money -- it was an appreciable infringement on a day's wages, and, as such, a higgling matter; but twopence -- "Here," he said, stepping forward and handing twopence to the gatekeeper; "let the young woman pass." He looked up at her then; she heard his words, and looked down. Gabriel's features adhered throughout their form so exactly to the middle line between the beauty of St. John and the ugliness of Judas Iscariot, as represented in a window of the church he attended, that not a single lineament could be selected and called worthy either of distinction or notoriety. The red-jacketed and dark-haired maiden seemed to think so too, for she carelessly glanced over him, and told her man to drive on. She might have looked her thanks to Gabriel on a minute scale, but she did not speak them; more probably she felt none, for in gaining her a passage he had lost her her point, and we know how women take a favour of that kind. The gatekeeper surveyed the retreating vehicle. "That's a handsome maid," he said to Oak. "But she has her faults," said Gabriel. "True, farmer." "And the greatest of them is -- well, what it is always." "Beating people down? ay, 'tis so." "O no." "What, then?" Gabriel, perhaps a little piqued by the comely traveller's indifference, glanced back to where he had witnessed her performance over the hedge, and said, "Vanity." kbuild-3686/src/oldsed/testsuite/readin.inp0000664000175000017500000000075615053010105020756 0ustar locutuslocutus``Democracy will not come today, this year, nor ever through compromise and fear. I have as much right as the other fellow has to stand on my two feet and own the land. I tire so of hearing people say let things take their course, tomorrow is another day. I do not need my freedom when I'm dead. I cannot live on tomorrow's bread. Freedom is a strong seed planted in a great need. I live here, too. I want freedom just as you.'' ``The Weary Blues'', Langston Hughes kbuild-3686/src/oldsed/testsuite/y-bracket.inp0000664000175000017500000000003115053010105021357 0ustar locutuslocutusAre you sure (y/n)? [y] kbuild-3686/src/oldsed/testsuite/xbxcx.inp0000664000175000017500000000003315053010105020634 0ustar locutuslocutus b bc bac baac baaac baaaackbuild-3686/src/oldsed/testsuite/readin.sed0000664000175000017500000000003415053010105020730 0ustar locutuslocutus/\.$/r readin.in2 /too\.$/q kbuild-3686/src/oldsed/testsuite/noeol.good0000664000175000017500000000011515053010105020757 0ustar locutuslocutusThis file is uniquewakuwaku in that it doeswakuwaku end in a newline.wakuwakukbuild-3686/src/oldsed/testsuite/noeolw.good0000664000175000017500000000032715053010105021153 0ustar locutuslocutusThis file is unique This file is unique in that it does in that it does end in a newline. end in a newline. This file is unique This file is unique in that it does in that it does end in a newline. end in a newline.kbuild-3686/src/oldsed/testsuite/xbxcx.good0000664000175000017500000000004315053010105020777 0ustar locutuslocutusx xbx xbxcx xbxcx xbxcx xbxcx xbxcxkbuild-3686/src/oldsed/testsuite/writeout.sed0000664000175000017500000000003315053010105021347 0ustar locutuslocutus/^Facts ar/w writeout.wout kbuild-3686/src/oldsed/testsuite/recall2.sed0000664000175000017500000000040615053010105021015 0ustar locutuslocutus# Starting from sed 4.1.3, regexes are compiled with REG_NOSUB # if they are used in an address, so that the matcher does not # have to obey leftmost-longest. The tricky part is to recompile # them if they are then used in a substitution. /\(ab*\)\+/ s//>\1abb<||>abbbb< kbuild-3686/src/oldsed/testsuite/xabcx.sed0000664000175000017500000000007215053010105020575 0ustar locutuslocutus# from the ChangeLog (Fri May 21 1993) \xfeetxs/blue/too/ kbuild-3686/src/oldsed/testsuite/linecnt.sed0000664000175000017500000000000215053010105021115 0ustar locutuslocutus= kbuild-3686/src/oldsed/testsuite/distrib.inp0000664000175000017500000000272315053010105021150 0ustar locutuslocutusFrom crash@cygnus.com Wed Mar 8 18:02:42 1995 Received: from s1.msi.umn.edu (s1.msi.umn.edu [128.101.24.1]) by cygnus.com (8.6.9/8.6.9) with ESMTP id SAA21692 for ; Wed, 8 Mar 1995 18:02:41 -0800 Received: from cygint.cygnus.com (cygint.cygnus.com [140.174.1.1]) by s1.msi.umn.edu (8.6.10/8.6.9) with ESMTP id TAA13398 for ; Wed, 8 Mar 1995 19:59:18 -0600 Received: from phydeaux.cygnus.com (phydeaux.cygnus.com [140.174.1.85]) by cygnus.com (8.6.9/8.6.9) with SMTP id SAA21688 for ; Wed, 8 Mar 1995 18:02:33 -0800 From: Jason Molenda Received: by phydeaux.cygnus.com (5.65/4.7) id AA06931; Wed, 8 Mar 1995 18:02:28 -0800 Message-Id: <9503090202.AA06931@phydeaux.cygnus.com> Subject: Note for sed testsuite To: molenda@msi.umn.edu Date: Wed, 8 Mar 1995 18:02:24 -0800 (PST) X-Mailer: ELM [version 2.4 PL23] _Summum Bonum_ All the breath and the bloom of the year in the bag of one bee: All the wonder and wealth of the mine in the heart of one gem: In the core of one pearl all the shade and the shine of the sea: Breath and bloom, shade and shine, -- wonder, wealth, and -- how far above them -- Truth, thats brighter than gem, Trust, that's purer than pearl, -- Brightest truth, purest trust in the universe -- all were for me In the kiss of one girl. -- Robert Browning kbuild-3686/src/oldsed/testsuite/enable.sed0000664000175000017500000000011415053010105020713 0ustar locutuslocutus# inspired by an autoconf generated configure script. s/-*enable-//;s/=.*// kbuild-3686/src/oldsed/testsuite/noeolw.sed0000664000175000017500000000010015053010105020763 0ustar locutuslocutusw noeolw.1out $ { x w noeolw.1out x } h 1,3w noeolw.2out p p kbuild-3686/src/oldsed/testsuite/numsub4.inp0000664000175000017500000000000215053010105021071 0ustar locutuslocutusz kbuild-3686/src/oldsed/testsuite/xbxcx3.inp0000664000175000017500000000003415053010105020720 0ustar locutuslocutus b bc bac baac baaac baaaac kbuild-3686/src/oldsed/testsuite/madding.sed0000664000175000017500000002560015053010105021077 0ustar locutuslocutus# this is from Thomas Hardy's _Far From the Madding Crowd_. # # cf ftp://ftp.cdrom.com/pub/gutenberg/etext94/crowd10a.txt # # the point of this test, in case it isn't obvious, is to overfill fixed # buffers wherever they might be. # s/The girl on the summit of the load sat motionless, surrounded by tables and chairs with their legs upwards, backed by an oak settle, and ornamented in front by pots of geraniums, myrtles, and cactuses, together with a caged canary -- all probably from the windows of the house just vacated. There was also a cat in a willow basket, from the partly-opened lid of which she gazed with half-closed eyes, and affectionately-surveyed the small birds around. The handsome girl waited for some time idly in her place, and the only sound heard in the stillness was the hopping of the canary up and down the perches of its prison. Then she looked attentively downwards. It was not at the bird, nor at the cat; it was at an oblong package tied in paper, and lying between them. She turned her head to learn if the waggoner were coming. He was not yet in sight; and her eyes crept back to the package, her thoughts seeming to run upon what was inside it. At length she drew the article into her lap, and untied the paper covering; a small swing looking- glass was disclosed, in which she proceeded to survey herself attentively. She parted her lips and smiled. It was a fine morning, and the sun lighted up to a scarlet glow the crimson jacket she wore, and painted a soft lustre upon her bright face and dark hair. The myrtles, geraniums, and cactuses packed around her were fresh and green, and at such a leafless season they invested the whole concern of horses, waggon, furniture, and girl with a peculiar vernal charm. What possessed her to indulge in such a performance in the sight of the sparrows, blackbirds, and unperceived farmer who were alone its spectators, -- whether the smile began as a factitious one, to test her capacity in that art, -- nobody knows; it ended certainly in a real smile. She blushed at herself, and seeing her reflection blush, blushed the more. The change from the customary spot and necessary occasion of such an act -- from the dressing hour in a bedroom to a time of travelling out of doors -- lent to the idle deed a novelty it did not intrinsically possess. The picture was a delicate one. Woman's prescriptive infirmity had stalked into the sunlight, which had clothed it in the freshness of an originality. A cynical inference was irresistible by Gabriel Oak as he regarded the scene, generous though he fain would have been. There was no necessity whatever for her looking in the glass. She did not adjust her hat, or pat her hair, or press a dimple into shape, or do one thing to signify that any such intention had been her motive in taking up the glass. She simply observed herself as a fair product of Nature in the feminine kind, her thoughts seeming to glide into far-off though likely dramas in which men would play a part -- vistas of probable triumphs -- the smiles being of a phase suggesting that hearts were imagined as lost and won. Still, this was but conjecture, and the whole series of actions was so idly put forth as to make it rash to assert that intention had any part in them at all. The waggoner's steps were heard returning. She put the glass in the paper, and the whole again into its place. When the waggon had passed on, Gabriel withdrew from his point of espial, and descending into the road, followed the vehicle to the turnpike-gate some way beyond the bottom of the hill, where the object of his contemplation now halted for the payment of toll. About twenty steps still remained between him and the gate, when he heard a dispute. It was a difference concerning twopence between the persons with the waggon and the man at the toll-bar. "Mis'ess's niece is upon the top of the things, and she says that's enough that I've offered ye, you great miser, and she won't pay any more." These were the waggoner's words. "Very well; then mis'ess's niece can't pass," said the turnpike-keeper, closing the gate. Oak looked from one to the other of the disputants, and fell into a reverie. There was something in the tone of twopence remarkably insignificant. Threepence had a definite value as money -- it was an appreciable infringement on a day's wages, and, as such, a higgling matter; but twopence -- "Here," he said, stepping forward and handing twopence to the gatekeeper; "let the young woman pass." He looked up at her then; she heard his words, and looked down. Gabriel's features adhered throughout their form so exactly to the middle line between the beauty of St. John and the ugliness of Judas Iscariot, as represented in a window of the church he attended, that not a single lineament could be selected and called worthy either of distinction or notoriety. The red-jacketed and dark-haired maiden seemed to think so too, for she carelessly glanced over him, and told her man to drive on. She might have looked her thanks to Gabriel on a minute scale, but she did not speak them; more probably she felt none, for in gaining her a passage he had lost her her point, and we know how women take a favour of that kind. The gatekeeper surveyed the retreating vehicle. "That's a handsome maid," he said to Oak. "But she has her faults," said Gabriel. "True, farmer." "And the greatest of them is -- well, what it is always." "Beating people down? ay, 'tis so." "O no." "What, then?" Gabriel, perhaps a little piqued by the comely traveller's indifference, glanced back to where he had witnessed her performance over the hedge, and said, "Vanity."/The girl on the summit of the load sat motionless, surrounded by tables and chairs with their legs upwards, backed by an oak settle, and ornamented in front by pots of geraniums, myrtles, and cactuses, together with a caged canary -- all probably from the windows of the house just vacated. There was also a cat in a willow basket, from the partly-opened lid of which she gazed with half-closed eyes, and affectionately-surveyed the small birds around. The handsome girl waited for some time idly in her place, and the only sound heard in the stillness was the hopping of the canary up and down the perches of its prison. Then she looked attentively downwards. It was not at the bird, nor at the cat; it was at an oblong package tied in paper, and lying between them. She turned her head to learn if the waggoner were coming. He was not yet in sight; and her eyes crept back to the package, her thoughts seeming to run upon what was inside it. At length she drew the article into her lap, and untied the paper covering; a small swing looking- glass was disclosed, in which she proceeded to survey herself attentively. She parted her lips and smiled. It was a fine morning, and the sun lighted up to a scarlet glow the crimson jacket she wore, and painted a soft lustre upon her bright face and dark hair. The myrtles, geraniums, and cactuses packed around her were fresh and green, and at such a leafless season they invested the whole concern of horses, waggon, furniture, and girl with a peculiar vernal charm. What possessed her to indulge in such a performance in the sight of the sparrows, blackbirds, and unperceived farmer who were alone its spectators, -- whether the smile began as a factitious one, to test her capacity in that art, -- nobody knows; it ended certainly in a real smile. She blushed at herself, and seeing her reflection blush, blushed the more. The change from the customary spot and necessary occasion of such an act -- from the dressing hour in a bedroom to a time of travelling out of doors -- lent to the idle deed a novelty it did not intrinsically possess. The picture was a delicate one. Woman's prescriptive infirmity had stalked into the sunlight, which had clothed it in the freshness of an originality. A cynical inference was irresistible by Gabriel Oak as he regarded the scene, generous though he fain would have been. There was no necessity whatever for her looking in the glass. She did not adjust her hat, or pat her hair, or press a dimple into shape, or do one thing to signify that any such intention had been her motive in taking up the glass. She simply observed herself as a fair product of Nature in the feminine kind, her thoughts seeming to glide into far-off though likely dramas in which men would play a part -- vistas of probable triumphs -- the smiles being of a phase suggesting that hearts were imagined as lost and won. Still, this was but conjecture, and the whole series of actions was so idly put forth as to make it rash to assert that intention had any part in them at all. The waggoner's steps were heard returning. She put the glass in the paper, and the whole again into its place. When the waggon had passed on, Gabriel withdrew from his point of espial, and descending into the road, followed the vehicle to the turnpike-gate some way beyond the bottom of the hill, where the object of his contemplation now halted for the payment of toll. About twenty steps still remained between him and the gate, when he heard a dispute. It was a difference concerning twopence between the persons with the waggon and the man at the toll-bar. "Mis'ess's niece is upon the top of the things, and she says that's enough that I've offered ye, you great miser, and she won't pay any more." These were the waggoner's words. "Very well; then mis'ess's niece can't pass," said the turnpike-keeper, closing the gate. Oak looked from one to the other of the disputants, and fell into a reverie. There was something in the tone of twopence remarkably insignificant. Threepence had a definite value as money -- it was an appreciable infringement on a day's wages, and, as such, a higgling matter; but twopence -- "Here," he said, stepping forward and handing twopence to the gatekeeper; "let the young woman pass." He looked up at her then; she heard his words, and looked down. Gabriel's features adhered throughout their form so exactly to the middle line between the beauty of St. John and the ugliness of Judas Iscariot, as represented in a window of the church he attended, that not a single lineament could be selected and called worthy either of distinction or notoriety. The red-jacketed and dark-haired maiden seemed to think so too, for she carelessly glanced over him, and told her man to drive on. She might have looked her thanks to Gabriel on a minute scale, but she did not speak them; more probably she felt none, for in gaining her a passage he had lost her her point, and we know how women take a favour of that kind. The gatekeeper surveyed the retreating vehicle. "That's a handsome maid," he said to Oak. "But she has her faults," said Gabriel. "True, farmer." "And the greatest of them is -- well, what it is always." "Beating people down? ay, 'tis so." "O no." "What, then?" Gabriel, perhaps a little piqued by the comely traveller's indifference, glanced back to where he had witnessed her performance over the hedge, and said, "Vanity, dude."/ kbuild-3686/src/oldsed/testsuite/subwrite.sed0000664000175000017500000000003215053010105021330 0ustar locutuslocutuss/you/YoU/w subwrite.wout kbuild-3686/src/oldsed/testsuite/0range.good0000664000175000017500000000000415053010105021014 0ustar locutuslocutusyes kbuild-3686/src/oldsed/testsuite/madding.good0000664000175000017500000001251515053010105021255 0ustar locutuslocutusThe girl on the summit of the load sat motionless, surrounded by tables and chairs with their legs upwards, backed by an oak settle, and ornamented in front by pots of geraniums, myrtles, and cactuses, together with a caged canary -- all probably from the windows of the house just vacated. There was also a cat in a willow basket, from the partly-opened lid of which she gazed with half-closed eyes, and affectionately-surveyed the small birds around. The handsome girl waited for some time idly in her place, and the only sound heard in the stillness was the hopping of the canary up and down the perches of its prison. Then she looked attentively downwards. It was not at the bird, nor at the cat; it was at an oblong package tied in paper, and lying between them. She turned her head to learn if the waggoner were coming. He was not yet in sight; and her eyes crept back to the package, her thoughts seeming to run upon what was inside it. At length she drew the article into her lap, and untied the paper covering; a small swing looking- glass was disclosed, in which she proceeded to survey herself attentively. She parted her lips and smiled. It was a fine morning, and the sun lighted up to a scarlet glow the crimson jacket she wore, and painted a soft lustre upon her bright face and dark hair. The myrtles, geraniums, and cactuses packed around her were fresh and green, and at such a leafless season they invested the whole concern of horses, waggon, furniture, and girl with a peculiar vernal charm. What possessed her to indulge in such a performance in the sight of the sparrows, blackbirds, and unperceived farmer who were alone its spectators, -- whether the smile began as a factitious one, to test her capacity in that art, -- nobody knows; it ended certainly in a real smile. She blushed at herself, and seeing her reflection blush, blushed the more. The change from the customary spot and necessary occasion of such an act -- from the dressing hour in a bedroom to a time of travelling out of doors -- lent to the idle deed a novelty it did not intrinsically possess. The picture was a delicate one. Woman's prescriptive infirmity had stalked into the sunlight, which had clothed it in the freshness of an originality. A cynical inference was irresistible by Gabriel Oak as he regarded the scene, generous though he fain would have been. There was no necessity whatever for her looking in the glass. She did not adjust her hat, or pat her hair, or press a dimple into shape, or do one thing to signify that any such intention had been her motive in taking up the glass. She simply observed herself as a fair product of Nature in the feminine kind, her thoughts seeming to glide into far-off though likely dramas in which men would play a part -- vistas of probable triumphs -- the smiles being of a phase suggesting that hearts were imagined as lost and won. Still, this was but conjecture, and the whole series of actions was so idly put forth as to make it rash to assert that intention had any part in them at all. The waggoner's steps were heard returning. She put the glass in the paper, and the whole again into its place. When the waggon had passed on, Gabriel withdrew from his point of espial, and descending into the road, followed the vehicle to the turnpike-gate some way beyond the bottom of the hill, where the object of his contemplation now halted for the payment of toll. About twenty steps still remained between him and the gate, when he heard a dispute. It was a difference concerning twopence between the persons with the waggon and the man at the toll-bar. "Mis'ess's niece is upon the top of the things, and she says that's enough that I've offered ye, you great miser, and she won't pay any more." These were the waggoner's words. "Very well; then mis'ess's niece can't pass," said the turnpike-keeper, closing the gate. Oak looked from one to the other of the disputants, and fell into a reverie. There was something in the tone of twopence remarkably insignificant. Threepence had a definite value as money -- it was an appreciable infringement on a day's wages, and, as such, a higgling matter; but twopence -- "Here," he said, stepping forward and handing twopence to the gatekeeper; "let the young woman pass." He looked up at her then; she heard his words, and looked down. Gabriel's features adhered throughout their form so exactly to the middle line between the beauty of St. John and the ugliness of Judas Iscariot, as represented in a window of the church he attended, that not a single lineament could be selected and called worthy either of distinction or notoriety. The red-jacketed and dark-haired maiden seemed to think so too, for she carelessly glanced over him, and told her man to drive on. She might have looked her thanks to Gabriel on a minute scale, but she did not speak them; more probably she felt none, for in gaining her a passage he had lost her her point, and we know how women take a favour of that kind. The gatekeeper surveyed the retreating vehicle. "That's a handsome maid," he said to Oak. "But she has her faults," said Gabriel. "True, farmer." "And the greatest of them is -- well, what it is always." "Beating people down? ay, 'tis so." "O no." "What, then?" Gabriel, perhaps a little piqued by the comely traveller's indifference, glanced back to where he had witnessed her performance over the hedge, and said, "Vanity, dude." kbuild-3686/src/oldsed/testsuite/flipcase.inp0000664000175000017500000000241215053010105021271 0ustar locutuslocutus09 - 02 - 2002 00.00 Tg La7 La7 - 09 - 02 - 2002 00.00 Brand New Tmc 2 - 09 - 02 - 2002 00.10 Tg1 Notte Rai Uno - 09 - 02 - 2002 00.15 Tg Parlamento Rai Due - 09 - 02 - 2002 00.15 Kung Fu - La Leggenda Continua La7 - 09 - 02 - 2002 00.20 Berserk - La CoNFESSIONE Di Gatz Italia 1 Cartoon 09 - 02 - 2002 00.20 Tg3 - Tg3 Meteo Rai TrE - 09 - 02 - 2002 00.25 Meteo 2 Rai Due - 09 - 02 - 2002 00.30 Appuntamento Al CinEMA RaI Due - 09 - 02 - 2002 00.30 Rai Educational - Mediamente Rai Tre - 09 - 02 - 2002 00.35 Profiler Rai Due - 09 - 02 - 2002 00.35 Stampa OggI - Che Tempo Fa Rai Uno - 09 - 02 - 2002 00.45 Rai Educational - Babele: Euro Rai Uno - 09 - 02 - 2002 00.45 BollettINO Della NEVE RETE 4 News 09 - 02 - 2002 00.50 STUDIO Aperto - La Giornata Italia 1 News 09 - 02 - 2002 00.50 BOCCA A Bocca - 2 Tempo Rete 4 Film 09 - 02 - 2002 01.00 AppuntAMENTO Al Cinema Rai Tre - 09 - 02 - 2002 01.00 Music NoN Stop Tmc 2 - 09 - 02 - 2002 01.00 Studio SpORT Italia 1 SporT 09 - 02 - 2002 01.00 Tg 5 - Notte Canale 5 News 09 - 02 - 2002 01.05 Fuori Orario. CosE (Mai) Viste Rai Tre - 09 - 02 - 2002 01.15 RAINOTTE Rai Due - 09 - 02 - 2002 01.15 Sottovoce Rai Uno - 09 - 02 - 2002 01.15 GiOCHI Olimpici InVERNALI - CERIMONIA Di Apertura Rai Tre - 09 - 02 - 2002 01.17 Italia Interroga Rai Due - kbuild-3686/src/oldsed/testsuite/insens.sed0000664000175000017500000000004515053010105020767 0ustar locutuslocutush s/Version: *//p g s/version: *//Ip kbuild-3686/src/oldsed/testsuite/middle.inp0000664000175000017500000000072215053010105020743 0ustar locutuslocutus "...by imposing a tiny bit of order in a communication you are translating, you are carving out a little bit of order in the universe. You will never succeed. Everything will fail and come to an end finally. But you have a chance to carve a little bit of order and maybe even beauty out of the raw materials that surround you everywhere, and I think there is no greater meaning in life." Donald L. Philippi, Oct 1930 - Jan 1993 kbuild-3686/src/oldsed/testsuite/empty.sed0000664000175000017500000000001015053010105020616 0ustar locutuslocutuss/^ *// kbuild-3686/src/oldsed/testsuite/xbxcx.sed0000664000175000017500000000005715053010105020627 0ustar locutuslocutus# from the ChangeLog (Wed Sep 5 2001) s/a*/x/g kbuild-3686/src/oldsed/testsuite/bsd.good0000664000175000017500000003562415053010105020430 0ustar locutuslocutus============ Test 1.1:101 ============ Testing argument parsing First type e1_l1_1 e1_l1_1 e1_l1_2 e1_l1_2 e1_l1_3 e1_l1_3 e1_l1_4 e1_l1_4 e1_l1_5 e1_l1_5 e1_l1_6 e1_l1_6 e1_l1_7 e1_l1_7 e1_l1_8 e1_l1_8 e1_l1_9 e1_l1_9 e1_l1_10 e1_l1_10 e1_l1_11 e1_l1_11 e1_l1_12 e1_l1_12 e1_l1_13 e1_l1_13 e1_l1_14 e1_l1_14 ============ Test 1.2:102 ============ e1_l1_1 e1_l1_2 e1_l1_3 e1_l1_4 e1_l1_5 e1_l1_6 e1_l1_7 e1_l1_8 e1_l1_9 e1_l1_10 e1_l1_11 e1_l1_12 e1_l1_13 e1_l1_14 ============ Test 1.3:103 ============ e1_l1_1 e1_l1_1 e1_l1_2 e1_l1_2 e1_l1_3 e1_l1_3 e1_l1_4 e1_l1_4 e1_l1_5 e1_l1_5 e1_l1_6 e1_l1_6 e1_l1_7 e1_l1_7 e1_l1_8 e1_l1_8 e1_l1_9 e1_l1_9 e1_l1_10 e1_l1_10 e1_l1_11 e1_l1_11 e1_l1_12 e1_l1_12 e1_l1_13 e1_l1_13 e1_l1_14 e1_l1_14 ============ Test 1.4:104 ============ e1_l1_1 e1_l1_2 e1_l1_3 e1_l1_4 e1_l1_5 e1_l1_6 e1_l1_7 e1_l1_8 e1_l1_9 e1_l1_10 e1_l1_11 e1_l1_12 e1_l1_13 e1_l1_14 Second type ============== Test 1.4.1:105 ============== l1_1 l1_2 l1_3 l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 ============ Test 1.5:106 ============ s1_l1_1 s1_l1_1 s1_l1_2 s1_l1_2 s1_l1_3 s1_l1_3 s1_l1_4 s1_l1_4 s1_l1_5 s1_l1_5 s1_l1_6 s1_l1_6 s1_l1_7 s1_l1_7 s1_l1_8 s1_l1_8 s1_l1_9 s1_l1_9 s1_l1_10 s1_l1_10 s1_l1_11 s1_l1_11 s1_l1_12 s1_l1_12 s1_l1_13 s1_l1_13 s1_l1_14 s1_l1_14 ============ Test 1.6:107 ============ s1_l1_1 s1_l1_1 s1_l1_2 s1_l1_2 s1_l1_3 s1_l1_3 s1_l1_4 s1_l1_4 s1_l1_5 s1_l1_5 s1_l1_6 s1_l1_6 s1_l1_7 s1_l1_7 s1_l1_8 s1_l1_8 s1_l1_9 s1_l1_9 s1_l1_10 s1_l1_10 s1_l1_11 s1_l1_11 s1_l1_12 s1_l1_12 s1_l1_13 s1_l1_13 s1_l1_14 s1_l1_14 ============ Test 1.7:108 ============ e1_l1_1 e1_l1_1 e1_l1_2 e1_l1_2 e1_l1_3 e1_l1_3 e1_l1_4 e1_l1_4 e1_l1_5 e1_l1_5 e1_l1_6 e1_l1_6 e1_l1_7 e1_l1_7 e1_l1_8 e1_l1_8 e1_l1_9 e1_l1_9 e1_l1_10 e1_l1_10 e1_l1_11 e1_l1_11 e1_l1_12 e1_l1_12 e1_l1_13 e1_l1_13 e1_l1_14 e1_l1_14 ============ Test 1.8:109 ============ e1_l1_1 e1_l1_1 e1_l1_2 e1_l1_2 e1_l1_3 e1_l1_3 e1_l1_4 e1_l1_4 e1_l1_5 e1_l1_5 e1_l1_6 e1_l1_6 e1_l1_7 e1_l1_7 e1_l1_8 e1_l1_8 e1_l1_9 e1_l1_9 e1_l1_10 e1_l1_10 e1_l1_11 e1_l1_11 e1_l1_12 e1_l1_12 e1_l1_13 e1_l1_13 e1_l1_14 e1_l1_14 ============ Test 1.9:110 ============ s1_l1_1 s1_l1_2 s1_l1_3 s1_l1_4 s1_l1_5 s1_l1_6 s1_l1_7 s1_l1_8 s1_l1_9 s1_l1_10 s1_l1_11 s1_l1_12 s1_l1_13 s1_l1_14 ============= Test 1.10:111 ============= s1_l1_1 s1_l1_2 s1_l1_3 s1_l1_4 s1_l1_5 s1_l1_6 s1_l1_7 s1_l1_8 s1_l1_9 s1_l1_10 s1_l1_11 s1_l1_12 s1_l1_13 s1_l1_14 ============= Test 1.11:112 ============= e1_l1_1 e1_l1_2 e1_l1_3 e1_l1_4 e1_l1_5 e1_l1_6 e1_l1_7 e1_l1_8 e1_l1_9 e1_l1_10 e1_l1_11 e1_l1_12 e1_l1_13 e1_l1_14 ============= Test 1.12:113 ============= e1_l1_1 e1_l1_2 e1_l1_3 e1_l1_4 e1_l1_5 e1_l1_6 e1_l1_7 e1_l1_8 e1_l1_9 e1_l1_10 e1_l1_11 e1_l1_12 e1_l1_13 e1_l1_14 ============= Test 1.13:114 ============= e1_l1_1 e2_e1_l1_1 e2_e1_l1_1 e1_l1_2 e2_e1_l1_2 e2_e1_l1_2 e1_l1_3 e2_e1_l1_3 e2_e1_l1_3 e1_l1_4 e2_e1_l1_4 e2_e1_l1_4 e1_l1_5 e2_e1_l1_5 e2_e1_l1_5 e1_l1_6 e2_e1_l1_6 e2_e1_l1_6 e1_l1_7 e2_e1_l1_7 e2_e1_l1_7 e1_l1_8 e2_e1_l1_8 e2_e1_l1_8 e1_l1_9 e2_e1_l1_9 e2_e1_l1_9 e1_l1_10 e2_e1_l1_10 e2_e1_l1_10 e1_l1_11 e2_e1_l1_11 e2_e1_l1_11 e1_l1_12 e2_e1_l1_12 e2_e1_l1_12 e1_l1_13 e2_e1_l1_13 e2_e1_l1_13 e1_l1_14 e2_e1_l1_14 e2_e1_l1_14 ============= Test 1.14:115 ============= s1_l1_1 s2_s1_l1_1 s2_s1_l1_1 s1_l1_2 s2_s1_l1_2 s2_s1_l1_2 s1_l1_3 s2_s1_l1_3 s2_s1_l1_3 s1_l1_4 s2_s1_l1_4 s2_s1_l1_4 s1_l1_5 s2_s1_l1_5 s2_s1_l1_5 s1_l1_6 s2_s1_l1_6 s2_s1_l1_6 s1_l1_7 s2_s1_l1_7 s2_s1_l1_7 s1_l1_8 s2_s1_l1_8 s2_s1_l1_8 s1_l1_9 s2_s1_l1_9 s2_s1_l1_9 s1_l1_10 s2_s1_l1_10 s2_s1_l1_10 s1_l1_11 s2_s1_l1_11 s2_s1_l1_11 s1_l1_12 s2_s1_l1_12 s2_s1_l1_12 s1_l1_13 s2_s1_l1_13 s2_s1_l1_13 s1_l1_14 s2_s1_l1_14 s2_s1_l1_14 ============= Test 1.15:116 ============= e1_l1_1 s1_e1_l1_1 s1_e1_l1_1 e1_l1_2 s1_e1_l1_2 s1_e1_l1_2 e1_l1_3 s1_e1_l1_3 s1_e1_l1_3 e1_l1_4 s1_e1_l1_4 s1_e1_l1_4 e1_l1_5 s1_e1_l1_5 s1_e1_l1_5 e1_l1_6 s1_e1_l1_6 s1_e1_l1_6 e1_l1_7 s1_e1_l1_7 s1_e1_l1_7 e1_l1_8 s1_e1_l1_8 s1_e1_l1_8 e1_l1_9 s1_e1_l1_9 s1_e1_l1_9 e1_l1_10 s1_e1_l1_10 s1_e1_l1_10 e1_l1_11 s1_e1_l1_11 s1_e1_l1_11 e1_l1_12 s1_e1_l1_12 s1_e1_l1_12 e1_l1_13 s1_e1_l1_13 s1_e1_l1_13 e1_l1_14 s1_e1_l1_14 s1_e1_l1_14 ============= Test 1.16:117 ============= e1_l1_1 e1_l1_1 e1_l1_2 e1_l1_2 e1_l1_3 e1_l1_3 e1_l1_4 e1_l1_4 e1_l1_5 e1_l1_5 e1_l1_6 e1_l1_6 e1_l1_7 e1_l1_7 e1_l1_8 e1_l1_8 e1_l1_9 e1_l1_9 e1_l1_10 e1_l1_10 e1_l1_11 e1_l1_11 e1_l1_12 e1_l1_12 e1_l1_13 e1_l1_13 e1_l1_14 e1_l1_14 e1_l1_1 e1_l1_1 e1_l1_2 e1_l1_2 e1_l1_3 e1_l1_3 e1_l1_4 e1_l1_4 e1_l1_5 e1_l1_5 e1_l1_6 e1_l1_6 e1_l1_7 e1_l1_7 e1_l1_8 e1_l1_8 e1_l1_9 e1_l1_9 e1_l1_10 e1_l1_10 e1_l1_11 e1_l1_11 e1_l1_12 e1_l1_12 e1_l1_13 e1_l1_13 e1_l1_14 e1_l1_14 ============= Test 1.17:118 ============= l1_1 l1_1 l1_2 l1_2 l1_3 l1_3 l1_4 l1_4 l1_5 l1_5 l1_6 l1_6 l1_7 l1_7 l1_8 l1_8 l1_9 l1_9 l1_10 l1_10 l1_11 l1_11 l1_12 l1_12 l1_13 l1_13 l1_14 l1_14 ============= Test 1.18:119 ============= l1_1 l1_2 l1_3 l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 Testing address ranges ============ Test 2.1:120 ============ l1_4 ============ Test 2.2:121 ============ l2_6 ============ Test 2.3:122 ============ l1_14 ============ Test 2.4:123 ============ l2_9 ============ Test 2.5:124 ============ ============ Test 2.6:125 ============ l2_9 ============ Test 2.7:126 ============ ============ Test 2.9:127 ============ l1_7 ============= Test 2.10:128 ============= l1_7 ============= Test 2.11:129 ============= l1_7 ============= Test 2.12:130 ============= l1_1 l1_2 l1_3 l1_4 ============= Test 2.13:131 ============= l1_1 l1_2 l1_3 l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 l2_1 l2_2 l2_3 l2_4 l2_5 l2_6 l2_7 l2_8 l2_9 ============= Test 2.14:132 ============= l1_1 l1_2 l1_3 l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 l2_1 l2_2 l2_3 l2_4 l2_5 l2_6 l2_7 l2_8 l2_9 ============= Test 2.15:133 ============= l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 l2_1 l2_2 l2_3 l2_4 l2_5 l2_6 l2_7 l2_8 l2_9 ============= Test 2.16:134 ============= l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 l2_1 l2_2 l2_3 l2_4 l2_5 l2_6 ============= Test 2.17:135 ============= l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_14 l2_1 l2_2 l2_3 l2_4 l2_5 l2_6 l2_7 l2_8 l2_9 ============= Test 2.18:136 ============= l2_3 l2_4 l2_5 l2_6 l2_7 l2_8 l2_9 ============= Test 2.19:137 ============= l1_12 ============= Test 2.20:138 ============= l1_7 Brace and other grouping ============ Test 3.1:139 ============ l1_1 l1_2 l1_3 ^l1T4$ ^l1T5$ ^l1T6$ ^l1T7$ ^l1T8$ ^l1T9$ ^l1T10$ ^l1T11$ ^l1T12$ l1_13 l1_14 ============ Test 3.2:140 ============ l1_1 l1_2 l1_3 ^l1_4 ^l1_5 ^l1_6$ ^l1_7$ ^l1T8$ ^l1_9$ ^l1_10$ ^l1_11 ^l1_12 l1_13 l1_14 ============ Test 3.3:141 ============ ^l1T1$ ^l1T2$ ^l1T3$ l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 ^l1T13$ ^l1T14$ ============ Test 3.4:142 ============ ^l1_1 ^l1_2 ^l1_3 l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 ^l1_13 ^l1_14 Testing a c d and i commands ============ Test 4.1:143 ============ before_il1_1 after_ibefore_il1_1 before_il1_2 after_ibefore_il1_2 before_il1_3 after_ibefore_il1_3 before_il1_4 after_ibefore_il1_4 before_il1_5 after_ibefore_il1_5 before_il1_6 after_ibefore_il1_6 before_il1_7 after_ibefore_il1_7 before_il1_8 after_ibefore_il1_8 before_il1_9 after_ibefore_il1_9 before_il1_10 after_ibefore_il1_10 before_il1_11 after_ibefore_il1_11 before_il1_12 after_ibefore_il1_12 before_il1_13 after_ibefore_il1_13 before_il1_14 after_ibefore_il1_14 before_il2_1 after_ibefore_il2_1 before_il2_2 after_ibefore_il2_2 before_il2_3 after_ibefore_il2_3 before_il2_4 after_ibefore_il2_4 before_il2_5 after_ibefore_il2_5 before_il2_6 inserted after_ibefore_il2_6 before_il2_7 after_ibefore_il2_7 before_il2_8 after_ibefore_il2_8 before_il2_9 after_ibefore_il2_9 ============ Test 4.2:144 ============ before_al1_1 after_abefore_al1_1 before_al1_2 after_abefore_al1_2 before_al1_3 after_abefore_al1_3 before_al1_4 after_abefore_al1_4 before_a5-12l1_5 after_abefore_a5-12l1_5 appended before_a5-12l1_6 after_abefore_a5-12l1_6 appended before_a5-12l1_7 after_abefore_a5-12l1_7 appended before_a5-12l1_8 after_abefore_a5-12l1_8 appended before_a5-12l1_9 after_abefore_a5-12l1_9 appended before_a5-12l1_10 after_abefore_a5-12l1_10 appended before_a5-12l1_11 after_abefore_a5-12l1_11 appended before_a5-12l1_12 after_abefore_a5-12l1_12 appended before_al1_13 after_abefore_al1_13 before_al1_14 after_abefore_al1_14 before_al2_1 after_abefore_al2_1 before_al2_2 after_abefore_al2_2 before_al2_3 after_abefore_al2_3 before_al2_4 after_abefore_al2_4 before_al2_5 after_abefore_al2_5 before_al2_6 after_abefore_al2_6 before_al2_7 after_abefore_al2_7 before_al2_8 after_abefore_al2_8 before_al2_9 after_abefore_al2_9 ============ Test 4.3:145 ============ ^l1_1 ^l1_1$ appended ^l1_2 ^l1_2$ appended ^l1_3 ^l1_3$ appended ^l1_4 ^l1_4$ appended ^l1_5 ^l1_5$ appended ^l1_6 ^l1_6$ appended ^l1_7 ^l1_7$ appended ^l1_8 appended ^l1_8 l1_9$ ^l1_10 appended ^l1_10 l1_11$ ^l1_12 ^l1_12$ appended ^l1_13 ^l1_13$ appended ^l1_14 ^l1_14$ appended ^l2_1 ^l2_1$ ^l2_2 ^l2_2$ ^l2_3 ^l2_3$ ^l2_4 ^l2_4$ ^l2_5 ^l2_5$ ^l2_6 ^l2_6$ ^l2_7 ^l2_7$ ^l2_8 ^l2_8$ ^l2_9 ^l2_9$ ============ Test 4.4:146 ============ hello hello hello hello hello hello hello hello hello hello hello hello hello hello ============ Test 4.5:147 ============ hello ============ Test 4.6:148 ============ hello ============ Test 4.7:149 ============ hello ============ Test 4.8:150 ============ Testing labels and branching ============ Test 5.1:151 ============ label2_l1_1 label3_label2_l1_1 label1_l1_2 label1_l1_3 label1_l1_4 label1_l1_5 label1_l1_6 label1_l1_7 label1_l1_8 label1_l1_9 label1_l1_10 label1_l1_11 label1_l1_12 label2_l1_13 label3_label2_l1_13 label2_l1_14 label3_label2_l1_14 ============ Test 5.2:152 ============ tested l2_1 tested l2_2 tested l2_3 tested l2_4 tested l2_5 tested l2_6 tested l2_7 tested l2_8 tested l2_9 tested l2_10 tested l2_11 tested l2_12 tested l2_13 tested l2_14 ============ Test 5.3:153 ============ ^l1_1 ^l1_1$ ^l1_2 ^l1_2$ ^l1_3 ^l1_3$ ^l1_4 ^l1_4$ l1_5$ l1_6$ l1_7$ l1_8$ ============ Test 5.4:154 ============ ^l1_1$ ^l1_2$ ^l1_3$ ^l1_4$ ^l1_5$ ^l1_6$ ^l1_7$ ^l1_8$ l1_9$ l1_10$ l1_11$ l1_12$ l1_13$ l1_14$ ============ Test 5.5:155 ============ ^l1_1 ^l1_2 ^l1_4 ^l1_6 ^l1_8 ============ Test 5.6:156 ============ l1_1 l1_2 l1_3 l1_4 l1_5 ============ Test 5.7:157 ============ l1_1 l1_2 l1_3 l1_4 hello l1_5 ============ Test 5.8:158 ============ m1_1 m1_2 m1_3 m1_4 m1_5 m1_6 m1_7 m1_8 m1_9 m1_10 m1_11 m1_12 m1_13 m1_14 Pattern space commands ============ Test 6.1:159 ============ changed changed changed changed changed changed changed changed changed changed changed changed changed changed ============ Test 6.2:160 ============ l1_1 l1_2 l1_3 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 ============ Test 6.3:161 ============ l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 ============ Test 6.4:162 ============ l1_1 l1_2 l1_3 l1_2 l1_3 l1_5 l1_2 l1_3 l1_2 l1_3 l1_6 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 ============ Test 6.5:163 ============ l1_1 l1_2 l1_3 l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 ============ Test 6.6:164 ============ Testing print and file routines ============ Test 7.1:165 ============ \001\002\003\004\005\006\a\b\t$ \v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\ \035\036\037 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX\ YZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\ \206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\ \227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\ \250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\ \271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\ \312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\ \333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\ \354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\ \375\376\377$ $ ============ Test 7.2:166 ============ l1_1 l1_2 l1_3 l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 15 l2_1 16 l2_2 17 l2_3 18 l2_4 19 l2_5 20 l2_6 21 l2_7 22 l2_8 23 l2_9 ============ Test 7.3:167 ============ l1_1 l1_2 l1_3 l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 w results l1_3 l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 ============ Test 7.4:168 ============ l1_1 l1_2 l1_3 l1_4 l2_1 l2_2 l2_3 l2_4 l2_5 l2_6 l2_7 l2_8 l2_9 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 ============ Test 7.5:169 ============ l1_1 l1_2 l1_3 l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 ============ Test 7.6:170 ============ l1_1 l1_2 l1_3 l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 ============ Test 7.8:171 ============ Testing substitution commands ============ Test 8.1:172 ============ XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXXX XXXXX XXXXX XXXXX XXXXX ============ Test 8.2:173 ============ XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXXX XXXXX XXXXX XXXXX XXXXX ============ Test 8.3:174 ============ XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXXX XXXXX XXXXX XXXXX XXXXX ============ Test 8.4:175 ============ l1_1 l1_2 l1_3 l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 ============ Test 8.5:176 ============ l1X1 l1X2 l1X3 l1X4 l1X5 l1X6 l1X7 l1X8 l1X9 l1X10 l1X11 l1X12 l1X13 l1X14 ============ Test 8.6:177 ============ (l)(1)(_)(1) (l)(1)(_)(2) (l)(1)(_)(3) (l)(1)(_)(4) (l)(1)(_)(5) (l)(1)(_)(6) (l)(1)(_)(7) (l)(1)(_)(8) (l)(1)(_)(9) (l)(1)(_)(1)(0) (l)(1)(_)(1)(1) (l)(1)(_)(1)(2) (l)(1)(_)(1)(3) (l)(1)(_)(1)(4) ============ Test 8.7:178 ============ (&)(&)(&)(&) (&)(&)(&)(&) (&)(&)(&)(&) (&)(&)(&)(&) (&)(&)(&)(&) (&)(&)(&)(&) (&)(&)(&)(&) (&)(&)(&)(&) (&)(&)(&)(&) (&)(&)(&)(&)(&) (&)(&)(&)(&)(&) (&)(&)(&)(&)(&) (&)(&)(&)(&)(&) (&)(&)(&)(&)(&) ============ Test 8.8:179 ============ x_x1xl1 x_x1xl2 x_x1xl3 x_x1xl4 x_x1xl5 x_x1xl6 x_x1xl7 x_x1xl8 x_x1xl9 x_x1xl10 x_x1xl11 x_x1xl12 x_x1xl13 x_x1xl14 ============ Test 8.9:180 ============ l1u0 u1 u21 l1u0 u1 u22 l1u0 u1 u23 l1u0 u1 u24 l1u0 u1 u25 l1u0 u1 u26 l1u0 u1 u27 l1u0 u1 u28 l1u0 u1 u29 l1u0 u1 u210 l1u0 u1 u211 l1u0 u1 u212 l1u0 u1 u213 l1u0 u1 u214 ============= Test 8.10:181 ============= l1_X l1_X l1_X l1_X l1_X l1_X l1_X l1_X l1_X l1_X0 l1_X1 l1_X2 l1_X3 l1_X4 ============= Test 8.11:182 ============= lX_1 lX_2 lX_3 lX_4 lX_5 lX_6 lX_7 lX_8 lX_9 lX_10 lX_11 lX_12 lX_13 lX_14 s wfile results lX_1 lX_2 lX_3 lX_4 lX_5 lX_6 lX_7 lX_8 lX_9 lX_10 lX_11 lX_12 lX_13 lX_14 ============= Test 8.12:183 ============= lX_X lX_X lX_X lX_4 lX_5 lX_6 lX_7 lX_8 lX_9 lX_X0 lX_XX lX_XX lX_XX lX_X4 ============= Test 8.13:184 ============= l8_8 l8_7 l8_6 l8_5 l8_4 l8_3 l8_2 l8_1 l8_0 l8_89 l8_88 l8_87 l8_86 l8_85 ============= Test 8.14:185 ============= l8_8 l8_7 l8_6 l8_5 l8_4 l8_3 l8_2 l8_1 l8_0 l8_89 l8_88 l8_87 l8_86 l8_85 ============= Test 8.15:186 ============= l1_1Xl1_2 l1_3 l1_4 l1_5 l1_6 l1_7 l1_8 l1_9 l1_10 l1_11 l1_12 l1_13 l1_14 ============= Test 8.16:187 ============= eeefff Xeefff XYefff XYeYff XYeYYf XYeYYY XYeYYY kbuild-3686/src/oldsed/testsuite/middle.good0000664000175000017500000000031015053010105021076 0ustar locutuslocutus universe. You will never succeed. Everything will fail and come to an end finally. But you have a chance to carve a little bit of order and maybe even beauty out of the raw materials that kbuild-3686/src/oldsed/testsuite/bug-regex15.c0000664000175000017500000000204115053010105021170 0ustar locutuslocutus/* Test for memory/CPU leak in regcomp. */ #include #include #include #include #include #include #define TEST_DATA_LIMIT (32 << 20) int main () { #ifdef RLIMIT_DATA regex_t re; int reerr; /* Try to avoid eating all memory if a test leaks. */ struct rlimit data_limit; if (getrlimit (RLIMIT_DATA, &data_limit) == 0) { if ((rlim_t) TEST_DATA_LIMIT > data_limit.rlim_max) data_limit.rlim_cur = data_limit.rlim_max; else if (data_limit.rlim_cur > (rlim_t) TEST_DATA_LIMIT) data_limit.rlim_cur = (rlim_t) TEST_DATA_LIMIT; if (setrlimit (RLIMIT_DATA, &data_limit) < 0) perror ("setrlimit: RLIMIT_DATA"); } else perror ("getrlimit: RLIMIT_DATA"); reerr = regcomp (&re, "^6?3?[25]?5?[14]*[25]*[69]*+[58]*87?4?$", REG_EXTENDED | REG_NOSUB); if (reerr != 0) { char buf[100]; regerror (reerr, &re, buf, sizeof buf); printf ("regerror %s\n", buf); return 1; } return 0; #else return 77; #endif } kbuild-3686/src/oldsed/testsuite/cv-vars.inp0000664000175000017500000000022415053010105021063 0ustar locutuslocutus_cv_=emptyvar ac_cv_prog_RANLIB=/usr/bin/ranlib ac_cv_prog_CC=/usr/unsupported/\ \ /lib/_cv_/cc ac_cv_prog_CPP=/usr/bin/cpp SHELL=bash GNU=GNU!UNIX kbuild-3686/src/oldsed/testsuite/bug-regex9.c0000664000175000017500000000346715053010105021130 0ustar locutuslocutus/* Test for memory handling in regex. Copyright (C) 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2001. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #ifdef HAVE_MCHECK_H #include #endif #include #include #include static const char text[] = "#! /bin/sh"; int main (void) { regex_t re; regmatch_t rm[2]; int n; #ifdef HAVE_MCHECK_H mtrace (); #endif n = regcomp (&re, "^#! */.*/(k|ba||pdk|z)sh", REG_EXTENDED); if (n != 0) { char buf[500]; regerror (n, &re, buf, sizeof (buf)); printf ("regcomp failed: %s\n", buf); exit (1); } for (n = 0; n < 20; ++n) { if (regexec (&re, text, 2, rm, 0)) { puts ("regexec failed"); exit (2); } if (rm[0].rm_so != 0 || rm[0].rm_eo != 10 || rm[1].rm_so != 8 || rm[1].rm_eo != 8) { printf ("regexec match failure: %d %d %d %d\n", rm[0].rm_so, rm[0].rm_eo, rm[1].rm_so, rm[1].rm_eo); exit (3); } } regfree (&re); return 0; } kbuild-3686/src/oldsed/testsuite/xemacs.sed0000664000175000017500000000031215053010105020745 0ustar locutuslocutus# Inspired by xemacs' config.status script # submitted by John Fremlin (john@fremlin.de) /^# Generated/d s%/\*\*/#.*%% s/^ *# */#/ /^##/d /^#/ { p d } /./ { s/\([\"]\)/\\\1/g s/^/"/ s/$/"/ } kbuild-3686/src/oldsed/testsuite/appquit.sed0000664000175000017500000000003615053010105021153 0ustar locutuslocutus# Test appending quit a\ ok q kbuild-3686/src/oldsed/testsuite/recall.inp0000664000175000017500000000000715053010105020743 0ustar locutuslocutuseeefff kbuild-3686/src/oldsed/testsuite/head.good0000664000175000017500000000031015053010105020541 0ustar locutuslocutus "...by imposing a tiny bit of order in a communication you are translating, you are carving out a little bit of order in the universe. You will never succeed. Everything will fail and come kbuild-3686/src/oldsed/testsuite/fasts.inp0000664000175000017500000000002515053010105020621 0ustar locutuslocutusaaaaaaabbbbbbaaaaaaa kbuild-3686/src/oldsed/testsuite/subwrite.inp0000664000175000017500000000021215053010105021343 0ustar locutuslocutusNot some church, and not the state, Not some dark capricious fate. Who you are, and when you lose, Comes only from the things you choose. kbuild-3686/src/oldsed/testsuite/modulo.inp0000664000175000017500000000073115053010105021004 0ustar locutuslocutuss%@CFLAGS@%%g s%@CPPFLAGS@%-I/%g s%@CXXFLAGS@%-x c++%g s%@DEFS@%$DEFS%g s%@LDFLAGS@%-L/usr/lib%g s%@LIBS@%-lgnu -lbfd%g s%@exec_prefix@%%g s%@prefix@%$prefix%g s%@RANLIB@%$RANLIB%g s%@CC@%/usr/local/bin/gcc%g s%@CPP@%$CPP%g s%@XCFLAGS@%$XCFLAGS%g s%@XINCLUDES@%$XINCLUDES%g s%@XLIBS@%$XLIBS%g s%@XPROGS@%$XPROGS%g s%@TCLHDIR@%$TCLHDIR%g s%@TCLLIB@%$TCLLIB%g s%@TKHDIR@%$TKHDIR%g s%@TKLIB@%$TKLIB%g s%@PTY_TYPE@%$PTY_TYPE%g s%@EVENT_TYPE@%$EVENT_TYPE%g s%@SETUID@%$SETUID%g kbuild-3686/src/oldsed/testsuite/dc.inp0000664000175000017500000000052415053010105020073 0ustar locutuslocutus# Compute Easter of 2002... # usage: (echo YEAR; cat easter.dc) | dc 2002 [ddsf[lfp[too early ]Pq]s@1583>@ ddd19%1+sg100/1+d3*4/12-sx8*5+25/5-sz5*4/lx-10-sdlg11*20+lz+lx-30% d[30+]s@0>@d[[1+]s@lg11<@]s@25=@d[1+]s@24=@se44le-d[30+]s@21>@dld+7%-7+ [March ]smd[31-[April ]sm]s@31<@psnlmPpsn1z>p]splpx # Compute square root of 2 16oAk2vpqkbuild-3686/src/oldsed/testsuite/xabcx.inp0000664000175000017500000000010315053010105020603 0ustar locutuslocutusroses are red violets are blue my feet are cold your feet are blue kbuild-3686/src/oldsed/testsuite/dollar.good0000664000175000017500000000016415053010105021124 0ustar locutuslocutusI can't quite remember where I heard it, but I can't seem to get out of my head the phrase space the final frontier kbuild-3686/src/oldsed/testsuite/subwrt1.good0000664000175000017500000000021215053010105021250 0ustar locutuslocutusNot some church, and not the state, Not some dark capricious fate. Who YoU are, and when you lose, Comes only from the things YoU choose. kbuild-3686/src/oldsed/testsuite/middle.sed0000664000175000017500000000000515053010105020722 0ustar locutuslocutus3,5p kbuild-3686/src/oldsed/testsuite/empty.inp0000664000175000017500000000000315053010105020633 0ustar locutuslocutusx kbuild-3686/src/oldsed/testsuite/noeolw.1good0000664000175000017500000000017415053010105021234 0ustar locutuslocutusThis file is unique in that it does end in a newline. This file is unique in that it does end in a newline. in that it does kbuild-3686/src/oldsed/testsuite/PCRE.tests0000664000175000017500000006260015053010105020615 0ustar locutuslocutus# PCRE version 4.4 21-August-2003 # Tests taken from PCRE and modified to suit glibc regex. # # 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-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. 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 # /the quick brown fox/ the quick brown fox 0: the quick brown fox The quick brown FOX No match What do you know about the quick brown fox? 0: the quick brown fox What do you know about THE QUICK BROWN FOX? No match /The quick brown fox/i the quick brown fox 0: the quick brown fox The quick brown FOX 0: The quick brown FOX What do you know about the quick brown fox? 0: the quick brown fox What do you know about THE QUICK BROWN FOX? 0: THE QUICK BROWN FOX /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/ abxyzpqrrrabbxyyyypqAzz 0: abxyzpqrrrabbxyyyypqAzz abxyzpqrrrabbxyyyypqAzz 0: abxyzpqrrrabbxyyyypqAzz aabxyzpqrrrabbxyyyypqAzz 0: aabxyzpqrrrabbxyyyypqAzz aaabxyzpqrrrabbxyyyypqAzz 0: aaabxyzpqrrrabbxyyyypqAzz aaaabxyzpqrrrabbxyyyypqAzz 0: aaaabxyzpqrrrabbxyyyypqAzz abcxyzpqrrrabbxyyyypqAzz 0: abcxyzpqrrrabbxyyyypqAzz aabcxyzpqrrrabbxyyyypqAzz 0: aabcxyzpqrrrabbxyyyypqAzz aaabcxyzpqrrrabbxyyyypAzz 0: aaabcxyzpqrrrabbxyyyypAzz aaabcxyzpqrrrabbxyyyypqAzz 0: aaabcxyzpqrrrabbxyyyypqAzz aaabcxyzpqrrrabbxyyyypqqAzz 0: aaabcxyzpqrrrabbxyyyypqqAzz aaabcxyzpqrrrabbxyyyypqqqAzz 0: aaabcxyzpqrrrabbxyyyypqqqAzz aaabcxyzpqrrrabbxyyyypqqqqAzz 0: aaabcxyzpqrrrabbxyyyypqqqqAzz aaabcxyzpqrrrabbxyyyypqqqqqAzz 0: aaabcxyzpqrrrabbxyyyypqqqqqAzz aaabcxyzpqrrrabbxyyyypqqqqqqAzz 0: aaabcxyzpqrrrabbxyyyypqqqqqqAzz aaaabcxyzpqrrrabbxyyyypqAzz 0: aaaabcxyzpqrrrabbxyyyypqAzz abxyzzpqrrrabbxyyyypqAzz 0: abxyzzpqrrrabbxyyyypqAzz aabxyzzzpqrrrabbxyyyypqAzz 0: aabxyzzzpqrrrabbxyyyypqAzz aaabxyzzzzpqrrrabbxyyyypqAzz 0: aaabxyzzzzpqrrrabbxyyyypqAzz aaaabxyzzzzpqrrrabbxyyyypqAzz 0: aaaabxyzzzzpqrrrabbxyyyypqAzz abcxyzzpqrrrabbxyyyypqAzz 0: abcxyzzpqrrrabbxyyyypqAzz aabcxyzzzpqrrrabbxyyyypqAzz 0: aabcxyzzzpqrrrabbxyyyypqAzz aaabcxyzzzzpqrrrabbxyyyypqAzz 0: aaabcxyzzzzpqrrrabbxyyyypqAzz aaaabcxyzzzzpqrrrabbxyyyypqAzz 0: aaaabcxyzzzzpqrrrabbxyyyypqAzz aaaabcxyzzzzpqrrrabbbxyyyypqAzz 0: aaaabcxyzzzzpqrrrabbbxyyyypqAzz aaaabcxyzzzzpqrrrabbbxyyyyypqAzz 0: aaaabcxyzzzzpqrrrabbbxyyyyypqAzz aaabcxyzpqrrrabbxyyyypABzz 0: aaabcxyzpqrrrabbxyyyypABzz aaabcxyzpqrrrabbxyyyypABBzz 0: aaabcxyzpqrrrabbxyyyypABBzz >>>aaabxyzpqrrrabbxyyyypqAzz 0: aaabxyzpqrrrabbxyyyypqAzz >aaaabxyzpqrrrabbxyyyypqAzz 0: aaaabxyzpqrrrabbxyyyypqAzz >>>>abcxyzpqrrrabbxyyyypqAzz 0: abcxyzpqrrrabbxyyyypqAzz *** Failers No match abxyzpqrrabbxyyyypqAzz No match abxyzpqrrrrabbxyyyypqAzz No match abxyzpqrrrabxyyyypqAzz No match aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz No match aaaabcxyzzzzpqrrrabbbxyyypqAzz No match aaabcxyzpqrrrabbxyyyypqqqqqqqAzz No match /^(abc){1,2}zz/ abczz 0: abczz 1: abc abcabczz 0: abcabczz 1: abc *** Failers No match zz No match abcabcabczz No match >>abczz No match /^(b+|a){1,2}c/ bc 0: bc 1: b bbc 0: bbc 1: bb bbbc 0: bbbc 1: bbb bac 0: bac 1: a bbac 0: bbac 1: a aac 0: aac 1: a abbbbbbbbbbbc 0: abbbbbbbbbbbc 1: bbbbbbbbbbb bbbbbbbbbbbac 0: bbbbbbbbbbbac 1: a *** Failers No match aaac No match abbbbbbbbbbbac No match /^[]cde]/ ]thing 0: ] cthing 0: c dthing 0: d ething 0: e *** Failers No match athing No match fthing No match /^[^]cde]/ athing 0: a fthing 0: f *** Failers 0: * ]thing No match cthing No match dthing No match ething No match /^[0-9]+$/ 0 0: 0 1 0: 1 2 0: 2 3 0: 3 4 0: 4 5 0: 5 6 0: 6 7 0: 7 8 0: 8 9 0: 9 10 0: 10 100 0: 100 *** Failers No match abc No match /^.*nter/ enter 0: enter inter 0: inter uponter 0: uponter /^xxx[0-9]+$/ xxx0 0: xxx0 xxx1234 0: xxx1234 *** Failers No match xxx No match /^.+[0-9][0-9][0-9]$/ x123 0: x123 xx123 0: xx123 123456 0: 123456 *** Failers No match 123 No match x1234 0: x1234 /^([^!]+)!(.+)=apquxz\.ixr\.zzz\.ac\.uk$/ abc!pqr=apquxz.ixr.zzz.ac.uk 0: abc!pqr=apquxz.ixr.zzz.ac.uk 1: abc 2: pqr *** Failers No match !pqr=apquxz.ixr.zzz.ac.uk No match abc!=apquxz.ixr.zzz.ac.uk No match abc!pqr=apquxz:ixr.zzz.ac.uk No match abc!pqr=apquxz.ixr.zzz.ac.ukk No match /:/ Well, we need a colon: somewhere 0: : *** Fail if we don't No match /([0-9a-f:]+)$/i 0abc 0: 0abc 1: 0abc abc 0: abc 1: abc fed 0: fed 1: fed E 0: E 1: E :: 0: :: 1: :: 5f03:12C0::932e 0: 5f03:12C0::932e 1: 5f03:12C0::932e fed def 0: def 1: def Any old stuff 0: ff 1: ff *** Failers No match 0zzz No match gzzz No match Any old rubbish No match /^.*\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/ .1.2.3 0: .1.2.3 1: 1 2: 2 3: 3 A.12.123.0 0: A.12.123.0 1: 12 2: 123 3: 0 *** Failers No match .1.2.3333 No match 1.2.3 No match 1234.2.3 No match /^([0-9]+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/ 1 IN SOA non-sp1 non-sp2( 0: 1 IN SOA non-sp1 non-sp2( 1: 1 2: non-sp1 3: non-sp2 1 IN SOA non-sp1 non-sp2 ( 0: 1 IN SOA non-sp1 non-sp2 ( 1: 1 2: non-sp1 3: non-sp2 *** Failers No match 1IN SOA non-sp1 non-sp2( No match /^[a-zA-Z0-9][a-zA-Z0-9-]*(\.[a-zA-Z0-9][a-zA-z0-9-]*)*\.$/ a. 0: a. Z. 0: Z. 2. 0: 2. ab-c.pq-r. 0: ab-c.pq-r. 1: .pq-r sxk.zzz.ac.uk. 0: sxk.zzz.ac.uk. 1: .uk x-.y-. 0: x-.y-. 1: .y- *** Failers No match -abc.peq. No match /^\*\.[a-z]([a-z0-9-]*[a-z0-9]+)?(\.[a-z]([a-z0-9-]*[a-z0-9]+)?)*$/ *.a 0: *.a *.b0-a 0: *.b0-a 1: 0-a *.c3-b.c 0: *.c3-b.c 1: 3-b 2: .c *.c-a.b-c 0: *.c-a.b-c 1: -a 2: .b-c 3: -c *** Failers No match *.0 No match *.a- No match *.a-b.c- No match *.c-a.0-c No match /^[0-9a-f](\.[0-9a-f])*$/i a.b.c.d 0: a.b.c.d 1: .d A.B.C.D 0: A.B.C.D 1: .D a.b.c.1.2.3.C 0: a.b.c.1.2.3.C 1: .C /^".*"\s*(;.*)?$/ "1234" 0: "1234" "abcd" ; 0: "abcd" ; 1: ; "" ; rhubarb 0: "" ; rhubarb 1: ; rhubarb *** Failers No match "1234" : things No match /^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/ abcdefhijklm 0: abcdefhijklm 1: abc 2: bc 3: c 4: def 5: ef 6: f 7: hij 8: ij 9: j 10: klm 11: lm 12: m /^a*\w/ z 0: z az 0: az aaaz 0: aaaz a 0: a aa 0: aa aaaa 0: aaaa a+ 0: a aa+ 0: aa /^a+\w/ az 0: az aaaz 0: aaaz aa 0: aa aaaa 0: aaaa aa+ 0: aa /^[0-9]{8}\w{2,}/ 1234567890 0: 1234567890 12345678ab 0: 12345678ab 12345678__ 0: 12345678__ *** Failers No match 1234567 No match /^[aeiou0-9]{4,5}$/ uoie 0: uoie 1234 0: 1234 12345 0: 12345 aaaaa 0: aaaaa *** Failers No match 123456 No match /\`(abc|def)=(\1){2,3}\'/ abc=abcabc 0: abc=abcabc 1: abc 2: abc def=defdefdef 0: def=defdefdef 1: def 2: def *** Failers No match abc=defdef No match /(cat(a(ract|tonic)|erpillar)) \1()2(3)/ cataract cataract23 0: cataract cataract23 1: cataract 2: aract 3: ract 4: 5: 3 catatonic catatonic23 0: catatonic catatonic23 1: catatonic 2: atonic 3: tonic 4: 5: 3 caterpillar caterpillar23 0: caterpillar caterpillar23 1: caterpillar 2: erpillar 3: 4: 5: 3 /^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/ From abcd Mon Sep 01 12:33:02 1997 0: From abcd Mon Sep 01 12:33 1: abcd /^From\s+\S+\s+([a-zA-Z]{3}\s+){2}[0-9]{1,2}\s+[0-9][0-9]:[0-9][0-9]/ From abcd Mon Sep 01 12:33:02 1997 0: From abcd Mon Sep 01 12:33 1: Sep From abcd Mon Sep 1 12:33:02 1997 0: From abcd Mon Sep 1 12:33 1: Sep *** Failers No match From abcd Sep 01 12:33:02 1997 No match /^(a)\1{2,3}(.)/ aaab 0: aaab 1: a 2: b aaaab 0: aaaab 1: a 2: b aaaaab 0: aaaaa 1: a 2: a aaaaaab 0: aaaaa 1: a 2: a /^[ab]{1,3}(ab*|b)/ aabbbbb 0: aabbbbb 1: abbbbb /^(cow|)\1(bell)/ cowcowbell 0: cowcowbell 1: cow 2: bell bell 0: bell 1: 2: bell *** Failers No match cowbell No match /^(a|)\1+b/ aab 0: aab 1: a aaaab 0: aaaab 1: a b 0: b 1: *** Failers No match ab No match /^(a|)\1{2}b/ aaab 0: aaab 1: a b 0: b 1: *** Failers No match ab No match aab No match aaaab No match /^(a|)\1{2,3}b/ aaab 0: aaab 1: a aaaab 0: aaaab 1: a b 0: b 1: *** Failers No match ab No match aab No match aaaaab No match /ab{1,3}bc/ abbbbc 0: abbbbc abbbc 0: abbbc abbc 0: abbc *** Failers No match abc No match abbbbbc No match /([^.]*)\.([^:]*):[T ]+(.*)/ track1.title:TBlah blah blah 0: track1.title:TBlah blah blah 1: track1 2: title 3: Blah blah blah /([^.]*)\.([^:]*):[T ]+(.*)/i track1.title:TBlah blah blah 0: track1.title:TBlah blah blah 1: track1 2: title 3: Blah blah blah /([^.]*)\.([^:]*):[t ]+(.*)/i track1.title:TBlah blah blah 0: track1.title:TBlah blah blah 1: track1 2: title 3: Blah blah blah /^abc$/ abc 0: abc *** Failers No match /[-az]+/ az- 0: az- *** Failers 0: a b No match /[az-]+/ za- 0: za- *** Failers 0: a b No match /[a-z]+/ abcdxyz 0: abcdxyz /[0-9-]+/ 12-34 0: 12-34 *** Failers No match aaa No match /(abc)\1/i abcabc 0: abcabc 1: abc ABCabc 0: ABCabc 1: ABC abcABC 0: abcABC 1: abc /a{0}bc/ bc 0: bc /^([^a])([^b])([^c]*)([^d]{3,4})/ baNOTccccd 0: baNOTcccc 1: b 2: a 3: NOT 4: cccc baNOTcccd 0: baNOTccc 1: b 2: a 3: NOT 4: ccc baNOTccd 0: baNOTcc 1: b 2: a 3: NO 4: Tcc bacccd 0: baccc 1: b 2: a 3: 4: ccc *** Failers 0: *** Failers 1: * 2: * 3: * Fail 4: ers anything No match baccd No match /[^a]/ Abc 0: A /[^a]/i Abc 0: b /[^a]+/ AAAaAbc 0: AAA /[^a]+/i AAAaAbc 0: bc /[^k]$/ abc 0: c *** Failers 0: s abk No match /[^k]{2,3}$/ abc 0: abc kbc 0: bc kabc 0: abc *** Failers 0: ers abk No match akb No match akk No match /^[0-9]{8,}@.+[^k]$/ 12345678@a.b.c.d 0: 12345678@a.b.c.d 123456789@x.y.z 0: 123456789@x.y.z *** Failers No match 12345678@x.y.uk No match 1234567@a.b.c.d No match /(a)\1{8,}/ aaaaaaaaa 0: aaaaaaaaa 1: a aaaaaaaaaa 0: aaaaaaaaaa 1: a *** Failers No match aaaaaaa No match /[^a]/ aaaabcd 0: b aaAabcd 0: A /[^a]/i aaaabcd 0: b aaAabcd 0: b /[^az]/ aaaabcd 0: b aaAabcd 0: A /[^az]/i aaaabcd 0: b aaAabcd 0: b /P[^*]TAIRE[^*]{1,6}LL/ xxxxxxxxxxxPSTAIREISLLxxxxxxxxx 0: PSTAIREISLL /P[^*]TAIRE[^*]{1,}LL/ xxxxxxxxxxxPSTAIREISLLxxxxxxxxx 0: PSTAIREISLL /(\.[0-9][0-9][1-9]?)[0-9]+/ 1.230003938 0: .230003938 1: .23 1.875000282 0: .875000282 1: .875 1.235 0: .235 1: .23 /\b(foo)\s+(\w+)/i Food is on the foo table 0: foo table 1: foo 2: table /foo(.*)bar/ The food is under the bar in the barn. 0: food is under the bar in the bar 1: d is under the bar in the /(.*)([0-9]*)/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 1: I have 2 numbers: 53147 2: /(.*)([0-9]+)/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 1: I have 2 numbers: 5314 2: 7 /(.*)([0-9]+)$/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 1: I have 2 numbers: 5314 2: 7 /(.*)\b([0-9]+)$/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 1: I have 2 numbers: 2: 53147 /(.*[^0-9])([0-9]+)$/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 1: I have 2 numbers: 2: 53147 /[[:digit:]][[:digit:]]\/[[:digit:]][[:digit:]]\/[[:digit:]][[:digit:]][[:digit:]][[:digit:]]/ 01/01/2000 0: 01/01/2000 /^(a){0,0}/ bcd 0: abc 0: aab 0: /^(a){0,1}/ bcd 0: abc 0: a 1: a aab 0: a 1: a /^(a){0,2}/ bcd 0: abc 0: a 1: a aab 0: aa 1: a /^(a){0,3}/ bcd 0: abc 0: a 1: a aab 0: aa 1: a aaa 0: aaa 1: a /^(a){0,}/ bcd 0: abc 0: a 1: a aab 0: aa 1: a aaa 0: aaa 1: a aaaaaaaa 0: aaaaaaaa 1: a /^(a){1,1}/ bcd No match abc 0: a 1: a aab 0: a 1: a /^(a){1,2}/ bcd No match abc 0: a 1: a aab 0: aa 1: a /^(a){1,3}/ bcd No match abc 0: a 1: a aab 0: aa 1: a aaa 0: aaa 1: a /^(a){1,}/ bcd No match abc 0: a 1: a aab 0: aa 1: a aaa 0: aaa 1: a aaaaaaaa 0: aaaaaaaa 1: a /^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/ 123456654321 0: 123456654321 /^[[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]]/ 123456654321 0: 123456654321 /^[abc]{12}/ abcabcabcabc 0: abcabcabcabc /^[a-c]{12}/ abcabcabcabc 0: abcabcabcabc /^(a|b|c){12}/ abcabcabcabc 0: abcabcabcabc 1: c /^[abcdefghijklmnopqrstuvwxy0123456789]/ n 0: n *** Failers No match z No match /abcde{0,0}/ abcd 0: abcd *** Failers No match abce No match /ab[cd]{0,0}e/ abe 0: abe *** Failers No match abcde No match /ab(c){0,0}d/ abd 0: abd *** Failers No match abcd No match /a(b*)/ a 0: a 1: ab 0: ab 1: b abbbb 0: abbbb 1: bbbb *** Failers 0: a 1: bbbbb No match /ab[0-9]{0}e/ abe 0: abe *** Failers No match ab1e No match /(A|B)*CD/ CD 0: CD /(AB)*\1/ ABABAB 0: ABABAB 1: AB /([0-9]+)(\w)/ 12345a 0: 12345a 1: 12345 2: a 12345+ 0: 12345 1: 1234 2: 5 /(abc|)+/ abc 0: abc 1: abc abcabc 0: abcabc 1: abc abcabcabc 0: abcabcabc 1: abc xyz 0: 1: /([a]*)*/ a 0: a 1: a aaaaa 0: aaaaa 1: aaaaa /([ab]*)*/ a 0: a 1: a b 0: b 1: b ababab 0: ababab 1: ababab aaaabcde 0: aaaab 1: aaaab bbbb 0: bbbb 1: bbbb /([^a]*)*/ b 0: b 1: b bbbb 0: bbbb 1: bbbb aaa 0: /([^ab]*)*/ cccc 0: cccc 1: cccc abab 0: /abc/ abc 0: abc xabcy 0: abc ababc 0: abc *** Failers No match xbc No match axc No match abx No match /ab*c/ abc 0: abc /ab*bc/ abc 0: abc abbc 0: abbc abbbbc 0: abbbbc /.{1}/ abbbbc 0: a /.{3,4}/ abbbbc 0: abbb /ab{0,}bc/ abbbbc 0: abbbbc /ab+bc/ abbc 0: abbc *** Failers No match abc No match abq No match /ab+bc/ abbbbc 0: abbbbc /ab{1,}bc/ abbbbc 0: abbbbc /ab{1,3}bc/ abbbbc 0: abbbbc /ab{3,4}bc/ abbbbc 0: abbbbc /ab{4,5}bc/ *** Failers No match abq No match abbbbc No match /ab?bc/ abbc 0: abbc abc 0: abc /ab{0,1}bc/ abc 0: abc /ab?c/ abc 0: abc /ab{0,1}c/ abc 0: abc /^abc$/ abc 0: abc *** Failers No match abbbbc No match abcc No match /^abc/ abcc 0: abc /abc$/ aabc 0: abc *** Failers No match aabc 0: abc aabcd No match /^/ abc 0: /$/ abc 0: /a.c/ abc 0: abc axc 0: axc /a.*c/ axyzc 0: axyzc /a[bc]d/ abd 0: abd *** Failers No match axyzd No match abc No match /a[b-d]e/ ace 0: ace /a[b-d]/ aac 0: ac /a[-b]/ a- 0: a- /a[b-]/ a- 0: a- /a[]]b/ a]b 0: a]b /a[^bc]d/ aed 0: aed *** Failers No match abd No match abd No match /a[^-b]c/ adc 0: adc /a[^]b]c/ adc 0: adc *** Failers No match a-c 0: a-c a]c No match /\ba\b/ a- 0: a -a 0: a -a- 0: a /\by\b/ *** Failers No match xy No match yz No match xyz No match /\Ba\B/ *** Failers 0: a a- No match -a No match -a- No match /\By\b/ xy 0: y /\by\B/ yz 0: y /\By\B/ xyz 0: y /\w/ a 0: a /\W/ - 0: - *** Failers 0: * - 0: - a No match /a\sb/ a b 0: a b /a\Sb/ a-b 0: a-b *** Failers No match a-b 0: a-b a b No match /[0-9]/ 1 0: 1 /[^0-9]/ - 0: - *** Failers 0: * - 0: - 1 No match /ab|cd/ abc 0: ab abcd 0: ab /()ef/ def 0: ef 1: /a\(b/ a(b 0: a(b /a\(*b/ ab 0: ab a((b 0: a((b /((a))/ abc 0: a 1: a 2: a /(a)b(c)/ abc 0: abc 1: a 2: c /a+b+c/ aabbabc 0: abc /a{1,}b{1,}c/ aabbabc 0: abc /(a+|b)*/ ab 0: ab 1: b /(a+|b){0,}/ ab 0: ab 1: b /(a+|b)+/ ab 0: ab 1: b /(a+|b){1,}/ ab 0: ab 1: b /(a+|b)?/ ab 0: a 1: a /(a+|b){0,1}/ ab 0: a 1: a /[^ab]*/ cde 0: cde /abc/ *** Failers No match b No match /a*/ /([abc])*d/ abbbcd 0: abbbcd 1: c /([abc])*bcd/ abcd 0: abcd 1: a /a|b|c|d|e/ e 0: e /(a|b|c|d|e)f/ ef 0: ef 1: e /abcd*efg/ abcdefg 0: abcdefg /ab*/ xabyabbbz 0: ab xayabbbz 0: a /(ab|cd)e/ abcde 0: cde 1: cd /[abhgefdc]ij/ hij 0: hij /(abc|)ef/ abcdef 0: ef 1: /(a|b)c*d/ abcd 0: bcd 1: b /(ab|ab*)bc/ abc 0: abc 1: a /a([bc]*)c*/ abc 0: abc 1: bc /a([bc]*)(c*d)/ abcd 0: abcd 1: bc 2: d /a([bc]+)(c*d)/ abcd 0: abcd 1: bc 2: d /a([bc]*)(c+d)/ abcd 0: abcd 1: b 2: cd /a[bcd]*dcdcde/ adcdcde 0: adcdcde /a[bcd]+dcdcde/ *** Failers No match abcde No match adcdcde No match /(ab|a)b*c/ abc 0: abc 1: ab /((a)(b)c)(d)/ abcd 0: abcd 1: abc 2: a 3: b 4: d /[a-zA-Z_][a-zA-Z0-9_]*/ alpha 0: alpha /^a(bc+|b[eh])g|.h$/ abh 0: bh /(bc+d$|ef*g.|h?i(j|k))/ effgz 0: effgz 1: effgz ij 0: ij 1: ij 2: j reffgz 0: effgz 1: effgz *** Failers No match effg No match bcdd No match /((((((((((a))))))))))/ a 0: a 1: a 2: a 3: a 4: a 5: a 6: a 7: a 8: a 9: a 10: a /((((((((((a))))))))))\9/ aa 0: aa 1: a 2: a 3: a 4: a 5: a 6: a 7: a 8: a 9: a 10: a /(((((((((a)))))))))/ a 0: a 1: a 2: a 3: a 4: a 5: a 6: a 7: a 8: a 9: a /multiple words of text/ *** Failers No match aa No match uh-uh No match /multiple words/ multiple words, yeah 0: multiple words /(.*)c(.*)/ abcde 0: abcde 1: ab 2: de /\((.*), (.*)\)/ (a, b) 0: (a, b) 1: a 2: b /abcd/ abcd 0: abcd /a(bc)d/ abcd 0: abcd 1: bc /a[-]?c/ ac 0: ac /(abc)\1/ abcabc 0: abcabc 1: abc /([a-c]*)\1/ abcabc 0: abcabc 1: abc /(a)|\1/ a 0: a 1: a *** Failers 0: a 1: a ab 0: a 1: a x No match /abc/i ABC 0: ABC XABCY 0: ABC ABABC 0: ABC *** Failers No match aaxabxbaxbbx No match XBC No match AXC No match ABX No match /ab*c/i ABC 0: ABC /ab*bc/i ABC 0: ABC ABBC 0: ABBC /ab+bc/i *** Failers No match ABC No match ABQ No match /ab+bc/i ABBBBC 0: ABBBBC /^abc$/i ABC 0: ABC *** Failers No match ABBBBC No match ABCC No match /^abc/i ABCC 0: ABC /abc$/i AABC 0: ABC /^/i ABC 0: /$/i ABC 0: /a.c/i ABC 0: ABC AXC 0: AXC /a.*c/i *** Failers No match AABC 0: AABC AXYZD No match /a[bc]d/i ABD 0: ABD /a[b-d]e/i ACE 0: ACE *** Failers No match ABC No match ABD No match /a[b-d]/i AAC 0: AC /a[-b]/i A- 0: A- /a[b-]/i A- 0: A- /a[]]b/i A]B 0: A]B /a[^bc]d/i AED 0: AED /a[^-b]c/i ADC 0: ADC *** Failers No match ABD No match A-C No match /a[^]b]c/i ADC 0: ADC /ab|cd/i ABC 0: AB ABCD 0: AB /()ef/i DEF 0: EF 1: /$b/i *** Failers No match A]C No match B No match /a\(b/i A(B 0: A(B /a\(*b/i AB 0: AB A((B 0: A((B /((a))/i ABC 0: A 1: A 2: A /(a)b(c)/i ABC 0: ABC 1: A 2: C /a+b+c/i AABBABC 0: ABC /a{1,}b{1,}c/i AABBABC 0: ABC /(a+|b)*/i AB 0: AB 1: B /(a+|b){0,}/i AB 0: AB 1: B /(a+|b)+/i AB 0: AB 1: B /(a+|b){1,}/i AB 0: AB 1: B /(a+|b)?/i AB 0: A 1: A /(a+|b){0,1}/i AB 0: A 1: A /[^ab]*/i CDE 0: CDE /([abc])*d/i ABBBCD 0: ABBBCD 1: C /([abc])*bcd/i ABCD 0: ABCD 1: A /a|b|c|d|e/i E 0: E /(a|b|c|d|e)f/i EF 0: EF 1: E /abcd*efg/i ABCDEFG 0: ABCDEFG /ab*/i XABYABBBZ 0: AB XAYABBBZ 0: A /(ab|cd)e/i ABCDE 0: CDE 1: CD /[abhgefdc]ij/i HIJ 0: HIJ /^(ab|cd)e/i ABCDE No match /(abc|)ef/i ABCDEF 0: EF 1: /(a|b)c*d/i ABCD 0: BCD 1: B /(ab|ab*)bc/i ABC 0: ABC 1: A /a([bc]*)c*/i ABC 0: ABC 1: BC /a([bc]*)(c*d)/i ABCD 0: ABCD 1: BC 2: D /a([bc]+)(c*d)/i ABCD 0: ABCD 1: BC 2: D /a([bc]*)(c+d)/i ABCD 0: ABCD 1: B 2: CD /a[bcd]*dcdcde/i ADCDCDE 0: ADCDCDE /a[bcd]+dcdcde/i /(ab|a)b*c/i ABC 0: ABC 1: AB /((a)(b)c)(d)/i ABCD 0: ABCD 1: ABC 2: A 3: B 4: D /[a-zA-Z_][a-zA-Z0-9_]*/i ALPHA 0: ALPHA /^a(bc+|b[eh])g|.h$/i ABH 0: BH /(bc+d$|ef*g.|h?i(j|k))/i EFFGZ 0: EFFGZ 1: EFFGZ IJ 0: IJ 1: IJ 2: J REFFGZ 0: EFFGZ 1: EFFGZ *** Failers No match ADCDCDE No match EFFG No match BCDD No match /((((((((((a))))))))))/i A 0: A 1: A 2: A 3: A 4: A 5: A 6: A 7: A 8: A 9: A 10: A /((((((((((a))))))))))\9/i AA 0: AA 1: A 2: A 3: A 4: A 5: A 6: A 7: A 8: A 9: A 10: A /(((((((((a)))))))))/i A 0: A 1: A 2: A 3: A 4: A 5: A 6: A 7: A 8: A 9: A /multiple words of text/i *** Failers No match AA No match UH-UH No match /multiple words/i MULTIPLE WORDS, YEAH 0: MULTIPLE WORDS /(.*)c(.*)/i ABCDE 0: ABCDE 1: AB 2: DE /\((.*), (.*)\)/i (A, B) 0: (A, B) 1: A 2: B /abcd/i ABCD 0: ABCD /a(bc)d/i ABCD 0: ABCD 1: BC /a[-]?c/i AC 0: AC /(abc)\1/i ABCABC 0: ABCABC 1: ABC /([a-c]*)\1/i ABCABC 0: ABCABC 1: ABC /((foo)|(bar))*/ foobar 0: foobar 1: bar 2: foo 3: bar /^(.+)?B/ AB 0: AB 1: A /^([^a-z])|(\^)$/ . 0: . 1: . /^[<>]&/ <&OUT 0: <& /^(){3,5}/ abc 0: 1: /^(a+)*ax/ aax 0: aax 1: a /^((a|b)+)*ax/ aax 0: aax 1: a 2: a /^((a|bc)+)*ax/ aax 0: aax 1: a 2: a /(a|x)*ab/ cab 0: ab /(a)*ab/ cab 0: ab /(ab)[0-9]\1/i Ab4ab 0: Ab4ab 1: Ab ab4Ab 0: ab4Ab 1: ab /foo\w*[0-9]{4}baz/ foobar1234baz 0: foobar1234baz /(\w+:)+/ one: 0: one: 1: one: /((\w|:)+::)?(\w+)$/ abcd 0: abcd 1: 2: 3: abcd xy:z:::abcd 0: xy:z:::abcd 1: xy:z::: 2: : 3: abcd /^[^bcd]*(c+)/ aexycd 0: aexyc 1: c /(a*)b+/ caab 0: aab 1: aa /((\w|:)+::)?(\w+)$/ abcd 0: abcd 1: 2: 3: abcd xy:z:::abcd 0: xy:z:::abcd 1: xy:z::: 2: : 3: abcd *** Failers 0: Failers 1: 2: 3: Failers abcd: No match abcd: No match /^[^bcd]*(c+)/ aexycd 0: aexyc 1: c /((Z)+|A)*/ ZABCDEFG 0: ZA 1: A 2: Z /(Z()|A)*/ ZABCDEFG 0: ZA 1: A 2: /(Z(())|A)*/ ZABCDEFG 0: ZA 1: A 2: 3: /(.*)[0-9]+\1/ abc123abc 0: abc123abc 1: abc abc123bc 0: bc123bc 1: bc /((.*))[0-9]+\1/ abc123abc 0: abc123abc 1: abc 2: abc abc123bc 0: bc123bc 1: bc 2: bc /^a{2,5}$/ aa 0: aa aaa 0: aaa aaaa 0: aaaa aaaaa 0: aaaaa *** Failers No match a No match b No match aaaaab No match aaaaaa kbuild-3686/src/oldsed/testsuite/classes.inp0000664000175000017500000000022515053010105021140 0ustar locutuslocutus_cv_=emptyvar ac_cv_prog/RANLIB=/usr/bin/ranlib ac_cv_prog/CC=/usr/unsupported/\ \ /lib/_cv_/cc a/c_cv_prog/CPP=/usr/bin/cpp SHELL=bash GNU=GNU!UNIX kbuild-3686/src/oldsed/basicdefs.h0000664000175000017500000001420715053010105017043 0ustar locutuslocutus/* GNU SED, a batch stream editor. Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc. 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, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef BASICDEFS_H #define BASICDEFS_H #if defined(_AIX) #pragma alloca #else # if !defined(alloca) /* predefined by HP cc +Olibcalls */ # ifdef __GNUC__ # define alloca(size) __builtin_alloca(size) # else # if HAVE_ALLOCA_H # include # else # if defined(__hpux) void *alloca (); # else # if !defined(__OS2__) && !defined(WIN32) char *alloca (); # else # include /* OS/2 defines alloca in here */ # endif # endif # endif # endif # endif #endif #ifdef HAVE_WCHAR_H # include #endif #ifdef HAVE_LOCALE_H # include #endif #ifdef HAVE_WCTYPE_H # include #endif #ifdef BOOTSTRAP # define false 0 # define true 1 # define bool unsigned # define __bool_true_false_are_defined 1 #else # if HAVE_STDBOOL_H || defined(__HAIKU__) /* haiku/gcc2 hack */ # include # endif #endif #if ENABLE_NLS # include #else # define gettext(msgid) (msgid) # define ngettext(sing, plur, n) ((n) == 1 ? (sing) : (plur)) #endif #define _(String) gettext(String) #ifdef gettext_noop # define N_(String) gettext_noop(String) #else # define N_(String) (String) #endif /* type countT is used to keep track of line numbers, etc. */ typedef unsigned long countT; /* Oftentimes casts are used as an ugly hack to silence warnings * from the compiler. However, sometimes those warnings really * do point to something worth avoiding. I define this * dummy marker to make searching for them with a text editor * much easier, in case I want to verify that they are all * legitimate. It is defined in the way it is so that it is * easy to disable all casts so that the compiler (or lint) * can tell me potentially interesting things about what would * happen to the code without the explicit casts. */ #ifdef LOUD_LINT # define CAST(x) #else # define CAST(x) (x) #endif /* Can the compiler grok function prototypes? */ #if (defined __STDC__ && __STDC__-0) || defined __GNUC__ || defined __SUNPRO_C || __PROTOTYPES # define P_(s) s #else # define P_(s) () #endif /* (VOID *) is the generic pointer type; some ancient compilers don't know about (void *), and typically use (char *) instead. VCAST() is used to cast to and from (VOID *)s --- but if the compiler *does* support (void *) make this a no-op, so that the compiler can detect if we omitted an essential function declaration somewhere. */ #ifndef VOID # define VOID void # define VCAST(t) #else # define VCAST(t) (t) #endif /* some basic definitions to avoid undue promulgating of VCAST ugliness */ #define MALLOC(n,t) (VCAST(t *)ck_malloc((n)*sizeof(t))) #define REALLOC(x,n,t) (VCAST(t *)ck_realloc(VCAST(VOID *)(x),(n)*sizeof(t))) #define MEMDUP(x,n,t) (VCAST(t *)ck_memdup(VCAST(VOID *)(x),(n)*sizeof(t))) #define FREE(x) (ck_free(VCAST(VOID *)x)) #define MEMCPY(d,s,l) (memcpy(VCAST(VOID *)(d),VCAST(const VOID *)(s),l)) #define MEMMOVE(d,s,l) (memmove(VCAST(VOID *)(d),VCAST(const VOID *)(s),l)) #define OB_MALLOC(o,n,t) (VCAST(t *)obstack_alloc(o,(n)*sizeof(t))) #define obstack_chunk_alloc ck_malloc #define obstack_chunk_free ck_free #ifdef HAVE_MEMORY_H # include #endif #ifndef HAVE_MEMMOVE # ifndef memmove /* ../lib/libsed.a provides a memmove() if the system doesn't. Here is where we declare its return type; we don't prototype it because that sometimes causes problems when we're running in bootstrap mode on a system which really does support memmove(). */ extern VOID *memmove(); # endif #endif #ifndef HAVE_MEMCPY # ifndef memcpy # define memcpy(d, s, n) memmove(d, s, n) # endif #endif #ifndef HAVE_STRERROR extern char *strerror P_((int e)); #endif /* handle misdesigned macros (snarfed from lib/regex.c) */ /* Jim Meyering writes: "... Some ctype macros are valid only for character codes that isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when using /bin/cc or gcc but without giving an ansi option). So, all ctype uses should be through macros like ISPRINT... If STDC_HEADERS is defined, then autoconf has verified that the ctype macros don't need to be guarded with references to isascii. ... Defining isascii to 1 should let any compiler worth its salt eliminate the && through constant folding." Solaris defines some of these symbols so we must undefine them first. */ #undef ISASCII #if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) # define ISASCII(c) 1 #else # define ISASCII(c) isascii(c) #endif #if defined isblank || defined HAVE_ISBLANK # define ISBLANK(c) (ISASCII (c) && isblank (c)) #else # define ISBLANK(c) ((c) == ' ' || (c) == '\t') #endif #undef ISPRINT #define ISPRINT(c) (ISASCII (c) && isprint (c)) #define ISDIGIT(c) (ISASCII (c) && isdigit (c)) #define ISALNUM(c) (ISASCII (c) && isalnum (c)) #define ISALPHA(c) (ISASCII (c) && isalpha (c)) #define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) #define ISLOWER(c) (ISASCII (c) && islower (c)) #define ISPUNCT(c) (ISASCII (c) && ispunct (c)) #define ISSPACE(c) (ISASCII (c) && isspace (c)) #define ISUPPER(c) (ISASCII (c) && isupper (c)) #define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) #ifndef initialize_main # ifdef __EMX__ # define initialize_main(argcp, argvp) \ { _response(argcp, argvp); _wildcard(argcp, argvp); } # else /* NOT __EMX__ */ # define initialize_main(argcp, argvp) # endif #endif #endif /*!BASICDEFS_H*/ kbuild-3686/src/oldsed/config.h.haiku0000664000175000017500000003205215053010104017462 0ustar locutuslocutus/* config.h. Generated from config_h.in by configure. */ /* config_h.in. Generated from configure.ac by autoheader. */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if translation of program messages to the user's native language is requested. */ /* #undef ENABLE_NLS */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ #define HAVE_ALLOCA_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_ARGZ_H */ /* Define to 1 if you have the `asprintf' function. */ #define HAVE_ASPRINTF 1 /* Define to 1 if you have the `bcopy' function. */ #define HAVE_BCOPY 1 /* Define to 1 if you have the `btowc' function. */ #define HAVE_BTOWC 1 /* Define to 1 if you have the `bzero' function. */ #define HAVE_BZERO 1 /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* #undef HAVE_DCGETTEXT */ /* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you don't. */ #define HAVE_DECL_FEOF_UNLOCKED 1 /* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if you don't. */ #define HAVE_DECL_FGETS_UNLOCKED 0 /* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you don't. */ #define HAVE_DECL_GETC_UNLOCKED 1 /* Define to 1 if you have the declaration of `_snprintf', and to 0 if you don't. */ #define HAVE_DECL__SNPRINTF 0 /* Define to 1 if you have the declaration of `_snwprintf', and to 0 if you don't. */ #define HAVE_DECL__SNWPRINTF 0 /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ /* #undef HAVE_DOPRNT */ /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H 1 /* Define to 1 if you have the `fchmod' function. */ #define HAVE_FCHMOD 1 /* Define to 1 if you have the `fchown' function. */ #define HAVE_FCHOWN 1 /* Define to 1 if you have the `fwprintf' function. */ #define HAVE_FWPRINTF 1 /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getegid' function. */ #define HAVE_GETEGID 1 /* Define to 1 if you have the `geteuid' function. */ #define HAVE_GETEUID 1 /* Define to 1 if you have the `getgid' function. */ #define HAVE_GETGID 1 /* Define to 1 if you have the `getpagesize' function. */ #define HAVE_GETPAGESIZE 1 /* Define if the GNU gettext() function is already present or preinstalled. */ /* #undef HAVE_GETTEXT */ /* Define to 1 if you have the `getuid' function. */ #define HAVE_GETUID 1 /* Define if you have the iconv() function. */ #define HAVE_ICONV 1 /* Define if you have the 'intmax_t' type in or . */ #define HAVE_INTMAX_T 1 /* Define if exists and doesn't clash with . */ #define HAVE_INTTYPES_H 1 /* Define if exists, doesn't clash with , and declares uintmax_t. */ #define HAVE_INTTYPES_H_WITH_UINTMAX 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_IO_H */ /* Define to 1 if you have the `isascii' function. */ #define HAVE_ISASCII 1 /* Define to 1 if you have the `isatty' function. */ #define HAVE_ISATTY 1 /* Define to 1 if you have the `isblank' function. */ #define HAVE_ISBLANK 1 /* Define if you have and nl_langinfo(CODESET). */ #define HAVE_LANGINFO_CODESET 1 /* Define if your file defines LC_MESSAGES. */ #define HAVE_LC_MESSAGES 1 /* Define to 1 if you have the `regex' library (-lregex). */ /* #undef HAVE_LIBREGEX */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define if you have the 'long double' type. */ #define HAVE_LONG_DOUBLE 1 /* Define to 1 if you support file names longer than 14 characters. */ #define HAVE_LONG_FILE_NAMES 1 /* Define if you have the 'long long' type. */ #define HAVE_LONG_LONG 1 /* Define to 1 if you have the header file. */ #define HAVE_MALLOC_H 1 /* Define to 1 if mbrtowc and mbstate_t are properly declared. */ #define HAVE_MBRTOWC 1 /* Define to 1 if declares mbstate_t. */ #define HAVE_MBSTATE_T 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MCHECK_H */ /* Define to 1 if you have the `memchr' function. */ #define HAVE_MEMCHR 1 /* Define to 1 if you have the `memcmp' function. */ #define HAVE_MEMCMP 1 /* Define to 1 if you have the `memcpy' function. */ #define HAVE_MEMCPY 1 /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mempcpy' function. */ /* #undef HAVE_MEMPCPY */ /* Define to 1 if you have the `memset' function. */ #define HAVE_MEMSET 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have a working `mmap' system call. */ #define HAVE_MMAP 1 /* Define to 1 if you have the `munmap' function. */ #define HAVE_MUNMAP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_NL_TYPES_H 1 /* Define to 1 if libc includes obstacks. */ /* #undef HAVE_OBSTACK */ /* Define to 1 if you have the `pathconf' function. */ #define HAVE_PATHCONF 1 /* Define to 1 if you have the `popen' function. */ #define HAVE_POPEN 1 /* Define if your printf() function supports format strings with positions. */ #define HAVE_POSIX_PRINTF 1 /* Define to 1 if you have the `putenv' function. */ #define HAVE_PUTENV 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_REGEX_H */ /* Define to 1 if you have the `setenv' function. */ #define HAVE_SETENV 1 /* Define to 1 if you have the `setlocale' function. */ #define HAVE_SETLOCALE 1 /* Define to 1 if you have the `snprintf' function. */ #define HAVE_SNPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if stdbool.h conforms to C99. */ /* #undef HAVE_STDBOOL_H */ /* Define to 1 if you have the header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define if exists, doesn't clash with , and declares uintmax_t. */ #define HAVE_STDINT_H_WITH_UINTMAX 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `stpcpy' function. */ #define HAVE_STPCPY 1 /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strtoul' function. */ #define HAVE_STRTOUL 1 /* Define to 1 if you have the `strverscmp' function. */ /* #undef HAVE_STRVERSCMP */ /* 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. */ #define HAVE_SYS_FILE_H 1 /* 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. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the `tsearch' function. */ #define HAVE_TSEARCH 1 /* Define if you have the 'uintmax_t' type in or . */ #define HAVE_UINTMAX_T 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define if you have the 'unsigned long long' type. */ #define HAVE_UNSIGNED_LONG_LONG 1 /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_WCHAR_H 1 /* Define if you have the 'wchar_t' type. */ #define HAVE_WCHAR_T 1 /* Define to 1 if you have the `wcrtomb' function. */ #define HAVE_WCRTOMB 1 /* Define to 1 if you have the `wcscoll' function. */ #define HAVE_WCSCOLL 1 /* Define to 1 if you have the `wcslen' function. */ #define HAVE_WCSLEN 1 /* Define to 1 if you have the header file. */ #define HAVE_WCTYPE_H 1 /* Define if you have the 'wint_t' type. */ #define HAVE_WINT_T 1 /* Define to 1 if the system has the type `_Bool'. */ /* #undef HAVE__BOOL */ /* Define to 1 if you have the `__argz_count' function. */ /* #undef HAVE___ARGZ_COUNT */ /* Define to 1 if you have the `__argz_next' function. */ /* #undef HAVE___ARGZ_NEXT */ /* Define to 1 if you have the `__argz_stringify' function. */ /* #undef HAVE___ARGZ_STRINGIFY */ /* Define to 1 if you have the `__fsetlocking' function. */ #define HAVE___FSETLOCKING 1 /* Define as const if the declaration of iconv() needs const. */ #define ICONV_CONST /* Define if integer division by zero raises signal SIGFPE. */ #define INTDIV0_RAISES_SIGFPE 1 /* Name of package */ #define PACKAGE "sed" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bonzini@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "sed" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "sed 4.1.5" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "sed" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "4.1.5" /* Define if exists and defines unusable PRI* macros. */ /* #undef PRI_MACROS_BROKEN */ /* Define to the version of GNU sed whose features are supported by this sed. */ #define SED_FEATURE_VERSION "4.1" /* Define as the maximum value of type 'size_t', if the system doesn't define it. */ /* #undef SIZE_MAX */ /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # define _ALL_SOURCE 1 #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # define _POSIX_PTHREAD_SEMANTICS 1 #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # define _TANDEM_SOURCE 1 #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # define __EXTENSIONS__ 1 #endif /* Version number of package */ #define VERSION "4.1.5" /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Include BSD functions in regex, used by the testsuite */ #define _REGEX_RE_COMP 1 /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to a type if does not define. */ /* #undef mbstate_t */ /* Define to `long int' if does not define. */ /* #undef off_t */ /* Define as the type of the result of subtracting two pointers, if the system doesn't define it. */ /* #undef ptrdiff_t */ /* Define to empty if the C compiler doesn't support this keyword. */ /* #undef signed */ /* Define to `unsigned int' if does not define. */ /* #undef size_t */ /* Define to `int' if does not define. */ /* #undef ssize_t */ /* Define to unsigned long or unsigned long long if and don't define. */ /* #undef uintmax_t */ kbuild-3686/src/oldsed/bootstrap.sh0000775000175000017500000000524315053010105017323 0ustar locutuslocutus#! /bin/sh # edit this to taste; note that you can also override via the environment: case "$CC" in "") CC=cc esac if test -f config.h; then :; else echo "Creating basic config.h..." cat >config.h <<'END_OF_CONFIG_H' /* A bootstrap version of config.h, for systems which can't auto-configure due to a lack of a working sed. If you are on a sufficiently odd machine you may need to hand-tweak this file. Regardless, once you get a working version of sed you really should re-build starting with a run of "configure", as the bootstrap version is almost certainly more crippled than it needs to be on your machine. */ #define PACKAGE "sed" #define VERSION "4.1.5-boot" #define SED_FEATURE_VERSION "4.1" #define BOOTSTRAP 1 /* Define if your compiler/headers don't support const. */ #undef const /* Undefine if headers have conflicting definition. */ #define mbstate_t int /* Toggle if you encounter errors in lib/mkstemp.c. */ #define HAVE_UNISTD_H #define HAVE_FCNTL_H #undef HAVE_SYS_FILE_H #undef HAVE_IO_H /* Undefine if or has conflicting definition. */ #define size_t unsigned #define ssize_t int /* If your antique compiler doesn't grok ``void *'', then #define VOID char */ #undef VOID /* All other config.h.in options intentionally omitted. Report as a bug if you need extra "#define"s in here. */ END_OF_CONFIG_H fi # tell the user what we're doing from here on... set -x -e # the ``|| exit 1''s are for fail-stop; set -e doesn't work on some systems rm -f lib/*.o sed/*.o sed/sed cd lib || exit 1 rm -f regex.h cp regex_.h regex.h ${CC} -DHAVE_CONFIG_H -I.. -I. -c alloca.c ${CC} -DHAVE_CONFIG_H -I.. -I. -c getline.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c getopt.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c getopt1.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c memchr.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c memcmp.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c memmove.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c mkstemp.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c strverscmp.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c obstack.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c regex.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c strerror.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -c utils.c || exit 1 cd ../sed || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c sed.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c fmt.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c compile.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c execute.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c mbcs.c || exit 1 ${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c regexp.c || exit 1 ${CC} -o sed *.o ../lib/*.o || exit 1 kbuild-3686/src/oldsed/config.h.netbsd0000775000175000017500000003206215053010105017645 0ustar locutuslocutus/* config.h. Generated from config_h.in by configure. */ /* config_h.in. Generated from configure.ac by autoheader. */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if translation of program messages to the user's native language is requested. */ /* #undef ENABLE_NLS */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ /* #undef HAVE_ALLOCA_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_ARGZ_H */ /* Define to 1 if you have the `asprintf' function. */ #define HAVE_ASPRINTF 1 /* Define to 1 if you have the `bcopy' function. */ #define HAVE_BCOPY 1 /* Define to 1 if you have the `btowc' function. */ #define HAVE_BTOWC 1 /* Define to 1 if you have the `bzero' function. */ #define HAVE_BZERO 1 /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* #undef HAVE_DCGETTEXT */ /* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you don't. */ #define HAVE_DECL_FEOF_UNLOCKED 0 /* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if you don't. */ #define HAVE_DECL_FGETS_UNLOCKED 0 /* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you don't. */ #define HAVE_DECL_GETC_UNLOCKED 1 /* Define to 1 if you have the declaration of `_snprintf', and to 0 if you don't. */ #define HAVE_DECL__SNPRINTF 0 /* Define to 1 if you have the declaration of `_snwprintf', and to 0 if you don't. */ #define HAVE_DECL__SNWPRINTF 0 /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ /* #undef HAVE_DOPRNT */ /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H 1 /* Define to 1 if you have the `fchmod' function. */ #define HAVE_FCHMOD 1 /* Define to 1 if you have the `fchown' function. */ #define HAVE_FCHOWN 1 /* Define to 1 if you have the `fwprintf' function. */ #define HAVE_FWPRINTF 1 /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getegid' function. */ #define HAVE_GETEGID 1 /* Define to 1 if you have the `geteuid' function. */ #define HAVE_GETEUID 1 /* Define to 1 if you have the `getgid' function. */ #define HAVE_GETGID 1 /* Define to 1 if you have the `getpagesize' function. */ #define HAVE_GETPAGESIZE 1 /* Define if the GNU gettext() function is already present or preinstalled. */ /* #undef HAVE_GETTEXT */ /* Define to 1 if you have the `getuid' function. */ #define HAVE_GETUID 1 /* Define if you have the iconv() function. */ #define HAVE_ICONV 1 /* Define if you have the 'intmax_t' type in or . */ #define HAVE_INTMAX_T 1 /* Define if exists and doesn't clash with . */ #define HAVE_INTTYPES_H 1 /* Define if exists, doesn't clash with , and declares uintmax_t. */ #define HAVE_INTTYPES_H_WITH_UINTMAX 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_IO_H */ /* Define to 1 if you have the `isascii' function. */ #define HAVE_ISASCII 1 /* Define to 1 if you have the `isatty' function. */ #define HAVE_ISATTY 1 /* Define to 1 if you have the `isblank' function. */ #define HAVE_ISBLANK 1 /* Define if you have and nl_langinfo(CODESET). */ #define HAVE_LANGINFO_CODESET 1 /* Define if your file defines LC_MESSAGES. */ #define HAVE_LC_MESSAGES 1 /* Define to 1 if you have the `regex' library (-lregex). */ /* #undef HAVE_LIBREGEX */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define if you have the 'long double' type. */ #define HAVE_LONG_DOUBLE 1 /* Define to 1 if you support file names longer than 14 characters. */ #define HAVE_LONG_FILE_NAMES 1 /* Define if you have the 'long long' type. */ #define HAVE_LONG_LONG 1 /* Define to 1 if you have the header file. */ #define HAVE_MALLOC_H 1 /* Define to 1 if mbrtowc and mbstate_t are properly declared. */ #define HAVE_MBRTOWC 1 /* Define to 1 if declares mbstate_t. */ #define HAVE_MBSTATE_T 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MCHECK_H */ /* Define to 1 if you have the `memchr' function. */ #define HAVE_MEMCHR 1 /* Define to 1 if you have the `memcmp' function. */ #define HAVE_MEMCMP 1 /* Define to 1 if you have the `memcpy' function. */ #define HAVE_MEMCPY 1 /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mempcpy' function. */ /* #undef HAVE_MEMPCPY */ /* Define to 1 if you have the `memset' function. */ #define HAVE_MEMSET 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have a working `mmap' system call. */ #define HAVE_MMAP 1 /* Define to 1 if you have the `munmap' function. */ #define HAVE_MUNMAP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_NL_TYPES_H 1 /* Define to 1 if libc includes obstacks. */ /* #undef HAVE_OBSTACK */ /* Define to 1 if you have the `pathconf' function. */ #define HAVE_PATHCONF 1 /* Define to 1 if you have the `popen' function. */ #define HAVE_POPEN 1 /* Define if your printf() function supports format strings with positions. */ #define HAVE_POSIX_PRINTF 1 /* Define to 1 if you have the `putenv' function. */ #define HAVE_PUTENV 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_REGEX_H */ /* Define to 1 if you have the `setenv' function. */ #define HAVE_SETENV 1 /* Define to 1 if you have the `setlocale' function. */ #define HAVE_SETLOCALE 1 /* Define to 1 if you have the `snprintf' function. */ #define HAVE_SNPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if stdbool.h conforms to C99. */ #define HAVE_STDBOOL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define if exists, doesn't clash with , and declares uintmax_t. */ #define HAVE_STDINT_H_WITH_UINTMAX 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `stpcpy' function. */ /* #undef HAVE_STPCPY */ /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strtoul' function. */ #define HAVE_STRTOUL 1 /* Define to 1 if you have the `strverscmp' function. */ /* #undef HAVE_STRVERSCMP */ /* 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. */ #define HAVE_SYS_FILE_H 1 /* 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. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the `tsearch' function. */ #define HAVE_TSEARCH 1 /* Define if you have the 'uintmax_t' type in or . */ #define HAVE_UINTMAX_T 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define if you have the 'unsigned long long' type. */ #define HAVE_UNSIGNED_LONG_LONG 1 /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_WCHAR_H 1 /* Define if you have the 'wchar_t' type. */ #define HAVE_WCHAR_T 1 /* Define to 1 if you have the `wcrtomb' function. */ #define HAVE_WCRTOMB 1 /* Define to 1 if you have the `wcscoll' function. */ #define HAVE_WCSCOLL 1 /* Define to 1 if you have the `wcslen' function. */ #define HAVE_WCSLEN 1 /* Define to 1 if you have the header file. */ #define HAVE_WCTYPE_H 1 /* Define if you have the 'wint_t' type. */ #define HAVE_WINT_T 1 /* Define to 1 if the system has the type `_Bool'. */ #define HAVE__BOOL 1 /* Define to 1 if you have the `__argz_count' function. */ /* #undef HAVE___ARGZ_COUNT */ /* Define to 1 if you have the `__argz_next' function. */ /* #undef HAVE___ARGZ_NEXT */ /* Define to 1 if you have the `__argz_stringify' function. */ /* #undef HAVE___ARGZ_STRINGIFY */ /* Define to 1 if you have the `__fsetlocking' function. */ /* #undef HAVE___FSETLOCKING */ /* Define as const if the declaration of iconv() needs const. */ #define ICONV_CONST const /* Define if integer division by zero raises signal SIGFPE. */ #define INTDIV0_RAISES_SIGFPE 1 /* Name of package */ #define PACKAGE "sed" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bonzini@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "sed" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "sed 4.1.5" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "sed" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "4.1.5" /* Define if exists and defines unusable PRI* macros. */ /* #undef PRI_MACROS_BROKEN */ /* Define to the version of GNU sed whose features are supported by this sed. */ #define SED_FEATURE_VERSION "4.1" /* Define as the maximum value of type 'size_t', if the system doesn't define it. */ /* #undef SIZE_MAX */ /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # define _ALL_SOURCE 1 #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # define _POSIX_PTHREAD_SEMANTICS 1 #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # define _TANDEM_SOURCE 1 #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # define __EXTENSIONS__ 1 #endif /* Version number of package */ #define VERSION "4.1.5" /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Include BSD functions in regex, used by the testsuite */ #define _REGEX_RE_COMP 1 /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to a type if does not define. */ /* #undef mbstate_t */ /* Define to `long int' if does not define. */ /* #undef off_t */ /* Define as the type of the result of subtracting two pointers, if the system doesn't define it. */ /* #undef ptrdiff_t */ /* Define to empty if the C compiler doesn't support this keyword. */ /* #undef signed */ /* Define to `unsigned int' if does not define. */ /* #undef size_t */ /* Define to `int' if does not define. */ /* #undef ssize_t */ /* Define to unsigned long or unsigned long long if and don't define. */ /* #undef uintmax_t */ kbuild-3686/src/oldsed/aclocal.m40000664000175000017500000007633515053010106016622 0ustar locutuslocutus# generated automatically by aclocal 1.9.5 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"]) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION so it can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.9.5])]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 7 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE]) AC_SUBST([$1_FALSE]) if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH]) ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. #serial 3 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 12 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.58])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AM_PROG_INSTALL_SH AM_PROG_INSTALL_STRIP AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl ]) ]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $1 | $1:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl install_sh=${install_sh-"$am_aux_dir/install-sh"} AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_MKDIR_P # --------------- # Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. # # Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories # created by `make install' are always world readable, even if the # installer happens to have an overly restrictive umask (e.g. 077). # This was a mistake. There are at least two reasons why we must not # use `-m 0755': # - it causes special bits like SGID to be ignored, # - it may be too restrictive (some setups expect 775 directories). # # Do not use -m 0755 and let people choose whatever they expect by # setting umask. # # We cannot accept any implementation of `mkdir' that recognizes `-p'. # Some implementations (such as Solaris 8's) are not thread-safe: if a # parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c' # concurrently, both version can detect that a/ is missing, but only # one can create it and the other will error out. Consequently we # restrict ourselves to GNU make (using the --version option ensures # this.) AC_DEFUN([AM_PROG_MKDIR_P], [if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then # We used to keeping the `.' as first argument, in order to # allow $(mkdir_p) to be used without argument. As in # $(mkdir_p) $(somedir) # where $(somedir) is conditionally defined. However this is wrong # for two reasons: # 1. if the package is installed by a user who cannot write `.' # make install will fail, # 2. the above comment should most certainly read # $(mkdir_p) $(DESTDIR)$(somedir) # so it does not work when $(somedir) is undefined and # $(DESTDIR) is not. # To support the latter case, we have to write # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), # so the `.' trick is pointless. mkdir_p='mkdir -p --' else # On NextStep and OpenStep, the `mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because `.' already # exists. for d in ./-p ./--version; do test -d $d && rmdir $d done # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. if test -f "$ac_aux_dir/mkinstalldirs"; then mkdir_p='$(mkinstalldirs)' else mkdir_p='$(install_sh) -d' fi fi AC_SUBST([mkdir_p])]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # ------------------------------ # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of `v7', `ustar', or `pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. AM_MISSING_PROG([AMTAR], [tar]) m4_if([$1], [v7], [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([config/codeset.m4]) m4_include([config/getline.m4]) m4_include([config/gettext-ver.m4]) m4_include([config/gettext.m4]) m4_include([config/glibc21.m4]) m4_include([config/iconv.m4]) m4_include([config/lcmessage.m4]) m4_include([config/lib-ld.m4]) m4_include([config/lib-link.m4]) m4_include([config/lib-prefix.m4]) m4_include([config/progtest.m4]) m4_include([config/stdbool.m4]) m4_include([config/strverscmp.m4]) kbuild-3686/src/oldsed/COPYING0000664000175000017500000004312215053010106016001 0ustar locutuslocutus GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, 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 show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 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 Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision 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 generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. kbuild-3686/src/oldsed/config.h.darwin0000664000175000017500000002442515053010105017653 0ustar locutuslocutus/* config.h. Generated by configure. */ /* config_h.in. Generated from configure.ac by autoheader. */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if translation of program messages to the user's native language is requested. */ /* #undef ENABLE_NLS */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ #define HAVE_ALLOCA_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_ARGZ_H */ /* Define to 1 if you have the `bcopy' function. */ #define HAVE_BCOPY 1 /* Define to 1 if you have the `btowc' function. */ #define HAVE_BTOWC 1 /* Define to 1 if you have the `bzero' function. */ #define HAVE_BZERO 1 /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* #undef HAVE_DCGETTEXT */ /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ /* #undef HAVE_DOPRNT */ /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H 1 /* Define to 1 if you have the `fchmod' function. */ #define HAVE_FCHMOD 1 /* Define to 1 if you have the `fchown' function. */ #define HAVE_FCHOWN 1 /* Define to 1 if you have the `feof_unlocked' function. */ #define HAVE_FEOF_UNLOCKED 1 /* Define to 1 if you have the `fgets_unlocked' function. */ /* #undef HAVE_FGETS_UNLOCKED */ /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getc_unlocked' function. */ #define HAVE_GETC_UNLOCKED 1 /* Define to 1 if you have the `getegid' function. */ #define HAVE_GETEGID 1 /* Define to 1 if you have the `geteuid' function. */ #define HAVE_GETEUID 1 /* Define to 1 if you have the `getgid' function. */ #define HAVE_GETGID 1 /* Define to 1 if you have the `getpagesize' function. */ #define HAVE_GETPAGESIZE 1 /* Define if the GNU gettext() function is already present or preinstalled. */ /* #undef HAVE_GETTEXT */ /* Define to 1 if you have the `getuid' function. */ #define HAVE_GETUID 1 /* Define if you have the iconv() function. */ #define HAVE_ICONV 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_IO_H */ /* Define to 1 if you have the `isascii' function. */ #define HAVE_ISASCII 1 /* Define to 1 if you have the `isatty' function. */ #define HAVE_ISATTY 1 /* Define to 1 if you have the `isblank' function. */ #define HAVE_ISBLANK 1 /* Define if you have and nl_langinfo(CODESET). */ #define HAVE_LANGINFO_CODESET 1 /* Define if your file defines LC_MESSAGES. */ #define HAVE_LC_MESSAGES 1 /* Define to 1 if you have the `regex' library (-lregex). */ /* #undef HAVE_LIBREGEX */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you support file names longer than 14 characters. */ #define HAVE_LONG_FILE_NAMES 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MALLOC_H */ /* Define to 1 if mbrtowc and mbstate_t are properly declared. */ #define HAVE_MBRTOWC 1 /* Define to 1 if declares mbstate_t. */ #define HAVE_MBSTATE_T 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MCHECK_H */ /* Define to 1 if you have the `memchr' function. */ #define HAVE_MEMCHR 1 /* Define to 1 if you have the `memcmp' function. */ #define HAVE_MEMCMP 1 /* Define to 1 if you have the `memcpy' function. */ #define HAVE_MEMCPY 1 /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mempcpy' function. */ /* #undef HAVE_MEMPCPY */ /* Define to 1 if you have the `memset' function. */ #define HAVE_MEMSET 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have a working `mmap' system call. */ #define HAVE_MMAP 1 /* Define to 1 if you have the `munmap' function. */ #define HAVE_MUNMAP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_NL_TYPES_H 1 /* Define to 1 if libc includes obstacks. */ /* #undef HAVE_OBSTACK */ /* Define to 1 if you have the `pathconf' function. */ #define HAVE_PATHCONF 1 /* Define to 1 if you have the `popen' function. */ #define HAVE_POPEN 1 /* Define to 1 if you have the `putenv' function. */ #define HAVE_PUTENV 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_REGEX_H */ /* Define to 1 if you have the `setenv' function. */ #define HAVE_SETENV 1 /* Define to 1 if you have the `setlocale' function. */ #define HAVE_SETLOCALE 1 /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if stdbool.h conforms to C99. */ #define HAVE_STDBOOL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `stpcpy' function. */ #define HAVE_STPCPY 1 /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strtoul' function. */ #define HAVE_STRTOUL 1 /* Define to 1 if you have the `strverscmp' function. */ /* #undef HAVE_STRVERSCMP */ /* 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. */ #define HAVE_SYS_FILE_H 1 /* 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. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the `tsearch' function. */ #define HAVE_TSEARCH 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_WCHAR_H 1 /* Define to 1 if you have the `wcrtomb' function. */ #define HAVE_WCRTOMB 1 /* Define to 1 if you have the `wcscoll' function. */ #define HAVE_WCSCOLL 1 /* Define to 1 if you have the header file. */ #define HAVE_WCTYPE_H 1 /* Define to 1 if the system has the type `_Bool'. */ #define HAVE__BOOL 1 /* Define to 1 if you have the `__argz_count' function. */ /* #undef HAVE___ARGZ_COUNT */ /* Define to 1 if you have the `__argz_next' function. */ /* #undef HAVE___ARGZ_NEXT */ /* Define to 1 if you have the `__argz_stringify' function. */ /* #undef HAVE___ARGZ_STRINGIFY */ /* Define as const if the declaration of iconv() needs const. */ #define ICONV_CONST const /* Name of package */ #define PACKAGE "sed" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bonzini@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "sed" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "sed 4.1.5" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "sed" /* Define to the version of this package. */ #define PACKAGE_VERSION "4.1.5" /* Define to the version of GNU sed whose features are supported by this sed. */ #define SED_FEATURE_VERSION "4.1" /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ #define VERSION "4.1.5" /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* # undef _ALL_SOURCE */ #endif /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Include BSD functions in regex, used by the testsuite */ #define _REGEX_RE_COMP 1 /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to a type if does not define. */ /* #undef mbstate_t */ /* Define to `long' if does not define. */ /* #undef off_t */ /* Define to `unsigned' if does not define. */ /* #undef size_t */ /* Define to `int' if does not define. */ /* #undef ssize_t */ kbuild-3686/src/oldsed/README-alpha0000664000175000017500000000030415053010105016703 0ustar locutuslocutusThis is an alpha version of GNU sed. Please try it on a wide range of scripts (especially configure scripts) and submit bug reports to bonzini@gnu.org. Thanks, Paolo Bonzini GNU sed maintainer kbuild-3686/src/oldsed/COPYING.DOC0000664000175000017500000004330215053010106016405 0ustar locutuslocutus GNU Free Documentation License Version 1.1, March 2000 Copyright (C) 2000 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other written document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (For example, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, whose contents can be viewed and edited directly and straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup has been designed to thwart or discourage subsequent modification by readers is not Transparent. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML designed for human modification. Opaque formats include PostScript, PDF, proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies of the Document numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a publicly-accessible computer-network location containing a complete Transparent copy of the Document, free of added material, which the general network-using public has access to download anonymously at no charge using public-standard network protocols. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has less than five). C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section entitled "History", and its title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. In any section entitled "Acknowledgements" or "Dedications", preserve the section's title, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section as "Endorsements" or to conflict in title with any Invariant Section. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections entitled "History" in the various original documents, forming one section entitled "History"; likewise combine any sections entitled "Acknowledgements", and any sections entitled "Dedications". You must delete all sections entitled "Endorsements." 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, does not as a whole count as a Modified Version of the Document, provided no compilation copyright is claimed for the compilation. Such a compilation is called an "aggregate", and this License does not apply to the other self-contained works thus compiled with the Document, on account of their being thus compiled, if they are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one quarter of the entire aggregate, the Document's Cover Texts may be placed on covers that surround only the Document within the aggregate. Otherwise they must appear on covers around the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License provided that you also include the original English version of this License. In case of a disagreement between the translation and the original English version of this License, the original English version will prevail. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright (c) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. A copy of the license is included in the section entitled "GNU Free Documentation License". If you have no Invariant Sections, write "with no Invariant Sections" instead of saying which ones are invariant. If you have no Front-Cover Texts, write "no Front-Cover Texts" instead of "Front-Cover Texts being LIST"; likewise for Back-Cover Texts. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software. kbuild-3686/src/oldsed/config_h.in0000664000175000017500000002335415053010105017056 0ustar locutuslocutus/* config_h.in. Generated from configure.ac by autoheader. */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ #undef CRAY_STACKSEG_END /* Define to 1 if using `alloca.c'. */ #undef C_ALLOCA /* Define to 1 if translation of program messages to the user's native language is requested. */ #undef ENABLE_NLS /* Define to 1 if you have `alloca', as a function or macro. */ #undef HAVE_ALLOCA /* Define to 1 if you have and it should be used (not on Ultrix). */ #undef HAVE_ALLOCA_H /* Define to 1 if you have the header file. */ #undef HAVE_ARGZ_H /* Define to 1 if you have the `bcopy' function. */ #undef HAVE_BCOPY /* Define to 1 if you have the `btowc' function. */ #undef HAVE_BTOWC /* Define to 1 if you have the `bzero' function. */ #undef HAVE_BZERO /* Define if the GNU dcgettext() function is already present or preinstalled. */ #undef HAVE_DCGETTEXT /* 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 header file. */ #undef HAVE_ERRNO_H /* Define to 1 if you have the `fchmod' function. */ #undef HAVE_FCHMOD /* Define to 1 if you have the `fchown' function. */ #undef HAVE_FCHOWN /* Define to 1 if you have the `feof_unlocked' function. */ #undef HAVE_FEOF_UNLOCKED /* Define to 1 if you have the `fgets_unlocked' function. */ #undef HAVE_FGETS_UNLOCKED /* Define to 1 if you have the `getcwd' function. */ #undef HAVE_GETCWD /* Define to 1 if you have the `getc_unlocked' function. */ #undef HAVE_GETC_UNLOCKED /* Define to 1 if you have the `getegid' function. */ #undef HAVE_GETEGID /* Define to 1 if you have the `geteuid' function. */ #undef HAVE_GETEUID /* Define to 1 if you have the `getgid' function. */ #undef HAVE_GETGID /* Define to 1 if you have the `getpagesize' function. */ #undef HAVE_GETPAGESIZE /* Define if the GNU gettext() function is already present or preinstalled. */ #undef HAVE_GETTEXT /* Define to 1 if you have the `getuid' function. */ #undef HAVE_GETUID /* Define if you have the iconv() function. */ #undef HAVE_ICONV /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_IO_H /* Define to 1 if you have the `isascii' function. */ #undef HAVE_ISASCII /* Define to 1 if you have the `isatty' function. */ #undef HAVE_ISATTY /* Define to 1 if you have the `isblank' function. */ #undef HAVE_ISBLANK /* Define if you have and nl_langinfo(CODESET). */ #undef HAVE_LANGINFO_CODESET /* Define if your file defines LC_MESSAGES. */ #undef HAVE_LC_MESSAGES /* Define to 1 if you have the `regex' library (-lregex). */ #undef HAVE_LIBREGEX /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H /* Define to 1 if you support file names longer than 14 characters. */ #undef HAVE_LONG_FILE_NAMES /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if mbrtowc and mbstate_t are properly declared. */ #undef HAVE_MBRTOWC /* Define to 1 if declares mbstate_t. */ #undef HAVE_MBSTATE_T /* Define to 1 if you have the header file. */ #undef HAVE_MCHECK_H /* Define to 1 if you have the `memchr' function. */ #undef HAVE_MEMCHR /* Define to 1 if you have the `memcmp' function. */ #undef HAVE_MEMCMP /* Define to 1 if you have the `memcpy' function. */ #undef HAVE_MEMCPY /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `mempcpy' function. */ #undef HAVE_MEMPCPY /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if you have the `mkstemp' function. */ #undef HAVE_MKSTEMP /* Define to 1 if you have a working `mmap' system call. */ #undef HAVE_MMAP /* Define to 1 if you have the `munmap' function. */ #undef HAVE_MUNMAP /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_NL_TYPES_H /* Define to 1 if libc includes obstacks. */ #undef HAVE_OBSTACK /* Define to 1 if you have the `pathconf' function. */ #undef HAVE_PATHCONF /* Define to 1 if you have the `popen' function. */ #undef HAVE_POPEN /* Define to 1 if you have the `putenv' function. */ #undef HAVE_PUTENV /* Define to 1 if you have the header file. */ #undef HAVE_REGEX_H /* Define to 1 if you have the `setenv' function. */ #undef HAVE_SETENV /* Define to 1 if you have the `setlocale' function. */ #undef HAVE_SETLOCALE /* Define to 1 if you have the header file. */ #undef HAVE_STDARG_H /* Define to 1 if stdbool.h conforms to C99. */ #undef HAVE_STDBOOL_H /* Define to 1 if you have the header file. */ #undef HAVE_STDDEF_H /* 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 `stpcpy' function. */ #undef HAVE_STPCPY /* Define to 1 if you have the `strcasecmp' function. */ #undef HAVE_STRCASECMP /* Define to 1 if you have the `strchr' function. */ #undef HAVE_STRCHR /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* 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 `strtoul' function. */ #undef HAVE_STRTOUL /* Define to 1 if you have the `strverscmp' function. */ #undef HAVE_STRVERSCMP /* 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_FILE_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_PARAM_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 `tsearch' function. */ #undef HAVE_TSEARCH /* 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 1 if you have the header file. */ #undef HAVE_WCHAR_H /* Define to 1 if you have the `wcrtomb' function. */ #undef HAVE_WCRTOMB /* Define to 1 if you have the `wcscoll' function. */ #undef HAVE_WCSCOLL /* Define to 1 if you have the header file. */ #undef HAVE_WCTYPE_H /* Define to 1 if the system has the type `_Bool'. */ #undef HAVE__BOOL /* Define to 1 if you have the `__argz_count' function. */ #undef HAVE___ARGZ_COUNT /* Define to 1 if you have the `__argz_next' function. */ #undef HAVE___ARGZ_NEXT /* Define to 1 if you have the `__argz_stringify' function. */ #undef HAVE___ARGZ_STRINGIFY /* Define as const if the declaration of iconv() needs const. */ #undef ICONV_CONST /* Name of package */ #undef PACKAGE /* 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 to the version of GNU sed whose features are supported by this sed. */ #undef SED_FEATURE_VERSION /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ #undef STACK_DIRECTION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES /* Define to 1 if on MINIX. */ #undef _MINIX /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ #undef _POSIX_1_SOURCE /* Define to 1 if you need to in order for `stat' and other things to work. */ #undef _POSIX_SOURCE /* Include BSD functions in regex, used by the testsuite */ #undef _REGEX_RE_COMP /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define to a type if does not define. */ #undef mbstate_t /* Define to `long' if does not define. */ #undef off_t /* Define to `unsigned' if does not define. */ #undef size_t /* Define to `int' if does not define. */ #undef ssize_t kbuild-3686/src/oldsed/INSTALL0000664000175000017500000002203015053010105015771 0ustar locutuslocutusCopyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== These are generic installation instructions. 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, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. (Caching is disabled by default to prevent problems with accidental use of stale cache files.) 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 you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You only need `configure.ac' 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. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix *Note Defining Variables::, for more details. 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 support 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' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS 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 machine type. If you are _building_ compiler tools for cross-compiling, you should use the `--target=TYPE' option to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. 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. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc will cause the specified gcc to be used as the C compiler (unless it is overridden in the site shell script). `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--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. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. kbuild-3686/src/kDeDup/0000775000175000017500000000000015053010106014646 5ustar locutuslocutuskbuild-3686/src/kDeDup/Makefile.kmk0000664000175000017500000000201015053010106017060 0ustar locutuslocutus# $Id: Makefile.kmk 3012 2016-11-07 11:53:11Z bird $ ## @file # Sub-makefile for kDeDup. # # # Copyright (c) 2016 knut st. osmundsen # # This file is part of kBuild. # # kBuild 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 3 of the License, or # (at your option) any later version. # # kBuild 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 kBuild. If not, see # # SUB_DEPTH = ../.. include $(KBUILD_PATH)/subheader.kmk PROGRAMS += kDeDup kDeDup_TEMPLATE = BIN kDeDup_LIBS = $(LIB_KUTIL) kDeDup_SOURCES = kDeDup.c include $(FILE_KBUILD_SUB_FOOTER) kbuild-3686/src/kDeDup/kDeDup.c0000664000175000017500000012273615053010106016201 0ustar locutuslocutus/* $Id: kDeDup.c 3296 2019-01-22 21:29:08Z bird $ */ /** @file * kDeDup - Utility that finds duplicate files, optionally hardlinking them. */ /* * Copyright (c) 2016 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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. * * kBuild 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 kBuild; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include #include #include #include #include #if K_OS != K_OS_WINDOWS # include # include # include # include #endif #include "md5.h" //#include "sha2.h" #if K_OS == K_OS_WINDOWS # include "nt/ntstuff.h" # include "nt/ntstat.h" # include "nt/fts-nt.h" # include "nt/nthlp.h" # include "nt/ntunlink.h" #else # include "fts.h" #endif /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ /** * The key is made up of two cryptographic hashes, collisions are * highly unlikely (once SHA2 is implemented). */ typedef struct KDUPFILENODEKEY { /** The MD5 digest of the file. */ KU8 abMd5[16]; /** The 256-bit SHA-2 digest of the file. */ KU8 abSha2[32]; } KDUPFILENODEKEY; /** Pointer to a file node.*/ typedef struct KDUPFILENODE *PKDUPFILENODE; /** * Hash tree node. */ typedef struct KDUPFILENODE { /** The is made up of two hashes. */ KDUPFILENODEKEY mKey; /** Left branch. */ PKDUPFILENODE mpLeft; /** Right branch. */ PKDUPFILENODE mpRight; /** Tree height (hmm). */ KU8 mHeight; /** The inode number. */ KU64 uInode; /** The device number. */ KU64 uDev; /** Pointer to next hard linked node (same inode and udev values). */ PKDUPFILENODE pNextHardLink; /** Pointer to next duplicate node. */ PKDUPFILENODE pNextDup; /** Pointer to next duplicate node on the global list. */ PKDUPFILENODE pNextGlobalDup; /** The path to this file (variable size). */ #if K_OS == K_OS_WINDOWS wchar_t wszPath[1]; #else char szPath[1]; #endif } KDUPFILENODE; #if K_OS == K_OS_WINDOWS # define PATH_PRI "ls" # define PATH_MEMB wszPath # define FTS_ACCPATH fts_wcsaccpath #else # define PATH_PRI "s" # define PATH_MEMB szPath # define FTS_ACCPATH fts_accpath #endif /*#define KAVL_EQUAL_ALLOWED*/ #define KAVL_CHECK_FOR_EQUAL_INSERT #define KAVL_MAX_STACK 32 /*#define KAVL_RANGE */ /*#define KAVL_OFFSET */ /*#define KAVL_STD_KEY_COMP*/ #define KAVLKEY KDUPFILENODEKEY #define KAVLNODE KDUPFILENODE #define KAVL_FN(name) kDupFileTree_ ## name #define KAVL_TYPE(prefix,name) prefix ## KDUPFILENODE ## name #define KAVL_INT(name) KDUPFILENODEINT ## name #define KAVL_DECL(rettype) static rettype #define KAVL_G(key1, key2) ( memcmp(&(key1), &(key2), sizeof(KDUPFILENODEKEY)) > 0 ) #define KAVL_E(key1, key2) ( memcmp(&(key1), &(key2), sizeof(KDUPFILENODEKEY)) == 0 ) #define KAVL_NE(key1, key2) ( memcmp(&(key1), &(key2), sizeof(KDUPFILENODEKEY)) != 0 ) #define register #include //#include //#include - busted #include //#include //#include //#include //#include #include #undef register /** Pointer to a size tree node. */ typedef struct KDUPSIZENODE *PKDUPSIZENODE; /** * Size tree node. */ typedef struct KDUPSIZENODE { /** The file size. */ KU64 mKey; /** Left branch. */ PKDUPSIZENODE mpLeft; /** Right branch. */ PKDUPSIZENODE mpRight; /** Tree height (hmm). */ KU8 mHeight; /** Number of files. */ KU32 cFiles; /** Tree with same sized files. * When cFiles is 1 the root node does not have hashes calculated yet. */ KDUPFILENODEROOT FileRoot; } KDUPSIZENODE; /*#define KAVL_EQUAL_ALLOWED*/ #define KAVL_CHECK_FOR_EQUAL_INSERT #define KAVL_MAX_STACK 32 /*#define KAVL_RANGE */ /*#define KAVL_OFFSET */ #define KAVL_STD_KEY_COMP #define KAVLKEY KU64 #define KAVLNODE KDUPSIZENODE #define KAVL_FN(name) kDupSizeTree_ ## name #define KAVL_TYPE(prefix,name) prefix ## KDUPSIZENODE ## name #define KAVL_INT(name) KDUPSIZENODEINT ## name #define KAVL_DECL(rettype) static rettype #include //#include //#include - busted #include //#include //#include //#include //#include #include /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ /** The verbosity level. */ static unsigned g_cVerbosity = 0; /** Whether to recurse into subdirectories. */ static KBOOL g_fRecursive = K_FALSE; /** Whether to recurse into symlinked subdirectories. */ static KBOOL g_fRecursiveViaSymlinks = K_FALSE; /** Whether to follow symbolicly linked files. */ static KBOOL g_fFollowSymlinkedFiles = K_TRUE; /** Minimum file size to care about. */ static KU64 g_cbMinFileSize = 1; /** Maximum file size to care about. */ static KU64 g_cbMaxFileSize = KU64_MAX; /** The root of the size tree. */ static KDUPSIZENODEROOT g_SizeRoot; /** Global list of duplicate file with duplicates. * @remarks This only contains the files in the hash tree, not the ones on * the KDUPFILENODE::pNextDup list. */ static PKDUPFILENODE g_pDuplicateHead = NULL; /** Where to insert the next file with duplicates. */ static PKDUPFILENODE *g_ppNextDuplicate = &g_pDuplicateHead; /** Number of files we're tracking. */ static KU64 g_cFiles = 0; /** Number of hardlinked files or files entered more than once. */ static KU64 g_cHardlinked = 0; /** Number of duplicates files (not hardlinked). */ static KU64 g_cDuplicates = 0; /** Number of duplicates files that can be hardlinked. */ static KU64 g_cDuplicatesSaved = 0; /** Size that could be saved if the duplicates were hardlinked. */ static KU64 g_cbDuplicatesSaved = 0; /** * Wrapper around malloc() that complains when out of memory. * * @returns Pointer to allocated memory * @param cb The size of the memory to allocate. */ static void *kDupAlloc(KSIZE cb) { void *pvRet = malloc(cb); if (pvRet) return pvRet; fprintf(stderr, "kDeDup: error: out of memory! (cb=%#zx)\n", cb); return NULL; } /** Wrapper around free() for symmetry. */ #define kDupFree(ptr) free(ptr) #if K_OS != K_OS_WINDOWS /** Wrapper around read() that hides EINTR and such. */ static ssize_t kDupReadFile(int fd, void *pvBuf, size_t cbToRead) { ssize_t cbRet; do cbRet = read(fd, pvBuf, cbToRead); while (cbRet < 0 && errno == EINTR); if (cbRet > 0 && (size_t)cbRet != cbToRead) { for (;;) { size_t cbLeft = cbToRead - (size_t)cbRet; ssize_t cbPart; do cbPart = read(fd, (KU8 *)pvBuf + (size_t)cbRet, cbLeft); while (cbPart < 0 && errno == EINTR); if (cbPart <= 0) break; cbRet += cbPart; } } return cbRet; } #endif static void kDupHashFile(PKDUPFILENODE pFileNode, FTSENT *pFtsEnt) { KSIZE i; PKDUPFILENODE *ppHash; /* * Open the file. */ #if K_OS == K_OS_WINDOWS HANDLE hFile; if (pFtsEnt && pFtsEnt->fts_parent && pFtsEnt->fts_parent->fts_dirfd != INVALID_HANDLE_VALUE) hFile = birdOpenFileExW(pFtsEnt->fts_parent->fts_dirfd, pFtsEnt->fts_wcsname, FILE_READ_DATA | SYNCHRONIZE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT, OBJ_CASE_INSENSITIVE); else hFile = birdOpenFileExW(NULL, pFileNode->wszPath, FILE_READ_DATA | SYNCHRONIZE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT, OBJ_CASE_INSENSITIVE); if (hFile != INVALID_HANDLE_VALUE) #else /* K_OS != K_OS_WINDOWS */ # ifdef O_BINARY int fd = open(pFileNode->szPath, O_RDONLY | O_BINARY); # else int fd = open(pFileNode->szPath, O_RDONLY); # endif if (fd >= 0) #endif /* K_OS != K_OS_WINDOWS */ { /* * Init the hash calculation contexts. */ struct MD5Context Md5Ctx; //SHA256CONTEXT Sha256Ctx; MD5Init(&Md5Ctx); //Sha256Init(&Sha256Ctx); /* * Process the file chunk by chunk. * * We could complicate this by memory mapping medium sized files, but * those kind of complications can wait. */ for (;;) { static KU8 s_abBuffer[2*1024*1024]; #if K_OS == K_OS_WINDOWS MY_NTSTATUS rcNt; MY_IO_STATUS_BLOCK Ios; Ios.Information = -1; Ios.u.Status = -1; rcNt = g_pfnNtReadFile(hFile, NULL /*hEvent*/, NULL /*pfnApc*/, NULL /*pvApcCtx*/, &Ios, s_abBuffer, sizeof(s_abBuffer), NULL /*poffFile*/, NULL /*puKey*/); if (MY_NT_SUCCESS(rcNt)) { MD5Update(&Md5Ctx, s_abBuffer, (unsigned)Ios.Information); //SHA256Update(&Sha256Ctx, s_abBuffer, Ios.Information); } else if (rcNt != STATUS_END_OF_FILE) { fprintf(stderr, "kDeDup: warning: Error reading '%ls': %#x\n", pFileNode->wszPath, rcNt); break; } /* Check for end of file. */ if ( rcNt == STATUS_END_OF_FILE || Ios.Information < sizeof(s_abBuffer)) { MD5Final(pFileNode->mKey.abMd5, &Md5Ctx); //Sha256Final(pFileNode->mKey.abSha2, &Sha256Ctx); birdCloseFile(hFile); return; } #else /* K_OS != K_OS_WINDOWS */ ssize_t cbRead = kDupReadFile(fd, s_abBuffer, sizeof(s_abBuffer)); if (cbRead > 0) { MD5Update(&Md5Ctx, s_abBuffer, (unsigned)cbRead); //SHA256Update(&Sha256Ctx, s_abBuffer, (unsigned)cbRead); } else if (cbRead == 0) { MD5Final(pFileNode->mKey.abMd5, &Md5Ctx); //Sha256Final(pFileNode->mKey.abSha2, &Sha256Ctx); close(fd); return; } else { fprintf(stderr, "kDeDup: warning: Error reading '%s': %s (%d)\n", pFileNode->szPath, strerror(errno), errno); break; } #endif /* K_OS != K_OS_WINDOWS */ } #if K_OS == K_OS_WINDOWS birdCloseFile(hFile); #else close(fd); #endif } else fprintf(stderr, "kDeDup: warning: Failed to open '%" PATH_PRI "': %s (%d)\n", pFileNode->PATH_MEMB, strerror(errno), errno); /* * Hashing failed. We fake the digests by repeating the node pointer value * again and again, holding a collision with both SHA2 and MD5 with similar * digest pattern for highly unlikely. */ ppHash = (PKDUPFILENODE *)&pFileNode->mKey; i = sizeof(pFileNode->mKey) / sizeof(*ppHash); while (i-- > 0) *ppHash++ = pFileNode; } /** * Deal with one file, adding it to the tree if it matches the criteria. * * @returns 0 on success, non-zero on failure. * @param pFtsEnt The FTS entry for the file. */ static int kDupDoFile(FTSENT *pFtsEnt) { KU64 cbFile; #if K_OS == K_OS_WINDOWS struct stat const *pStat = &pFtsEnt->fts_stat; #else struct stat const *pStat = pFtsEnt->fts_statp; #endif if (g_cVerbosity >= 2) printf("debug: kDupDoFile(%" PATH_PRI ")\n", pFtsEnt->FTS_ACCPATH); /* * Check that it's within the size range. */ cbFile = pStat->st_size; if ( cbFile >= g_cbMinFileSize && cbFile <= g_cbMaxFileSize) { /* * Start out treating this like a unique file with a unique size, i.e. * allocate all the structures we might possibly need. */ #if K_OS == K_OS_WINDOWS size_t cbAccessPath = (wcslen(pFtsEnt->fts_wcsaccpath) + 1) * sizeof(wchar_t); #else size_t cbAccessPath = strlen(pFtsEnt->fts_accpath) + 1; #endif PKDUPFILENODE pFileNode = (PKDUPFILENODE)kDupAlloc(sizeof(*pFileNode) + cbAccessPath); PKDUPSIZENODE pSizeNode = (PKDUPSIZENODE)kDupAlloc(sizeof(*pSizeNode)); if (!pFileNode || !pSizeNode) return 3; g_cFiles++; memset(&pFileNode->mKey, 0, sizeof(pFileNode->mKey)); pFileNode->pNextHardLink = NULL; pFileNode->pNextDup = NULL; pFileNode->pNextGlobalDup = NULL; pFileNode->uDev = pStat->st_dev; pFileNode->uInode = pStat->st_ino; memcpy(pFileNode->PATH_MEMB, pFtsEnt->FTS_ACCPATH, cbAccessPath); pSizeNode->mKey = cbFile; pSizeNode->cFiles = 1; kDupFileTree_Init(&pSizeNode->FileRoot); kDupFileTree_Insert(&pSizeNode->FileRoot, pFileNode); /* * Try insert it. */ if (kDupSizeTree_Insert(&g_SizeRoot, pSizeNode)) { /* unique size, nothing more to do for now. */ } else { /* * More than one file with this size. We may need to hash the * hash the file we encountered with this size, if this is the * second one. In that case we should check for hardlinked or * double entering of the file first as well. */ kDupFree(pSizeNode); pSizeNode = kDupSizeTree_Get(&g_SizeRoot, cbFile); if (pSizeNode->cFiles == 1) { PKDUPFILENODE pFirstFileNode = pSizeNode->FileRoot.mpRoot; if ( pFirstFileNode->uInode == pFileNode->uInode && pFileNode->uInode != 0 && pFirstFileNode->uDev == pFileNode->uDev) { pFileNode->pNextHardLink = pFirstFileNode->pNextHardLink; pFirstFileNode->pNextHardLink = pFileNode; if (g_cVerbosity >= 1) printf("Found hardlinked: '%" PATH_PRI "' -> '%" PATH_PRI "' (ino:%#" KX64_PRI " dev:%#" KX64_PRI ")\n", pFileNode->PATH_MEMB, pFirstFileNode->PATH_MEMB, pFileNode->uInode, pFileNode->uDev); g_cHardlinked += 1; return 0; } kDupHashFile(pFirstFileNode, NULL); } kDupHashFile(pFileNode, pFtsEnt); if (kDupFileTree_Insert(&pSizeNode->FileRoot, pFileNode)) { /* great, unique content */ } else { /* * Duplicate content. Could be hardlinked or a duplicate entry. */ PKDUPFILENODE pDupFileNode = kDupFileTree_Get(&pSizeNode->FileRoot, pFileNode->mKey); if ( pDupFileNode->uInode == pFileNode->uInode && pFileNode->uInode != 0 && pDupFileNode->uDev == pFileNode->uDev) { pFileNode->pNextHardLink = pDupFileNode->pNextHardLink; pDupFileNode->pNextHardLink = pFileNode; if (g_cVerbosity >= 1) printf("Found hardlinked: '%" PATH_PRI "' -> '%" PATH_PRI "' (ino:%#" KX64_PRI " dev:%#" KX64_PRI ")\n", pFileNode->PATH_MEMB, pDupFileNode->PATH_MEMB, pFileNode->uInode, pFileNode->uDev); g_cHardlinked += 1; } else { KBOOL fDifferentDev; /* Genuinly duplicate (or inode numbers are busted). */ if (!pDupFileNode->pNextDup) { *g_ppNextDuplicate = pDupFileNode; g_ppNextDuplicate = &pDupFileNode->pNextGlobalDup; } /* The list is sorted by device to better facility hardlinking later. */ while ( (fDifferentDev = pDupFileNode->uDev != pFileNode->uDev) && pDupFileNode->pNextDup) pDupFileNode = pDupFileNode->pNextDup; pFileNode->pNextDup = pDupFileNode->pNextDup; pDupFileNode->pNextDup = pFileNode; g_cDuplicates += 1; if (!fDifferentDev) { g_cDuplicatesSaved += 1; #if K_OS == K_OS_WINDOWS g_cbDuplicatesSaved += pStat->st_blocks * BIRD_STAT_BLOCK_SIZE; #else g_cbDuplicatesSaved += pStat->st_size; #endif if (g_cVerbosity >= 1) printf("Found duplicate: '%" PATH_PRI "' <-> '%" PATH_PRI "'\n", pFileNode->PATH_MEMB, pDupFileNode->PATH_MEMB); } else if (g_cVerbosity >= 1) printf("Found duplicate: '%" PATH_PRI "' <-> '%" PATH_PRI "' (devices differ).\n", pFileNode->PATH_MEMB, pDupFileNode->PATH_MEMB); } } } } else if (g_cVerbosity >= 1) printf("Skipping '%" PATH_PRI "' because %" KU64_PRI " bytes is outside the size range.\n", pFtsEnt->FTS_ACCPATH, cbFile); return 0; } /** * Process the non-option arguments, creating the file tree. * * @returns 0 on success, non-zero on failure. * @param papwszFtsArgs The input in argv style. * @param fFtsOptions The FTS options. */ #if K_OS == K_OS_WINDOWS static int kDupReadAll(wchar_t **papwszFtsArgs, unsigned fFtsOptions) #else static int kDupReadAll(char **papszFtsArgs, unsigned fFtsOptions) #endif { int rcExit = 0; #if K_OS == K_OS_WINDOWS FTS *pFts = nt_fts_openw(papwszFtsArgs, fFtsOptions, NULL /*pfnCompare*/); #else FTS *pFts = fts_open(papszFtsArgs, fFtsOptions, NULL /*pfnCompare*/); #endif if (pFts != NULL) { for (;;) { #if K_OS == K_OS_WINDOWS FTSENT *pFtsEnt = nt_fts_read(pFts); #else FTSENT *pFtsEnt = fts_read(pFts); #endif if (pFtsEnt) { switch (pFtsEnt->fts_info) { case FTS_F: rcExit = kDupDoFile(pFtsEnt); if (rcExit == 0) continue; break; case FTS_D: if ( g_fRecursive || pFtsEnt->fts_level == FTS_ROOTLEVEL) /* enumerate dirs on the command line */ continue; #if K_OS == K_OS_WINDOWS rcExit = nt_fts_set(pFts, pFtsEnt, FTS_SKIP); #else rcExit = fts_set(pFts, pFtsEnt, FTS_SKIP); #endif if (rcExit == 0) continue; fprintf(stderr, "kDeDup: internal error: nt_fts_set failed!\n"); rcExit = 1; break; case FTS_DP: /* nothing to do here. */ break; case FTS_SL: { #if K_OS == K_OS_WINDOWS /* The nice thing on windows is that we already know whether it's a directory or file when encountering the symbolic link. */ if ( (pFtsEnt->fts_stat.st_isdirsymlink ? g_fRecursiveViaSymlinks : g_fFollowSymlinkedFiles) && pFtsEnt->fts_number == 0) #else struct stat St; if ( pFtsEnt->fts_number == 0 && ( (g_fRecursiveViaSymlinks && g_fFollowSymlinkedFiles) || ( stat(pFtsEnt->fts_accpath, &St) == 0 && (S_ISDIR(St.st_mode) ? g_fRecursiveViaSymlinks : g_fFollowSymlinkedFiles)))) #endif { pFtsEnt->fts_number++; #if K_OS == K_OS_WINDOWS rcExit = nt_fts_set(pFts, pFtsEnt, FTS_FOLLOW); #else rcExit = fts_set(pFts, pFtsEnt, FTS_FOLLOW); #endif if (rcExit == 0) continue; fprintf(stderr, "kDeDup: internal error: nt_fts_set failed!\n"); rcExit = 1; } break; } case FTS_DC: fprintf(stderr, "kDeDup: warning: Ignoring cycle '%" PATH_PRI "'!\n", pFtsEnt->FTS_ACCPATH); continue; case FTS_NS: fprintf(stderr, "kDeDup: warning: Failed to stat '%" PATH_PRI "': %s (%d)\n", pFtsEnt->FTS_ACCPATH, strerror(pFtsEnt->fts_errno), pFtsEnt->fts_errno); continue; case FTS_DNR: fprintf(stderr, "kDeDup: error: Error reading directory '%" PATH_PRI "': %s (%d)\n", pFtsEnt->FTS_ACCPATH, strerror(pFtsEnt->fts_errno), pFtsEnt->fts_errno); rcExit = 1; break; case FTS_ERR: fprintf(stderr, "kDeDup: error: Error on '%" PATH_PRI "': %s (%d)\n", pFtsEnt->FTS_ACCPATH, strerror(pFtsEnt->fts_errno), pFtsEnt->fts_errno); rcExit = 1; break; /* ignore */ case FTS_SLNONE: case FTS_DEFAULT: break; /* Not supposed to get here. */ default: fprintf(stderr, "kDeDup: internal error: fts_info=%d - '%" PATH_PRI "'\n", pFtsEnt->fts_info, pFtsEnt->FTS_ACCPATH); rcExit = 1; break; } } else if (errno == 0) break; else { fprintf(stderr, "kDeDup: error: nt_fts_read failed: %s (%d)\n", strerror(errno), errno); rcExit = 1; break; } } #if K_OS == K_OS_WINDOWS if (nt_fts_close(pFts) != 0) #else if (fts_close(pFts) != 0) #endif { fprintf(stderr, "kDeDup: error: nt_fts_close failed: %s (%d)\n", strerror(errno), errno); rcExit = 1; } } else { fprintf(stderr, "kDeDup: error: nt_fts_openw failed: %s (%d)\n", strerror(errno), errno); rcExit = 1; } return rcExit; } /** * Compares the content of the two files. * * @returns 0 if equal, 1 if not equal, -1 on open/read error. * @param pFile1 The first file. * @param pFile2 The second file. */ static int kDupCompareFiles(PKDUPFILENODE pFile1, PKDUPFILENODE pFile2) { #if K_OS == K_OS_WINDOWS int rcRet = 0; K_NOREF(pFile1); K_NOREF(pFile2); /** @todo compare files. */ #else int rcRet = -1; # ifdef O_BINARY int fOpen = O_RDONLY | O_BINARY; # else int fOpen = O_RDONLY; # endif /* * Open the two files. */ int fd1 = open(pFile1->szPath, fOpen); if (fd1 >= 0) { int fd2 = open(pFile2->szPath, fOpen); if (fd1 >= 0) { /* * Read and compare all the data. */ static KU8 s_abBuf1[2*1024*1024]; static KU8 s_abBuf2[2*1024*1024]; KU64 off = 0; for (;;) { ssize_t cb1 = kDupReadFile(fd1, s_abBuf1, sizeof(s_abBuf1)); ssize_t cb2 = kDupReadFile(fd2, s_abBuf2, sizeof(s_abBuf2)); if (cb1 < 0 || cb2 < 0) { if (cb1 < 0) fprintf(stderr, "kDeDup: error: reading from '%s': %s (%d)\n", pFile1->szPath, strerror(errno), errno); if (cb2 < 0) fprintf(stderr, "kDeDup: error: reading from '%s': %s (%d)\n", pFile2->szPath, strerror(errno), errno); break; } if (cb1 != cb2) { fprintf(stderr, "kDeDup: warning: '%s' now differs from '%s' in size...\n", pFile1->szPath, pFile2->szPath); rcRet = 1; break; } if (cb1 == 0) { rcRet = 0; break; } if (memcmp(s_abBuf1, s_abBuf2, cb1) != 0) { fprintf(stderr, "kDeDup: warning: hash collision: '%s' differs from '%s' (" KX64_PRI " LB %#x)\n", pFile1->szPath, pFile2->szPath, off, (unsigned)cb1); rcRet = 1; break; } off += cb1; } close(fd2); } close(fd1); } #endif return rcRet; } /** * Hardlink duplicates. */ static int kDupHardlinkDuplicates(void) { int rcExit = 0; PKDUPFILENODE pFileNode; for (pFileNode = g_pDuplicateHead; pFileNode != NULL; pFileNode = pFileNode->pNextGlobalDup) { PKDUPFILENODE pTargetFile = pFileNode; PKDUPFILENODE pDupFile; for (pDupFile = pFileNode->pNextDup; pDupFile != NULL; pDupFile = pDupFile->pNextDup) { /* * Can only hard link if the files are on the same device. */ if (pDupFile->uDev == pTargetFile->uDev) { if (kDupCompareFiles(pDupFile, pTargetFile) == 0) { /* * Start by renaming the orinal file before we try create the hard link. */ #if K_OS == K_OS_WINDOWS static const wchar_t s_wszBackupSuffix[] = L".kDepBackup"; wchar_t wszBackup[0x4000]; size_t cwcPath = wcslen(pDupFile->wszPath); if (cwcPath + sizeof(s_wszBackupSuffix) / sizeof(wchar_t) < K_ELEMENTS(wszBackup)) { memcpy(wszBackup, pDupFile->wszPath, cwcPath * sizeof(wchar_t)); memcpy(&wszBackup[cwcPath], s_wszBackupSuffix, sizeof(s_wszBackupSuffix)); if (MoveFileW(pDupFile->wszPath, wszBackup)) { if (CreateHardLinkW(pDupFile->wszPath, pTargetFile->wszPath, NULL)) { if (birdUnlinkForcedW(wszBackup) == 0) { if (g_cVerbosity >= 1) printf("Hardlinked '%ls' to '%ls'.\n", pDupFile->wszPath, pTargetFile->wszPath); } else { fprintf(stderr, "kDeDup: fatal: failed to delete '%ls' after hardlinking: %s (%d)\n", wszBackup, strerror(errno), errno); return 8; } } else { fprintf(stderr, "kDeDup: error: failed to hard link '%ls' to '%ls': %u\n", pDupFile->wszPath, wszBackup, GetLastError()); if (!MoveFileW(wszBackup, pDupFile->wszPath)) { fprintf(stderr, "kDeDup: fatal: Restore '%ls' to '%ls' after hardlinking failed: %u\n", wszBackup, pDupFile->wszPath, GetLastError()); return 8; } rcExit = 1; } } else { fprintf(stderr, "kDeDup: error: failed to rename '%ls' to '%ls': %u\n", pDupFile->wszPath, wszBackup, GetLastError()); rcExit = 1; } } else { fprintf(stderr, "kDeDup: error: too long backup path: '%ls'\n", pDupFile->wszPath); rcExit = 1; } #else /* K_OS != K_OS_WINDOWS */ static const char s_szBackupSuffix[] = ".kDepBackup"; char szBackup[0x4000]; size_t cchPath = strlen(pDupFile->szPath); if (cchPath + sizeof(s_szBackupSuffix) < sizeof(szBackup)) { struct stat StTmp; memcpy(szBackup, pDupFile->szPath, cchPath); memcpy(&szBackup[cchPath], s_szBackupSuffix, sizeof(s_szBackupSuffix)); if (stat(szBackup, &StTmp) != 0) { if (rename(pDupFile->szPath, szBackup) == 0) { if (link(pTargetFile->szPath, pDupFile->szPath) == 0) { if (unlink(szBackup) == 0) { if (g_cVerbosity >= 1) printf("Hardlinked '%s' to '%s'.\n", pDupFile->szPath, pTargetFile->szPath); } else { fprintf(stderr, "kDeDup: fatal: failed to delete '%s' after hardlinking: %s (%d)\n", szBackup, strerror(errno), errno); return 8; } } else { fprintf(stderr, "kDeDup: error: failed to hard link '%s' to '%s': %s (%d)\n", pDupFile->szPath, szBackup, strerror(errno), errno); if (rename(szBackup, pDupFile->szPath) != 0) { fprintf(stderr, "kDeDup: fatal: Restore '%s' to '%s' after hardlinking failed: %s (%d)\n", szBackup, pDupFile->szPath, strerror(errno), errno); return 8; } rcExit = 1; } } else { fprintf(stderr, "kDeDup: error: failed to rename '%s' to '%s': %s (%d)\n", pDupFile->szPath, szBackup, strerror(errno), errno); rcExit = 1; } } else { fprintf(stderr, "kDeDup: error: failed to rename '%s' to '%s': file already exist (st_mode=%#x)\n", pDupFile->szPath, szBackup, StTmp.st_mode); rcExit = 1; } } else { fprintf(stderr, "kDeDup: error: too long backup path: '%s'\n", pDupFile->szPath); rcExit = 1; } #endif /* K_OS != K_OS_WINDOWS */ } } /* * Since the list is sorted by uDev, we now change the target file. */ else pTargetFile = pDupFile; } } return rcExit; } static int usage(const char *pszName, FILE *pOut) { fprintf(pOut, "usage: %s [options] [path2 [..]]\n" "usage: %s <-V|--version>\n" "usage: %s <-h|--help>\n" , pszName, pszName, pszName); fprintf(pOut, "\n" "Options:\n" " -H, --dereference-command-line, --no-dereference-command-line\n" " Follow symbolic links on the command line.\n" " -L, --dereference\n" " Follow symbolic links while scanning directories.\n" " -P, --no-dereference\n" " Do not follow symbolic links while scanning directories.\n" " -r, --recursive\n" " Recurse into subdirectories, but do not follow links to them.\n" " -R, --recursive-dereference\n" " Same as -r, but also follow into symlinked subdirectories.\n" " -x, --one-file-system\n" " Do not consider other file system (volumes), either down thru a\n" " mount point or via a symbolic link to a directory.\n" " --no-one-file-system, --cross-file-systems\n" " Reverses the effect of --one-file-system.\n" " -q, --quiet, -v,--verbose\n" " Controls the output level.\n" " --hardlink-duplicates\n" " Hardlink duplicate files to remove duplicates and save space. By default\n" " no action is taken and only analysis is done.\n" ); return 0; } #if K_OS == K_OS_WINDOWS int wmain(int argc, wchar_t **argv) #else int main(int argc, char **argv) #endif { int rcExit; /* * Process parameters. Position. */ unsigned cFtsArgs = 0; #if K_OS == K_OS_WINDOWS wchar_t **papwszFtsArgs = (wchar_t **)calloc(argc + 1, sizeof(wchar_t *)); unsigned fFtsOptions = FTS_NOCHDIR | FTS_NO_ANSI; #else char **papszFtsArgs = (char **)calloc(argc + 1, sizeof(char *)); unsigned fFtsOptions = FTS_NOCHDIR; #endif KBOOL fEndOfOptions = K_FALSE; KBOOL fHardlinkDups = K_FALSE; int i; for (i = 1; i < argc; i++) { #if K_OS == K_OS_WINDOWS wchar_t *pwszArg = argv[i]; if ( *pwszArg == '-' && !fEndOfOptions) #else char *pszArg = argv[i]; if ( *pszArg == '-' && !fEndOfOptions) #endif { #if K_OS != K_OS_WINDOWS wchar_t wszOpt[1024] = { 0 }; wchar_t *pwszArg = wszOpt; mbsrtowcs(wszOpt, (const char **)&pszArg, 1024 - 1, NULL); #endif wchar_t wcOpt = *++pwszArg; pwszArg++; if (wcOpt == '-') { /* Translate long options. */ if (wcscmp(pwszArg, L"help") == 0) wcOpt = 'h'; else if (wcscmp(pwszArg, L"version") == 0) wcOpt = 'V'; else if (wcscmp(pwszArg, L"recursive") == 0) wcOpt = 'r'; else if (wcscmp(pwszArg, L"dereference-recursive") == 0) wcOpt = 'R'; else if (wcscmp(pwszArg, L"dereference") == 0) wcOpt = 'L'; else if (wcscmp(pwszArg, L"dereference-command-line") == 0) wcOpt = 'H'; else if (wcscmp(pwszArg, L"one-file-system") == 0) wcOpt = 'x'; /* Process long options. */ else if (*pwszArg == '\0') { fEndOfOptions = K_TRUE; continue; } else if (wcscmp(pwszArg, L"no-recursive") == 0) { g_fRecursive = g_fRecursiveViaSymlinks = K_FALSE; continue; } else if (wcscmp(pwszArg, L"no-dereference-command-line") == 0) { fFtsOptions &= ~FTS_COMFOLLOW; continue; } else if ( wcscmp(pwszArg, L"no-one-file-system") == 0 || wcscmp(pwszArg, L"cross-file-systems") == 0) { fFtsOptions &= ~FTS_XDEV; continue; } else if (wcscmp(pwszArg, L"hardlink-duplicates") == 0) { fHardlinkDups = K_TRUE; continue; } else { fprintf(stderr, "kDeDup: syntax error: Unknown option '--%ls'\n", pwszArg); return 2; } } /* Process one or more short options. */ do { switch (wcOpt) { case 'r': /* --recursive */ g_fRecursive = K_TRUE; break; case 'R': /* --dereference-recursive */ g_fRecursive = g_fRecursiveViaSymlinks = K_TRUE; break; case 'H': /* --dereference-command-line */ fFtsOptions |= FTS_COMFOLLOW; break; case 'L': /* --dereference*/ g_fFollowSymlinkedFiles = K_TRUE; break; case 'x': /* --one-file-system*/ fFtsOptions |= FTS_XDEV; break; case 'q': g_cVerbosity = 0; break; case 'v': g_cVerbosity++; break; case 'h': case '?': return usage("kDeDup", stdout); case 'V': printf("0.0.1\n"); return 0; default: #if K_OS == K_OS_WINDOWS fprintf(stderr, "kDeDup: syntax error: Unknown option '-%lc'\n", wcOpt); #else fprintf(stderr, "kDeDup: syntax error: Unknown option '-%c'\n", (int)wcOpt); #endif return 2; } wcOpt = *pwszArg++; } while (wcOpt != '\0'); } else { /* * Append non-option arguments to the FTS argument vector. */ #if K_OS == K_OS_WINDOWS papwszFtsArgs[cFtsArgs] = pwszArg; #else papszFtsArgs[cFtsArgs] = pszArg; #endif cFtsArgs++; } } /* * Do the FTS processing. */ kDupSizeTree_Init(&g_SizeRoot); #if K_OS == K_OS_WINDOWS rcExit = kDupReadAll(papwszFtsArgs, fFtsOptions); #else rcExit = kDupReadAll(papszFtsArgs, fFtsOptions); #endif if (rcExit == 0) { /* * Display the result. */ printf("Found %" KU64_PRI " duplicate files, out which %" KU64_PRI " can be hardlinked saving %" KU64_PRI " bytes\n", g_cDuplicates, g_cDuplicatesSaved, g_cbDuplicatesSaved); if (fHardlinkDups) rcExit = kDupHardlinkDuplicates(); } K_NOREF(kDupFileTree_Remove); K_NOREF(kDupSizeTree_Remove); return rcExit; } kbuild-3686/src/kmk/0000775000175000017500000000000015053010076014262 5ustar locutuslocutuskbuild-3686/src/kmk/dep.h0000664000175000017500000001546715053010075015217 0ustar locutuslocutus/* Definitions of dependency data structures for GNU Make. Copyright (C) 1988-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ /* Structure used in chains of names, for parsing and globbing. */ #define NAMESEQ(_t) \ _t *next; \ const char *name struct nameseq { NAMESEQ (struct nameseq); }; /* Flag bits for the second argument to 'read_makefile'. These flags are saved in the 'flags' field of each 'struct goaldep' in the chain returned by 'read_all_makefiles'. */ #define RM_NO_DEFAULT_GOAL (1 << 0) /* Do not set default goal. */ #define RM_INCLUDED (1 << 1) /* Search makefile search path. */ #define RM_DONTCARE (1 << 2) /* No error if it doesn't exist. */ #define RM_NO_TILDE (1 << 3) /* Don't expand ~ in file name. */ #define RM_NOFLAG 0 /* Structure representing one dependency of a file. Each struct file's 'deps' points to a chain of these, through 'next'. 'stem' is the stem for this dep line of static pattern rule or NULL. */ #ifndef CONFIG_WITH_INCLUDEDEP #define DEP(_t) \ NAMESEQ (_t); \ struct file *file; \ const char *stem; \ unsigned short flags : 8; \ unsigned short changed : 1; \ unsigned short ignore_mtime : 1; \ unsigned short staticpattern : 1; \ unsigned short need_2nd_expansion : 1 #else # define DEP(_t) \ NAMESEQ (_t); \ struct file *file; \ const char *stem; \ unsigned short flags : 8; \ unsigned short changed : 1; \ unsigned short ignore_mtime : 1; \ unsigned short staticpattern : 1; \ unsigned short need_2nd_expansion : 1; \ unsigned short includedep : 1 #endif struct dep { DEP (struct dep); }; /* Structure representing one goal. The goals to be built constitute a chain of these, chained through 'next'. 'stem' is not used, but it's simpler to include and ignore it. */ struct goaldep { DEP (struct goaldep); unsigned short error; floc floc; }; /* Options for parsing lists of filenames. */ #define PARSEFS_NONE 0x0000 #define PARSEFS_NOSTRIP 0x0001 #define PARSEFS_NOAR 0x0002 #define PARSEFS_NOGLOB 0x0004 #define PARSEFS_EXISTS 0x0008 #define PARSEFS_NOCACHE 0x0010 #ifndef CONFIG_WITH_ALLOC_CACHES #define PARSE_FILE_SEQ(_s,_t,_c,_p,_f) \ (_t *)parse_file_seq ((_s),sizeof (_t),(_c),(_p),(_f)) #define PARSE_SIMPLE_SEQ(_s,_t) \ (_t *)parse_file_seq ((_s),sizeof (_t),MAP_NUL,NULL,PARSEFS_NONE) #else # define PARSE_FILE_SEQ(_s,_t,_c,_p,_f) \ (_t *)parse_file_seq ((_s),sizeof (_t),(_c),(_p),(_f), \ &PARSE_FILE_SEQ_IGNORE_ ## _t ## _cache) # define PARSE_SIMPLE_SEQ(_s,_t) \ (_t *)parse_file_seq ((_s),sizeof (_t),MAP_NUL,NULL,PARSEFS_NONE, \ &PARSE_FILE_SEQ_IGNORE_ ## _t ## _cache) # define PARSE_FILE_SEQ_IGNORE_struct #endif #ifdef VMS void *parse_file_seq (); #else void *parse_file_seq (char **stringp, unsigned int size, int stopmap, const char *prefix, int flags IF_WITH_ALLOC_CACHES_PARAM(struct alloccache *cache)); #endif char *tilde_expand (const char *name); #ifndef NO_ARCHIVES struct nameseq *ar_glob (const char *arname, const char *member_pattern, unsigned int size); #endif #define dep_name(d) ((d)->name ? (d)->name : (d)->file->name) #ifndef CONFIG_WITH_ALLOC_CACHES #define alloc_seq_elt(_t) xcalloc (sizeof (_t)) void free_ns_chain (struct nameseq *n); #if defined(MAKE_MAINTAINER_MODE) && defined(__GNUC__) /* Use inline to get real type-checking. */ #define SI static inline SI struct nameseq *alloc_ns() { return alloc_seq_elt (struct nameseq); } SI struct dep *alloc_dep() { return alloc_seq_elt (struct dep); } SI struct goaldep *alloc_goaldep() { return alloc_seq_elt (struct goaldep); } SI void free_ns(struct nameseq *n) { free (n); } SI void free_dep(struct dep *d) { free_ns ((struct nameseq *)d); } SI void free_goaldep(struct goaldep *g) { free_dep ((struct dep *)g); } SI void free_dep_chain(struct dep *d) { free_ns_chain((struct nameseq *)d); } SI void free_goal_chain(struct goaldep *g) { free_dep_chain((struct dep *)g); } #else # define alloc_ns() alloc_seq_elt (struct nameseq) # define alloc_dep() alloc_seq_elt (struct dep) # define alloc_goaldep() alloc_seq_elt (struct goaldep) # define free_ns(_n) free (_n) # define free_dep(_d) free_ns (_d) # define free_goaldep(_g) free_dep (_g) # define free_dep_chain(_d) free_ns_chain ((struct nameseq *)(_d)) # define free_goal_chain(_g) free_ns_chain ((struct nameseq *)(_g)) #endif #else /* CONFIG_WITH_ALLOC_CACHES */ # include K_INLINE struct nameseq *alloc_ns (void) { return (struct nameseq *)alloccache_calloc (&nameseq_cache); } K_INLINE void free_ns (struct nameseq *n) { alloccache_free (&nameseq_cache, n); } void free_ns_chain (struct nameseq *n); K_INLINE struct dep *alloc_dep (void) { return (struct dep *)alloccache_calloc (&dep_cache); } K_INLINE void free_dep (struct dep *d) { alloccache_free (&dep_cache, d); } void free_dep_chain (struct dep *d); K_INLINE struct goaldep *alloc_goaldep (void) { return (struct goaldep *)alloccache_calloc (&goaldep_cache); } K_INLINE void free_goaldep (struct goaldep *g) { alloccache_free (&goaldep_cache, g); } void free_goal_chain (struct goaldep *g); #endif /* CONFIG_WITH_ALLOC_CACHES */ struct dep *copy_dep_chain (const struct dep *d); struct goaldep *read_all_makefiles (const char **makefiles); void eval_buffer (char *buffer, const floc *floc IF_WITH_VALUE_LENGTH(COMMA char *eos)); enum update_status update_goal_chain (struct goaldep *goals); #ifdef CONFIG_WITH_INCLUDEDEP /* incdep.c */ enum incdep_op { incdep_read_it, incdep_queue, incdep_flush }; void eval_include_dep (const char *name, floc *f, enum incdep_op op); void incdep_flush_and_term (void); #endif kbuild-3686/src/kmk/loadapi.c0000664000175000017500000000412515053010075016040 0ustar locutuslocutus/* API for GNU Make dynamic objects. Copyright (C) 2013-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include "makeint.h" #include "filedef.h" #include "variable.h" #include "dep.h" /* Allocate a buffer in our context, so we can free it. */ char * gmk_alloc (unsigned int len) { return xmalloc (len); } /* Free a buffer returned by gmk_expand(). */ void gmk_free (char *s) { free (s); } /* Evaluate a buffer as make syntax. Ideally eval_buffer() will take const char *, but not yet. */ void gmk_eval (const char *buffer, const gmk_floc *gfloc) { /* Preserve existing variable buffer context. */ char *pbuf; unsigned int plen; char *s; floc fl; floc *flp; if (gfloc) { fl.filenm = gfloc->filenm; fl.lineno = gfloc->lineno; fl.offset = 0; flp = &fl; } else flp = NULL; install_variable_buffer (&pbuf, &plen); s = xstrdup (buffer); eval_buffer (s, flp IF_WITH_VALUE_LENGTH_PARAM (strchr (s, '\0') /** @todo suboptimal */)); free (s); restore_variable_buffer (pbuf, plen); } /* Expand a string and return an allocated buffer. Caller must call gmk_free() with this buffer. */ char * gmk_expand (const char *ref) { return allocated_variable_expand (ref); } /* Register a function to be called from makefiles. */ void gmk_add_function (const char *name, gmk_func_ptr func, unsigned int min, unsigned int max, unsigned int flags) { define_new_function (reading_file, name, min, max, flags, func); } kbuild-3686/src/kmk/Makefile.kmk0000664000175000017500000004203515053010074016505 0ustar locutuslocutus# $Id: Makefile.kmk 3671 2025-03-04 02:26:47Z bird $ ## @file # Sub-makefile for kmk / GNU Make. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild 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 3 of the License, or # (at your option) any later version. # # kBuild 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 kBuild. If not, see # # SUB_DEPTH = ../.. include $(KBUILD_PATH)/subheader.kmk # Enable new children handling for windows. CONFIG_NEW_WIN_CHILDREN = 1 # # Template for kmk and the kmk_* binaries in this makefile. # TEMPLATE_BIN-KMK = Template for src/gmake binaries TEMPLATE_BIN-KMK_EXTENDS = BIN-THREADED TEMPLATE_BIN-KMK_DEFS = \ HAVE_CONFIG_H \ $(TEMPLATE_BIN_DEFS) \ KBUILD_SVN_REV=$(KBUILD_SVN_REV) \ KBUILD_TYPE=$(TMP_QUOTE_SLASH)"$(KBUILD_TYPE)$(TMP_QUOTE_SLASH)" TEMPLATE_BIN-KMK_DEPS = \ $(kmk_0_OUTDIR)/config.h \ $(kmk_0_OUTDIR)/fts.h TEMPLATE_BIN-KMK_CLEAN = $(TEMPLATE_BIN-KMK_DEPS) TEMPLATE_BIN-KMK_DEPS.solaris = \ $(kmk_0_OUTDIR)/paths.h TEMPLATE_BIN-KMK_CLEAN.solaris = $(TEMPLATE_BIN-KMK_DEPS.solaris) TEMPLATE_BIN-KMK_DEPS.win = \ $(kmk_0_OUTDIR)/sysexits.h \ $(kmk_0_OUTDIR)/unistd.h \ $(kmk_0_OUTDIR)/paths.h \ $(kmk_0_OUTDIR)/grp.h \ $(kmk_0_OUTDIR)/pwd.h \ $(kmk_0_OUTDIR)/inttypes.h TEMPLATE_BIN-KMK_CFLAGS.win.amd64 = $(TEMPLATE_BIN-THREADED_CFLAGS.win.amd64) -wd4244 -wd4267 TEMPLATE_BIN-KMK_CLEAN.win = $(TEMPLATE_BIN-KMK_DEPS.win) TEMPLATE_BIN-KMK_DEFS.debug = $(TEMPLATE_BIN_DEFS.debug) MAKE_MAINTAINER_MODE TEMPLATE_BIN-KMK_INCS = $(kmk_0_OUTDIR) . $(TEMPLATE_BIN-THREADED_INCS) ifneq ($(KBUILD_TARGET),os2) TEMPLATE_BIN-KMK_INCS += glob endif TEMPLATE_BIN-KMK_LIBS = $(LIB_KUTIL) $(TEMPLATE_BIN-THREADED_LIBS) $(kmkmissing_1_TARGET) $(LIB_KUTIL) TEMPLATE_BIN-KMK_LIBS.x86 = $(LIB_KUTIL) $(TEMPLATE_BIN-THREADED_LIBS.x86) TEMPLATE_BIN-KMK_LIBS.amd64 = $(LIB_KUTIL) $(TEMPLATE_BIN-THREADED_LIBS.amd64) ifdef ELECTRIC_HEAP # for electric heap (see electric.c). ifeq ($(KBUILD_TARGET),win) TEMPLATE_BIN-KMK_CFLAGS = $(TEMPLATE_BIN-THREADED_CFLAGS) /FI$(kmk_DEFPATH)/electric.h -DELECTRIC_HEAP=1 else TEMPLATE_BIN-KMK_CFLAGS = $(TEMPLATE_BIN-THREADED_CFLAGS) -include $(kmk_DEFPATH)/electric.h -DELECTRIC_HEAP=1 endif endif ifdef CONFIG_WITH_ALLOCCACHE_DEBUG TEMPLATE_BIN-KMK_DEFS += CONFIG_WITH_ALLOCCACHE_DEBUG endif ifdef CONFIG_NEW_WIN_CHILDREN TEMPLATE_BIN-KMK_DEFS.win = $(TEMPLATE_BIN_DEFS.win) CONFIG_NEW_WIN_CHILDREN endif # GCC sanitizers. ifdef GCC_SANITIZERS TEMPLATE_BIN-KMK_CFLAGS ?= $(TEMPLATE_BIN-THREADED_CFLAGS) # TEMPLATE_BIN-KMK_CFLAGS += -fsanitize=address -fsanitize=undefined -static-libubsan -D GCC_ADDRESS_SANITIZER TEMPLATE_BIN-KMK_CFLAGS += -fsanitize=address -fsanitize=undefined -D GCC_ADDRESS_SANITIZER TEMPLATE_BIN-KMK_LDFLAGS ?= $(TEMPLATE_BIN-THREADED_LDFLAGS) TEMPLATE_BIN-KMK_LDFLAGS += -fsanitize=address -fsanitize=undefined endif # # Library version of the above. # TEMPLATE_LIB-KMK = Template for src/gmake libraries TEMPLATE_LIB-KMK_EXTENDS = BIN-KMK TEMPLATE_LIB-KMK_POST_CMDS.win = $(NO_SUCH_VARIABLE) # # Template for building standalone built-in utilities. # TEMPLATE_BIN-KMK-BUILTIN = Template for standalone built-in utilies. TEMPLATE_BIN-KMK-BUILTIN_EXTENDS = BIN-KMK TEMPLATE_BIN-KMK-BUILTIN_EXTENDS_BY = appending TEMPLATE_BIN-KMK-BUILTIN_DEFS += KMK_BUILTIN_STANDALONE TEMPLATE_BIN-KMK-BUILTIN_SOURCES += kmkbuiltin/err.c # # A library containing the missing features needed by kmk and the # kmk_* binaries. Saves a bit of work later on. # LIBRARIES += kmkmissing kmkmissing_TEMPLATE = LIB-KMK kmkmissing_DEFS = KMK kmkmissing_NOINST = 1 kmkmissing_SOURCES = \ kmkbuiltin/fts.c \ kmkbuiltin/setmode.c \ kmkbuiltin/strmode.c \ kmkbuiltin/kbuild_protection.c \ kmkbuiltin/common-env-and-cwd-opt.c \ kmkbuiltin/getopt_r.c \ kmkbuiltin/getopt1_r.c \ getopt.c \ getopt1.c \ electric.c ifneq ($(KBUILD_TARGET),os2) kmkmissing_SOURCES += \ glob/glob.c endif kmkmissing_SOURCES.darwin = \ kmkbuiltin/darwin.c \ glob/fnmatch.c kmkmissing_SOURCES.dragonfly = \ glob/fnmatch.c kmkmissing_SOURCES.freebsd = \ glob/fnmatch.c kmkmissing_SOURCES.gnuhurd += \ kmkbuiltin/strlcpy.c kmkmissing_SOURCES.gnukfbsd += \ kmkbuiltin/strlcpy.c kmkmissing_SOURCES.gnuknbsd += \ kmkbuiltin/strlcpy.c kmkmissing_SOURCES.haiku = \ kmkbuiltin/haikufakes.c \ glob/fnmatch.c kmkmissing_SOURCES.linux += \ kmkbuiltin/strlcpy.c kmkmissing_SOURCES.netbsd = \ glob/fnmatch.c kmkmissing_SOURCES.openbsd = \ kmkbuiltin/openbsd.c kmkmissing_SOURCES.solaris = \ kmkbuiltin/strlcpy.c \ kmkbuiltin/solfakes.c \ glob/fnmatch.c kmkmissing_SOURCES.win += \ kmkbuiltin/strlcpy.c \ kmkbuiltin/mscfakes.c \ glob/fnmatch.c \ getloadavg.c \ w32/subproc/misc.c \ w32/subproc/w32err.c \ w32/pathstuff.c \ w32/imagecache.c \ w32/compat/posixfcn.c # # kmk # PROGRAMS += kmk kmk_TEMPLATE = BIN-KMK kmk_DEFS = \ NO_ARCHIVES \ EXPERIMENTAL \ CONFIG_WITH_TOUPPER_TOLOWER \ CONFIG_WITH_DEFINED \ CONFIG_WITH_EXPLICIT_MULTITARGET \ CONFIG_WITH_DOT_MUST_MAKE \ CONFIG_WITH_PREPEND_ASSIGNMENT \ CONFIG_WITH_LOCAL_VARIABLES \ CONFIG_WITH_2ND_TARGET_EXPANSION \ CONFIG_WITH_ALLOC_CACHES \ CONFIG_WITH_STRCACHE2 \ \ KMK \ KMK_HELPERS \ CONFIG_NO_DEFAULT_SUFFIXES \ CONFIG_NO_DEFAULT_PATTERN_RULES \ CONFIG_NO_DEFAULT_TERMINAL_RULES \ CONFIG_NO_DEFAULT_SUFFIX_RULES \ CONFIG_NO_DEFAULT_VARIABLES \ \ CONFIG_WITH_ABSPATHEX \ CONFIG_WITH_COMMANDS_FUNC \ CONFIG_WITH_DATE \ CONFIG_WITH_DEFINED_FUNCTIONS \ CONFIG_WITH_EVALPLUS \ CONFIG_WITH_FILE_SIZE \ CONFIG_WITH_LOOP_FUNCTIONS \ CONFIG_WITH_MATH \ CONFIG_WITH_NANOTS \ CONFIG_WITH_ROOT_FUNC \ CONFIG_WITH_RSORT \ CONFIG_WITH_STACK \ CONFIG_WITH_STRING_FUNCTIONS \ CONFIG_WITH_WHERE_FUNCTION \ CONFIG_WITH_WHICH \ CONFIG_WITH_XARGS \ \ CONFIG_WITH_EXTENDED_NOTPARALLEL \ CONFIG_WITH_INCLUDEDEP \ CONFIG_WITH_VALUE_LENGTH \ CONFIG_WITH_COMPARE \ CONFIG_WITH_SET_CONDITIONALS \ CONFIG_WITH_IF_CONDITIONALS \ CONFIG_WITH_PRINTF \ CONFIG_WITH_MINIMAL_STATS \ \ CONFIG_PRETTY_COMMAND_PRINTING \ CONFIG_WITH_PRINT_STATS_SWITCH \ CONFIG_WITH_PRINT_TIME_SWITCH \ CONFIG_WITH_RDONLY_VARIABLE_VALUE \ CONFIG_WITH_LAZY_DEPS_VARS \ CONFIG_WITH_MEMORY_OPTIMIZATIONS \ \ KBUILD_HOST=$(TMP_QUOTE_SLASH)"$(KBUILD_TARGET)$(TMP_QUOTE_SLASH)" \ KBUILD_HOST_ARCH=$(TMP_QUOTE_SLASH)"$(KBUILD_TARGET_ARCH)$(TMP_QUOTE_SLASH)" \ KBUILD_HOST_CPU=$(TMP_QUOTE_SLASH)"$(KBUILD_TARGET_CPU)$(TMP_QUOTE_SLASH)" # kmk_DEFS += CONFIG_WITH_COMPILER # experimental, doesn't work 101% right it seems. kmk_DEFS.x86 := CONFIG_WITH_OPTIMIZATION_HACKS kmk_DEFS.amd64 := CONFIG_WITH_OPTIMIZATION_HACKS kmk_DEFS.win := CONFIG_WITH_OUTPUT_IN_MEMORY kmk_DEFS.win.x86 := CONFIG_NEW_WIN32_CTRL_EVENT kmk_DEFS.win.amd64 := CONFIG_NEW_WIN32_CTRL_EVENT kmk_DEFS.debug := CONFIG_WITH_MAKE_STATS ifdef CONFIG_WITH_MAKE_STATS kmk_DEFS += CONFIG_WITH_MAKE_STATS endif #ifdef CONFIG_WITH_KMK_BUILTIN_STATS kmk_DEFS += CONFIG_WITH_KMK_BUILTIN_STATS #endif ifdef CONFIG_WITH_EVAL_COMPILER kmk_DEFS += CONFIG_WITH_EVAL_COMPILER endif ifdef CONFIG_WITH_COMPILE_EVERYTHING kmk_DEFS += CONFIG_WITH_COMPILE_EVERYTHING endif #ifeq ($(KBUILD_TYPE).$(USERNAME),debug.bird) # kmk_DEFS += CONFIG_WITH_COMPILER CONFIG_WITH_EVAL_COMPILER CONFIG_WITH_COMPILE_EVERYTHING #endif kmk_SOURCES = \ main.c \ read.c \ hash.c \ strcache.c \ variable.c \ ar.c \ arscan.c \ commands.c \ default.c \ expand.c \ file.c \ function.c \ implicit.c \ job.c \ misc.c \ output.c \ remake.c \ rule.c \ signame.c \ version.c \ vpath.c \ remote-stub.c \ guile.c \ load.c \ \ alloccache.c \ expreval.c \ incdep.c \ strcache2.c \ kmk_cc_exec.c \ kbuild.c \ kbuild-object.c ifeq ($(KBUILD_TARGET),win) kmk_SOURCES += \ dir-nt-bird.c \ w32/w32os.c else kmk_SOURCES += \ dir.c \ posixos.c endif ifndef CONFIG_NEW_WIN_CHILDREN kmk_SOURCES.win = \ w32/subproc/sub_proc.c else kmk_SOURCES.win = \ w32/winchildren.c endif #kmk_DEFS.win += DEBUG_STDOUT_CLOSE_ISSUE kmk_SOURCES.win += ../lib/msc_buffered_printf.c kmk_DEFS.freebsd.x86 = CONFIG_WITHOUT_THREADS #kmk_LIBS.solaris = malloc #kmk_DEFS.solaris += HAVE_MALLINFO # # kmkbuiltin commands # kmk_DEFS += CONFIG_WITH_KMK_BUILTIN kmk_LIBS += $(LIB_KUTIL) #$(LIB_KDEP) kmk_SOURCES += \ kmkbuiltin.c \ kmkbuiltin/append.c \ kmkbuiltin/cat.c \ kmkbuiltin/chmod.c \ kmkbuiltin/cmp.c \ kmkbuiltin/cmp_util.c \ kmkbuiltin/cp.c \ kmkbuiltin/cp_utils.c \ kmkbuiltin/echo.c \ kmkbuiltin/expr.c \ kmkbuiltin/install.c \ kmkbuiltin/kDepIDB.c \ kmkbuiltin/kDepObj.c \ ../lib/kDep.c \ kmkbuiltin/md5sum.c \ kmkbuiltin/mkdir.c \ kmkbuiltin/mv.c \ kmkbuiltin/ln.c \ kmkbuiltin/printf.c \ kmkbuiltin/redirect.c \ kmkbuiltin/rm.c \ kmkbuiltin/rmdir.c \ $(if-expr $(KBUILD_TARGET) == win,kmkbuiltin/kSubmit.c) \ kmkbuiltin/sleep.c \ kmkbuiltin/test.c \ kmkbuiltin/touch.c \ \ kmkbuiltin/err.c kmk_SOURCES.win += \ kmkbuiltin/kill.c ## @todo kmkbuiltin/redirect.c ## Some profiling #kmk_SOURCES += kbuildprf.c #kmk_DEFS += open=prf_open read=prf_read lseek=prf_lseek close=prf_close ##kmk_DEFS += KMK_PRF=1 ##kmkmissing_DEFS += KMK_PRF=1 # # Standalone kmkbuiltin commands. # PROGRAMS += \ kmk_append \ kmk_cat \ kmk_chmod \ kmk_cp \ kmk_cmp \ kmk_echo \ kmk_expr \ kmk_md5sum \ kmk_mkdir \ kmk_mv \ kmk_install \ kmk_ln \ kmk_printf \ kmk_redirect \ kmk_rm \ kmk_rmdir \ kmk_sleep \ kmk_test \ kmk_touch \ kDepIDB \ kDepObj PROGRAMS.win += \ kmk_kill kmk_append_TEMPLATE = BIN-KMK-BUILTIN kmk_append_INCS = . kmk_append_SOURCES = \ kmkbuiltin/append.c kmk_cat_TEMPLATE = BIN-KMK-BUILTIN kmk_cat_SOURCES = \ kmkbuiltin/cat.c kmk_chmod_TEMPLATE = BIN-KMK-BUILTIN kmk_chmod_SOURCES = \ kmkbuiltin/chmod.c kmk_cmp_TEMPLATE = BIN-KMK-BUILTIN kmk_cmp_SOURCES = \ kmkbuiltin/cmp.c \ kmkbuiltin/cmp_util.c kmk_cp_TEMPLATE = BIN-KMK-BUILTIN kmk_cp_SOURCES = \ kmkbuiltin/cp.c \ kmkbuiltin/cp_utils.c \ kmkbuiltin/cmp_util.c kmk_echo_TEMPLATE = BIN-KMK-BUILTIN kmk_echo_SOURCES = \ kmkbuiltin/echo.c kmk_expr_TEMPLATE = BIN-KMK-BUILTIN kmk_expr_SOURCES = \ kmkbuiltin/expr.c kmk_install_TEMPLATE = BIN-KMK-BUILTIN kmk_install_SOURCES = \ kmkbuiltin/install.c kmk_kill_TEMPLATE = BIN-KMK-BUILTIN kmk_kill_SOURCES = \ kmkbuiltin/kill.c kmk_ln_TEMPLATE = BIN-KMK-BUILTIN kmk_ln_SOURCES = \ kmkbuiltin/ln.c kmk_mkdir_TEMPLATE = BIN-KMK-BUILTIN kmk_mkdir_SOURCES = \ kmkbuiltin/mkdir.c kmk_md5sum_TEMPLATE = BIN-KMK-BUILTIN kmk_md5sum_SOURCES = \ kmkbuiltin/md5sum.c kmk_md5sum_LIBS = $(LIB_KUTIL) kmk_mv_TEMPLATE = BIN-KMK-BUILTIN kmk_mv_SOURCES = \ kmkbuiltin/mv.c kmk_printf_TEMPLATE = BIN-KMK-BUILTIN kmk_printf_SOURCES = \ kmkbuiltin/printf.c kmk_rm_TEMPLATE = BIN-KMK-BUILTIN kmk_rm_SOURCES = \ kmkbuiltin/rm.c kmk_redirect_TEMPLATE = BIN-KMK-BUILTIN kmk_redirect_SOURCES = \ kmkbuiltin/redirect.c kmk_redirect_SOURCES.win = \ ../lib/startuphacks-win.c kmk_rmdir_TEMPLATE = BIN-KMK-BUILTIN kmk_rmdir_SOURCES = \ kmkbuiltin/rmdir.c kmk_sleep_TEMPLATE = BIN-KMK-BUILTIN kmk_sleep_SOURCES = \ kmkbuiltin/sleep.c kmk_test_TEMPLATE = BIN-KMK-BUILTIN kmk_test_SOURCES = \ kmkbuiltin/test.c kmk_touch_TEMPLATE = BIN-KMK-BUILTIN kmk_touch_SOURCES = \ kmkbuiltin/touch.c kDepIDB_TEMPLATE = BIN-KMK-BUILTIN kDepIDB_INCS = . kDepIDB_LIBS = $(LIB_KDEP) $(LIB_KUTIL) kDepIDB_SOURCES = \ kmkbuiltin/kDepIDB.c kDepObj_TEMPLATE = BIN-KMK-BUILTIN kDepObj_INCS = . kDepObj_LIBS = $(LIB_KDEP) $(LIB_KUTIL) kDepObj_SOURCES = \ kmkbuiltin/kDepObj.c # # kmk_gmake - almost plain GNU Make. # PROGRAMS += kmk_gmake kmk_gmake_TEMPLATE = BIN-KMK kmk_gmake_DEFS = \ HAVE_CONFIG_H \ CONFIG_WITH_TOUPPER_TOLOWER \ EXPERIMENTAL # NO_ARCHIVES kmk_gmake_SOURCES = \ main.c \ read.c \ hash.c \ strcache.c \ variable.c \ ar.c \ arscan.c \ commands.c \ default.c \ dir.c \ expand.c \ file.c \ function.c \ implicit.c \ job.c \ misc.c \ output.c \ remake.c \ rule.c \ signame.c \ version.c \ vpath.c \ remote-stub.c \ guile.c \ load.c ifeq ($(KBUILD_TARGET),win) kmk_gmake_SOURCES += \ w32/w32os.c else kmk_gmake_SOURCES += \ posixos.c endif ifndef CONFIG_NEW_WIN_CHILDREN kmk_gmake_SOURCES.win = \ w32/subproc/sub_proc.c else kmk_gmake_SOURCES.win = \ w32/winchildren.c endif # # kmk_fmake - Faster GNU Make. # ifeq ($(USER),bird) # for experimental purposes only. PROGRAMS += kmk_fgmake endif kmk_fgmake_TEMPLATE = BIN-KMK kmk_fgmake_DEFS = \ HAVE_CONFIG_H \ NO_ARCHIVES \ CONFIG_WITH_TOUPPER_TOLOWER \ EXPERIMENTAL \ \ CONFIG_WITH_ALLOC_CACHES \ CONFIG_WITH_LAZY_DEPS_VARS \ CONFIG_WITH_STRCACHE2 \ CONFIG_WITH_VALUE_LENGTH \ CONFIG_WITH_RDONLY_VARIABLE_VALUE # TODO ? # CONFIG_WITH_PRINT_STATS_SWITCH \ # CONFIG_WITH_EXTENDED_NOTPARALLEL \ kmk_fgmake_SOURCES = \ main.c \ read.c \ hash.c \ strcache.c \ strcache2.c \ variable.c \ ar.c \ arscan.c \ commands.c \ default.c \ dir.c \ expand.c \ file.c \ function.c \ implicit.c \ job.c \ misc.c \ output.c \ alloccache.c \ remake.c \ rule.c \ signame.c \ version.c \ vpath.c \ remote-stub.c \ guile.c \ load.c ifeq ($(KBUILD_TARGET),win) kmk_fgmake_SOURCES += \ w32/w32os.c # @todo: dir-nt-bird.c for fgmake else kmk_fgmake_SOURCES += \ posixos.c endif kmk_fgmake_SOURCES.win = \ w32/subproc/sub_proc.c # # tstFileInfo # PROGRAMS.win += tstFileInfo tstFileInfo_TEMPLATE = BIN tstFileInfo_SOURCES = w32/tstFileInfo.c # # tstFileInfo # PROGRAMS.win += tstFtsFake tstFtsFake_TEMPLATE = BIN-KMK tstFtsFake_NOINST = 1 tstFtsFake_DEFS = USE_OLD_FTS tstFtsFake_SOURCES = ../lib/nt/tstNtFts.c include $(FILE_KBUILD_SUB_FOOTER) # # Use checked in config.h instead of running ./Configure for it. # kmk_config.h.$(KBUILD_TARGET) := $(kmk_DEFPATH)/config.h.$(KBUILD_TARGET) $(kmk_0_OUTDIR)/config.h: $(kmk_config.h.$(KBUILD_TARGET)) $(MKDIR) -p $(dir $@) $(CP) $^ $@ # # Some missing headers. # if1of ($(KBUILD_TARGET), win nt) $(kmk_0_OUTDIR)/fts.h: $(MAKEFILE) | $(call DIRDEP,$(kmk_0_OUTDIR)) $(APPEND) -t "$@" "#include " else $(kmk_0_OUTDIR)/fts.h: $(kmk_DEFPATH)/kmkbuiltin/ftsfake.h | $(call DIRDEP,$(kmk_0_OUTDIR)) $(CP) $^ $@ endif $(kmk_0_OUTDIR)/unistd.h: | $(call DIRDEP,$(kmk_0_OUTDIR)) $(ECHO_EXT) > $@ $(kmk_0_OUTDIR)/sysexits.h: | $(call DIRDEP,$(kmk_0_OUTDIR)) $(ECHO_EXT) > $@ $(kmk_0_OUTDIR)/inttypes.h: | $(call DIRDEP,$(kmk_0_OUTDIR)) $(ECHO_EXT) > $@ $(kmk_0_OUTDIR)/paths.h: | $(call DIRDEP,$(kmk_0_OUTDIR)) $(ECHO_EXT) > $@ $(kmk_0_OUTDIR)/pwd.h: | $(call DIRDEP,$(kmk_0_OUTDIR)) $(ECHO_EXT) > $@ $(kmk_0_OUTDIR)/grp.h: | $(call DIRDEP,$(kmk_0_OUTDIR)) $(ECHO_EXT) > $@ # # Some tests. # parallel: parallel_1 parallel_2 parallel_3 parallel_4 parallel_5 parallel_1 parallel_2 parallel_3 parallel_4 parallel_5: echo $@_start ; sleep 1; echo $@_done my_test: echo "1" echo "2" echo "3" echo "4" # # Shell execution tests. # test_shell: test_shell_quoting test_shell_double_quoting test_shell_newline # shell double and single quoting check (was busted on windows in 3.81). test_shell_quoting: $(ECHO_EXT) "double quoted sTrInG" $(ECHO_EXT) "double quoted sTrInG" | $(SED_EXT) -e "s/sTrInG/string/g" $(ECHO_EXT) 'single quoted sTrInG' | $(SED_EXT) -e 's/sTrInG/string/g' $(ECHO) "This string should not be printed with double quotes." $(ECHO) 'This string should not be printed with single quotes.' ( echo " #define PWD \"`pwd`\""; ) test_shell_double_quoting: $(ECHO_EXT) "foo foo foo" | $(SED_EXT) -e \ "s/foo/$@/" -e \ "s/foo/works/" \ -e "s/foo/\!/" test_shell_double_quoting2: $(ECHO_EXT) "foo foo foo" | $(SED_EXT) -e \ "s/foo/$@/" -e \ "s/foo/works/" \ -e\ "s/foo/\!/" # when using batch mode shell, the newline got escaped twice and spoiling everything. test_shell_newline: $(ECHO_EXT) "foo foo foo" | $(SED_EXT) -e \ 's/foo/$@/' -e \ 's/foo/works/' \ -e 's/foo/\!/' test_stack: $(MAKE) -f $(kmk_DEFPATH)/testcase-stack.kmk test_math: $(MAKE) -f $(kmk_DEFPATH)/testcase-math.kmk test_if1of: $(MAKE) -f $(kmk_DEFPATH)/testcase-if1of.kmk test_local: $(MAKE) -f $(kmk_DEFPATH)/testcase-local.kmk test_includedep: $(MAKE) -f $(kmk_DEFPATH)/testcase-includedep.kmk test_root: $(MAKE) -f $(kmk_DEFPATH)/testcase-root.kmk test_2ndtargetexp: $(MAKE) -f $(kmk_DEFPATH)/testcase-2ndtargetexp.kmk test_30_continued_on_failure_worker: this_executable_does_not_exist.exe echo "We shouldn't see this..." test_30_continued_on_failure: $(MAKE) -f $(MAKEFILE) test_30_continued_on_failure_worker; \ RC=$$?; \ if test $${RC} -ne 2; then \ echo "$@: FAILED - exit code $${RC} instead of 2."; \ exit 1; \ else \ echo "$@: SUCCESS"; \ fi test_lazy_deps_vars: $(MAKE) -C $(kmk_DEFPATH) -f testcase-lazy-deps-vars.kmk test_all: \ test_math \ test_stack \ test_shell \ test_if1of \ test_local \ test_root \ test_includedep \ test_2ndtargetexp \ test_30_continued_on_failure \ test_lazy_deps_vars kbuild-3686/src/kmk/ar.c0000664000175000017500000002044715053010075015036 0ustar locutuslocutus/* Interface to 'ar' archives for GNU Make. Copyright (C) 1988-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include "makeint.h" #ifndef NO_ARCHIVES #include "filedef.h" #include "dep.h" #include /* Return nonzero if NAME is an archive-member reference, zero if not. An archive-member reference is a name like 'lib(member)' where member is a non-empty string. If a name like 'lib((entry))' is used, a fatal error is signaled at the attempt to use this unsupported feature. */ int ar_name (const char *name) { const char *p = strchr (name, '('); const char *end; if (p == 0 || p == name) return 0; end = p + strlen (p) - 1; if (*end != ')' || end == p + 1) return 0; if (p[1] == '(' && end[-1] == ')') OS (fatal, NILF, _("attempt to use unsupported feature: '%s'"), name); return 1; } /* Parse the archive-member reference NAME into the archive and member names. Creates one allocated string containing both names, pointed to by ARNAME_P. MEMNAME_P points to the member. */ void ar_parse_name (const char *name, char **arname_p, char **memname_p) { char *p; *arname_p = xstrdup (name); p = strchr (*arname_p, '('); *(p++) = '\0'; p[strlen (p) - 1] = '\0'; *memname_p = p; } /* This function is called by 'ar_scan' to find which member to look at. */ /* ARGSUSED */ static long int ar_member_date_1 (int desc UNUSED, const char *mem, int truncated, long int hdrpos UNUSED, long int datapos UNUSED, long int size UNUSED, long int date, int uid UNUSED, int gid UNUSED, unsigned int mode UNUSED, const void *name) { return ar_name_equal (name, mem, truncated) ? date : 0; } /* Return the modtime of NAME. */ time_t ar_member_date (const char *name) { char *arname; char *memname; long int val; ar_parse_name (name, &arname, &memname); /* Make sure we know the modtime of the archive itself because we are likely to be called just before commands to remake a member are run, and they will change the archive itself. But we must be careful not to enter_file the archive itself if it does not exist, because pattern_search assumes that files found in the data base exist or can be made. */ { struct file *arfile; arfile = lookup_file (arname); if (arfile == 0 && file_exists_p (arname)) arfile = enter_file (strcache_add (arname)); if (arfile != 0) (void) f_mtime (arfile, 0); } val = ar_scan (arname, ar_member_date_1, memname); free (arname); return (val <= 0 ? (time_t) -1 : (time_t) val); } /* Set the archive-member NAME's modtime to now. */ #ifdef VMS int ar_touch (const char *name) { O (error, NILF, _("touch archive member is not available on VMS")); return -1; } #else int ar_touch (const char *name) { char *arname, *memname; int val; ar_parse_name (name, &arname, &memname); /* Make sure we know the modtime of the archive itself before we touch the member, since this will change the archive modtime. */ { struct file *arfile; arfile = enter_file (strcache_add (arname)); f_mtime (arfile, 0); } val = 1; switch (ar_member_touch (arname, memname)) { case -1: OS (error, NILF, _("touch: Archive '%s' does not exist"), arname); break; case -2: OS (error, NILF, _("touch: '%s' is not a valid archive"), arname); break; case -3: perror_with_name ("touch: ", arname); break; case 1: OSS (error, NILF, _("touch: Member '%s' does not exist in '%s'"), memname, arname); break; case 0: val = 0; break; default: OS (error, NILF, _("touch: Bad return code from ar_member_touch on '%s'"), name); } free (arname); return val; } #endif /* !VMS */ /* State of an 'ar_glob' run, passed to 'ar_glob_match'. */ /* On VMS, (object) modules in libraries do not have suffixes. That is, to find a match for a pattern, the pattern must not have any suffix. So the suffix of the pattern is saved and the pattern is stripped (ar_glob). If there is a match and the match, which is a module name, is added to the chain, the saved suffix is added back to construct a source filename (ar_glob_match). */ struct ar_glob_state { const char *arname; const char *pattern; #ifdef VMS char *suffix; #endif unsigned int size; struct nameseq *chain; unsigned int n; }; /* This function is called by 'ar_scan' to match one archive element against the pattern in STATE. */ static long int ar_glob_match (int desc UNUSED, const char *mem, int truncated UNUSED, long int hdrpos UNUSED, long int datapos UNUSED, long int size UNUSED, long int date UNUSED, int uid UNUSED, int gid UNUSED, unsigned int mode UNUSED, const void *arg) { struct ar_glob_state *state = (struct ar_glob_state *)arg; if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0) { /* We have a match. Add it to the chain. */ struct nameseq *new = xcalloc (state->size); #ifdef VMS if (state->suffix) new->name = strcache_add( concat(5, state->arname, "(", mem, state->suffix, ")")); else #endif new->name = strcache_add(concat(4, state->arname, "(", mem, ")")); new->next = state->chain; state->chain = new; ++state->n; } return 0L; } /* Return nonzero if PATTERN contains any metacharacters. Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ static int ar_glob_pattern_p (const char *pattern, int quote) { const char *p; int opened = 0; for (p = pattern; *p != '\0'; ++p) switch (*p) { case '?': case '*': return 1; case '\\': if (quote) ++p; break; case '[': opened = 1; break; case ']': if (opened) return 1; break; } return 0; } /* Glob for MEMBER_PATTERN in archive ARNAME. Return a malloc'd chain of matching elements (or nil if none). */ struct nameseq * ar_glob (const char *arname, const char *member_pattern, unsigned int size) { struct ar_glob_state state; struct nameseq *n; const char **names; unsigned int i; #ifdef VMS char *vms_member_pattern; #endif if (! ar_glob_pattern_p (member_pattern, 1)) return 0; /* Scan the archive for matches. ar_glob_match will accumulate them in STATE.chain. */ state.arname = arname; state.pattern = member_pattern; #ifdef VMS { /* In a copy of the pattern, find the suffix, save it and remove it from the pattern */ char *lastdot; vms_member_pattern = xstrdup(member_pattern); lastdot = strrchr(vms_member_pattern, '.'); state.suffix = lastdot; if (lastdot) { state.suffix = xstrdup(lastdot); *lastdot = 0; } state.pattern = vms_member_pattern; } #endif state.size = size; state.chain = 0; state.n = 0; ar_scan (arname, ar_glob_match, &state); #ifdef VMS /* Deallocate any duplicated string */ free(vms_member_pattern); if (state.suffix) { free(state.suffix); } #endif if (state.chain == 0) return 0; /* Now put the names into a vector for sorting. */ names = alloca (state.n * sizeof (const char *)); i = 0; for (n = state.chain; n != 0; n = n->next) names[i++] = n->name; /* Sort them alphabetically. */ /* MSVC erroneously warns without a cast here. */ qsort ((void *)names, i, sizeof (*names), alpha_compare); /* Put them back into the chain in the sorted order. */ i = 0; for (n = state.chain; n != 0; n = n->next) n->name = names[i++]; return state.chain; } #endif /* Not NO_ARCHIVES. */ kbuild-3686/src/kmk/po/0000775000175000017500000000000015053010075014677 5ustar locutuslocutuskbuild-3686/src/kmk/po/.gitignore0000664000175000017500000000030415053010075016664 0ustar locutuslocutusMakefile.in.in Makevars.template POTFILES Rules-quot boldquot.sed en@boldquot.header en@quot.header insert-header.sin make.pot quot.sed remove-potcdate.sin remove-potcdate.sed stamp-po *.gmo *.po kbuild-3686/src/kmk/po/POTFILES.in0000664000175000017500000000203715053010075016456 0ustar locutuslocutus# List of source files containing translatable strings. # Copyright (C) 2000-2016 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) any later # version. # # GNU Make 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, see . ar.c arscan.c commands.c dir.c expand.c file.c function.c getopt.c guile.c hash.c implicit.c job.c job.h kbuild.c load.c main.c misc.c output.c posixos.c read.c remake.c remote-cstms.c rule.c signame.c strcache.c variable.c variable.h vmsfunctions.c vmsjobs.c vpath.c w32/w32os.c kbuild-3686/src/kmk/po/LINGUAS0000664000175000017500000000027515053010075015730 0ustar locutuslocutus# Set of available languages: 25 languages be cs da de es fi fr ga gl he hr id it ja ko lt nl pl pt_BR ru sv tr uk vi zh_CN # Can't seem to get en@quot and en@boldquot to build properly? kbuild-3686/src/kmk/po/Makevars0000664000175000017500000000501215053010075016371 0ustar locutuslocutus# This is a -*-Makefile-*- # Copyright (C) 2002-2016 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) # any later version. # # GNU Make 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, see . # Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = $(PACKAGE) # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = Free Software Foundation, Inc. # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = bug-make@gnu.org # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = kbuild-3686/src/kmk/remote-cstms.c0000664000175000017500000002057215053010075017055 0ustar locutuslocutus/* GNU Make remote job exportation interface to the Customs daemon. THIS CODE IS NOT SUPPORTED BY THE GNU PROJECT. Please do not send bug reports or questions about it to the Make maintainers. Copyright (C) 1988-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include "makeint.h" #include "filedef.h" #include "commands.h" #include "job.h" #include "debug.h" #include #include #include "customs.h" char *remote_description = "Customs"; /* File name of the Customs 'export' client command. A full path name can be used to avoid some path-searching overhead. */ #define EXPORT_COMMAND "/usr/local/bin/export" /* ExportPermit gotten by start_remote_job_p, and used by start_remote_job. */ static ExportPermit permit; /* Normalized path name of the current directory. */ static char *normalized_cwd; /* Call once at startup even if no commands are run. */ void remote_setup (void) { } /* Called before exit. */ void remote_cleanup (void) { } /* Return nonzero if the next job should be done remotely. */ int start_remote_job_p (int first_p) { static int inited = 0; int status; int njobs; if (!inited) { /* Allow the user to turn off job exportation (useful while he is debugging Customs, for example). */ if (getenv ("GNU_MAKE_NO_CUSTOMS") != 0) { inited = -1; return 0; } /* For secure Customs, make is installed setuid root and Customs requires a privileged source port be used. */ make_access (); if (ISDB (DB_JOBS)) Rpc_Debug (1); /* Ping the daemon once to see if it is there. */ inited = Customs_Ping () == RPC_SUCCESS ? 1 : -1; /* Return to normal user access. */ user_access (); if (starting_directory == 0) /* main couldn't figure it out. */ inited = -1; else { /* Normalize the current directory path name to something that should work on all machines exported to. */ normalized_cwd = xmalloc (GET_PATH_MAX); strcpy (normalized_cwd, starting_directory); if (Customs_NormPath (normalized_cwd, GET_PATH_MAX) < 0) /* Path normalization failure means using Customs won't work, but it's not really an error. */ inited = -1; } } if (inited < 0) return 0; njobs = job_slots_used; if (!first_p) njobs -= 1; /* correction for being called from reap_children() */ /* the first job should run locally, or, if the -l flag is given, we use that as clue as to how many local jobs should be scheduled locally */ if (max_load_average < 0 && njobs == 0 || njobs < max_load_average) return 0; status = Customs_Host (EXPORT_SAME, &permit); if (status != RPC_SUCCESS) { DB (DB_JOBS, (_("Customs won't export: %s\n"), Rpc_ErrorMessage (status))); return 0; } return !CUSTOMS_FAIL (&permit.addr); } /* Start a remote job running the command in ARGV, with environment from ENVP. It gets standard input from STDIN_FD. On failure, return nonzero. On success, return zero, and set *USED_STDIN to nonzero if it will actually use STDIN_FD, zero if not, set *ID_PTR to a unique identification, and set *IS_REMOTE to nonzero if the job is remote, zero if it is local (meaning *ID_PTR is a process ID). */ int start_remote_job (char **argv, char **envp, int stdin_fd, int *is_remote, int *id_ptr, int *used_stdin) { char waybill[MAX_DATA_SIZE], msg[128]; struct hostent *host; struct timeval timeout; struct sockaddr_in sin; int len; int retsock, retport, sock; Rpc_Stat status; int pid; /* Create the return socket. */ retsock = Rpc_UdpCreate (True, 0); if (retsock < 0) { O (error, NILF, "exporting: Couldn't create return socket."); return 1; } /* Get the return socket's port number. */ len = sizeof (sin); if (getsockname (retsock, (struct sockaddr *) &sin, &len) < 0) { (void) close (retsock); perror_with_name ("exporting: ", "getsockname"); return 1; } retport = sin.sin_port; /* Create the TCP socket for talking to the remote child. */ sock = Rpc_TcpCreate (False, 0); /* Create a WayBill to give to the server. */ len = Customs_MakeWayBill (&permit, normalized_cwd, argv[0], argv, envp, retport, waybill); /* Modify the waybill as if the remote child had done 'child_access ()'. */ { WayBill *wb = (WayBill *) waybill; wb->ruid = wb->euid; wb->rgid = wb->egid; } /* Send the request to the server, timing out in 20 seconds. */ timeout.tv_usec = 0; timeout.tv_sec = 20; sin.sin_family = AF_INET; sin.sin_port = htons (Customs_Port ()); sin.sin_addr = permit.addr; status = Rpc_Call (sock, &sin, (Rpc_Proc) CUSTOMS_IMPORT, len, (Rpc_Opaque) waybill, sizeof (msg), (Rpc_Opaque) msg, 1, &timeout); host = gethostbyaddr ((char *)&permit.addr, sizeof(permit.addr), AF_INET); { const char *hnm = host ? host->h_name : inet_ntoa (permit.addr); size_t hlen = strlen (hnm); if (status != RPC_SUCCESS) { const char *err = Rpc_ErrorMessage (status); (void) close (retsock); (void) close (sock); error (NILF, hlen + strlen (err), "exporting to %s: %s", hnm, err); return 1; } else if (msg[0] != 'O' || msg[1] != 'k' || msg[2] != '\0') { (void) close (retsock); (void) close (sock); error (NILF, hlen + strlen (msg), "exporting to %s: %s", hnm, msg); return 1; } else { error (NILF, hlen + INTSTR_LENGTH, "*** exported to %s (id %u)", hnm, permit.id); } fflush (stdout); fflush (stderr); } pid = vfork (); if (pid < 0) { /* The fork failed! */ perror_with_name ("fork", ""); return 1; } else if (pid == 0) { /* Child side. Run 'export' to handle the connection. */ static char sock_buf[20], retsock_buf[20], id_buf[20]; static char *new_argv[6] = { EXPORT_COMMAND, "-id", sock_buf, retsock_buf, id_buf, 0 }; /* Set up the arguments. */ (void) sprintf (sock_buf, "%d", sock); (void) sprintf (retsock_buf, "%d", retsock); (void) sprintf (id_buf, "%x", permit.id); /* Get the right stdin. */ if (stdin_fd != 0) (void) dup2 (stdin_fd, 0); /* Unblock signals in the child. */ unblock_sigs (); /* Run the command. */ exec_command (new_argv, envp); } /* Parent side. Return the 'export' process's ID. */ (void) close (retsock); (void) close (sock); *is_remote = 0; *id_ptr = pid; *used_stdin = 1; return 0; } /* Get the status of a dead remote child. Block waiting for one to die if BLOCK is nonzero. Set *EXIT_CODE_PTR to the exit status, *SIGNAL_PTR to the termination signal or zero if it exited normally, and *COREDUMP_PTR nonzero if it dumped core. Return the ID of the child that died, 0 if we would have to block and !BLOCK, or < 0 if there were none. */ int remote_status (int *exit_code_ptr, int *signal_ptr, int *coredump_ptr, int block) { return -1; } /* Block asynchronous notification of remote child death. If this notification is done by raising the child termination signal, do not block that signal. */ void block_remote_children (void) { return; } /* Restore asynchronous notification of remote child death. If this is done by raising the child termination signal, do not unblock that signal. */ void unblock_remote_children (void) { return; } /* Send signal SIG to child ID. Return 0 if successful, -1 if not. */ int remote_kill (int id, int sig) { return -1; } kbuild-3686/src/kmk/make.lnk0000664000175000017500000000056415053010075015711 0ustar locutuslocutusFROM LIB:cres.o "commands.o"+"job.o"+"dir.o"+"file.o"+"misc.o"+"main.o"+"read.o"+"remake.o"+"rule.o"+"implicit.o"+"default.o"+"variable.o"+"expand.o"+"function.o"+"vpath.o"+"version.o"+"ar.o"+"arscan.o"+"signame.o"+"remote-stub.o"+"getopt.o"+"getopt1.o"+"alloca.o"+"amiga.o"+"hash.o"+"strcache.o"+"output.o" TO "make.new" LIB glob/glob.lib LIB:sc.lib LIB:amiga.lib QUIET kbuild-3686/src/kmk/getloadavg.c0000664000175000017500000006260615053010075016554 0ustar locutuslocutus/* Get the system load averages. Copyright (C) 1985-2016 Free Software Foundation, Inc. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ /* Compile-time symbols that this file uses: HAVE_PSTAT_GETDYNAMIC Define this if your system has the pstat_getdynamic function. I think it is unique to HPUX9. The best way to get the definition is through the AC_FUNC_GETLOADAVG macro that comes with autoconf 2.13 or newer. If that isn't an option, then just put AC_CHECK_FUNCS(pstat_getdynamic) in your configure.in file. FIXUP_KERNEL_SYMBOL_ADDR() Adjust address in returned struct nlist. KERNEL_FILE Pathname of the kernel to nlist. LDAV_CVT() Scale the load average from the kernel. Returns a double. LDAV_SYMBOL Name of kernel symbol giving load average. LOAD_AVE_TYPE Type of the load average array in the kernel. Must be defined unless one of apollo, DGUX, NeXT, or UMAX is defined; or we have libkstat; otherwise, no load average is available. NLIST_STRUCT Include nlist.h, not a.out.h, and the nlist n_name element is a pointer, not an array. HAVE_STRUCT_NLIST_N_UN_N_NAME struct nlist has an n_un member, not n_name. LINUX_LDAV_FILE [__linux__]: File containing load averages. Specific system predefines this file uses, aside from setting default values if not emacs: apollo BSD Real BSD, not just BSD-like. convex DGUX eunice UNIX emulator under VMS. hpux __MSDOS__ No-op for MSDOS. NeXT sgi sequent Sequent Dynix 3.x.x (BSD) _SEQUENT_ Sequent DYNIX/ptx 1.x.x (SYSV) sony_news NEWS-OS (works at least for 4.1C) UMAX UMAX4_3 VMS WINDOWS32 No-op for Windows95/NT. __linux__ Linux: assumes /proc filesystem mounted. Support from Michael K. Johnson. __NetBSD__ NetBSD: assumes /kern filesystem mounted. In addition, to avoid nesting many #ifdefs, we internally set LDAV_DONE to indicate that the load average has been computed. We also #define LDAV_PRIVILEGED if a program will require special installation to be able to call getloadavg. */ /* This should always be first. */ #ifdef HAVE_CONFIG_H # include #endif #include /* Both the Emacs and non-Emacs sections want this. Some configuration files' definitions for the LOAD_AVE_CVT macro (like sparc.h's) use macros like FSCALE, defined here. */ #if defined (unix) || defined (__unix) # include #endif /* Exclude all the code except the test program at the end if the system has its own 'getloadavg' function. The declaration of 'errno' is needed by the test program as well as the function itself, so it comes first. */ #include #ifndef errno extern int errno; #endif #if HAVE_LOCALE_H # include #endif #if !HAVE_SETLOCALE # define setlocale(Category, Locale) /* empty */ #endif #ifndef HAVE_GETLOADAVG /* The existing Emacs configuration files define a macro called LOAD_AVE_CVT, which accepts a value of type LOAD_AVE_TYPE, and returns the load average multiplied by 100. What we actually want is a macro called LDAV_CVT, which returns the load average as an unmultiplied double. For backwards compatibility, we'll define LDAV_CVT in terms of LOAD_AVE_CVT, but future machine config files should just define LDAV_CVT directly. */ # if !defined(LDAV_CVT) && defined(LOAD_AVE_CVT) # define LDAV_CVT(n) (LOAD_AVE_CVT (n) / 100.0) # endif # if !defined (BSD) && defined (ultrix) /* Ultrix behaves like BSD on Vaxen. */ # define BSD # endif # ifdef NeXT /* NeXT in the 2.{0,1,2} releases defines BSD in , which conflicts with the definition understood in this file, that this really is BSD. */ # undef BSD /* NeXT defines FSCALE in . However, we take FSCALE being defined to mean that the nlist method should be used, which is not true. */ # undef FSCALE # endif /* Same issues as for NeXT apply to the HURD-based GNU system. */ # ifdef __GNU__ # undef BSD # undef FSCALE # endif /* __GNU__ */ /* Set values that are different from the defaults, which are set a little farther down with #ifndef. */ /* Some shorthands. */ # if defined (HPUX) && !defined (hpux) # define hpux # endif # if defined (__hpux) && !defined (hpux) # define hpux # endif # if defined (__sun) && !defined (sun) # define sun # endif # if defined(hp300) && !defined(hpux) # define MORE_BSD # endif # if defined(ultrix) && defined(mips) # define decstation # endif # if defined (__SVR4) && !defined (SVR4) # define SVR4 # endif # if (defined(sun) && defined(SVR4)) || defined (SOLARIS2) # define SUNOS_5 # endif # if defined (__osf__) && (defined (__alpha) || defined (__alpha__)) # define OSF_ALPHA # include # include # include # include # endif # if defined (__osf__) && (defined (mips) || defined (__mips__)) # define OSF_MIPS # include # endif /* UTek's /bin/cc on the 4300 has no architecture specific cpp define by default, but _MACH_IND_SYS_TYPES is defined in . Combine that with a couple of other things and we'll have a unique match. */ # if !defined (tek4300) && defined (unix) && defined (m68k) && defined (mc68000) && defined (mc68020) && defined (_MACH_IND_SYS_TYPES) # define tek4300 /* Define by emacs, but not by other users. */ # endif /* AC_FUNC_GETLOADAVG thinks QNX is SVR4, but it isn't. */ # if defined(__QNX__) # undef SVR4 # endif /* VAX C can't handle multi-line #ifs, or lines longer than 256 chars. */ # ifndef LOAD_AVE_TYPE # ifdef MORE_BSD # define LOAD_AVE_TYPE long # endif # ifdef sun # define LOAD_AVE_TYPE long # endif # ifdef decstation # define LOAD_AVE_TYPE long # endif # ifdef _SEQUENT_ # define LOAD_AVE_TYPE long # endif # ifdef sgi # define LOAD_AVE_TYPE long # endif # ifdef SVR4 # define LOAD_AVE_TYPE long # endif # ifdef sony_news # define LOAD_AVE_TYPE long # endif # ifdef sequent # define LOAD_AVE_TYPE long # endif # ifdef OSF_ALPHA # define LOAD_AVE_TYPE long # endif # if defined (ardent) && defined (titan) # define LOAD_AVE_TYPE long # endif # ifdef tek4300 # define LOAD_AVE_TYPE long # endif # if defined(alliant) && defined(i860) /* Alliant FX/2800 */ # define LOAD_AVE_TYPE long # endif # ifdef _AIX # define LOAD_AVE_TYPE long # endif # ifdef convex # define LOAD_AVE_TYPE double # ifndef LDAV_CVT # define LDAV_CVT(n) (n) # endif # endif # endif /* No LOAD_AVE_TYPE. */ # ifdef OSF_ALPHA /* defines an incorrect value for FSCALE on Alpha OSF/1, according to ghazi@noc.rutgers.edu. */ # undef FSCALE # define FSCALE 1024.0 # endif # if defined(alliant) && defined(i860) /* Alliant FX/2800 */ /* defines an incorrect value for FSCALE on an Alliant FX/2800 Concentrix 2.2, according to ghazi@noc.rutgers.edu. */ # undef FSCALE # define FSCALE 100.0 # endif # ifndef FSCALE /* SunOS and some others define FSCALE in sys/param.h. */ # ifdef MORE_BSD # define FSCALE 2048.0 # endif # if defined(MIPS) || defined(SVR4) || defined(decstation) # define FSCALE 256 # endif # if defined (sgi) || defined (sequent) /* Sometimes both MIPS and sgi are defined, so FSCALE was just defined above under #ifdef MIPS. But we want the sgi value. */ # undef FSCALE # define FSCALE 1000.0 # endif # if defined (ardent) && defined (titan) # define FSCALE 65536.0 # endif # ifdef tek4300 # define FSCALE 100.0 # endif # ifdef _AIX # define FSCALE 65536.0 # endif # endif /* Not FSCALE. */ # if !defined (LDAV_CVT) && defined (FSCALE) # define LDAV_CVT(n) (((double) (n)) / FSCALE) # endif # if defined(sgi) || (defined(mips) && !defined(BSD)) # define FIXUP_KERNEL_SYMBOL_ADDR(nl) ((nl)[0].n_value &= ~(1 << 31)) # endif # if !defined (KERNEL_FILE) && defined (sequent) # define KERNEL_FILE "/dynix" # endif # if !defined (KERNEL_FILE) && defined (hpux) # define KERNEL_FILE "/hp-ux" # endif # if !defined(KERNEL_FILE) && (defined(_SEQUENT_) || defined(MIPS) || defined(SVR4) || defined(ISC) || defined (sgi) || (defined (ardent) && defined (titan))) # define KERNEL_FILE "/unix" # endif # if !defined (LDAV_SYMBOL) && defined (alliant) # define LDAV_SYMBOL "_Loadavg" # endif # if !defined(LDAV_SYMBOL) && ((defined(hpux) && !defined(hp9000s300)) || defined(_SEQUENT_) || defined(SVR4) || defined(ISC) || defined(sgi) || (defined (ardent) && defined (titan)) || defined (_AIX)) # define LDAV_SYMBOL "avenrun" # endif # ifdef HAVE_UNISTD_H # include # endif # include /* LOAD_AVE_TYPE should only get defined if we're going to use the nlist method. */ # if !defined(LOAD_AVE_TYPE) && (defined(BSD) || defined(LDAV_CVT) || defined(KERNEL_FILE) || defined(LDAV_SYMBOL)) && !defined(__riscos__) # define LOAD_AVE_TYPE double # endif # ifdef LOAD_AVE_TYPE # ifndef VMS # ifndef __linux__ # ifdef HAVE_NLIST_H # include # else # include # endif # ifdef SUNOS_5 # include # include # include # endif # if defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC) # include # endif # ifndef KERNEL_FILE # define KERNEL_FILE "/vmunix" # endif /* KERNEL_FILE */ # ifndef LDAV_SYMBOL # define LDAV_SYMBOL "_avenrun" # endif /* LDAV_SYMBOL */ # endif /* __linux__ */ # else /* VMS */ # ifndef eunice # include # include # else /* eunice */ # include # endif /* eunice */ # endif /* VMS */ # ifndef LDAV_CVT # define LDAV_CVT(n) ((double) (n)) # endif /* !LDAV_CVT */ # endif /* LOAD_AVE_TYPE */ # if defined(__GNU__) && !defined (NeXT) /* Note that NeXT Openstep defines __GNU__ even though it should not. */ /* GNU system acts much like NeXT, for load average purposes, but not exactly. */ # define NeXT # define host_self mach_host_self # endif # ifdef NeXT # ifdef HAVE_MACH_MACH_H # include # else # include # endif # endif /* NeXT */ # ifdef sgi # include # endif /* sgi */ # ifdef UMAX # include # include # include # include # include # ifdef UMAX_43 # include # include # include # include # include # else /* Not UMAX_43. */ # include # include # include # include # include # include # endif /* Not UMAX_43. */ # endif /* UMAX */ # ifdef DGUX # include # endif # if defined(HAVE_FCNTL_H) || defined(_POSIX_VERSION) # include # else # include # endif /* Avoid static vars inside a function since in HPUX they dump as pure. */ # ifdef NeXT static processor_set_t default_set; static int getloadavg_initialized; # endif /* NeXT */ # ifdef UMAX static unsigned int cpus = 0; static unsigned int samples; # endif /* UMAX */ # ifdef DGUX static struct dg_sys_info_load_info load_info; /* what-a-mouthful! */ # endif /* DGUX */ #if !defined(HAVE_LIBKSTAT) && defined(LOAD_AVE_TYPE) /* File descriptor open to /dev/kmem or VMS load ave driver. */ static int channel; /* Nonzero iff channel is valid. */ static int getloadavg_initialized; /* Offset in kmem to seek to read load average, or 0 means invalid. */ static long offset; #if !defined(VMS) && !defined(sgi) && !defined(__linux__) static struct nlist nl[2]; #endif /* Not VMS or sgi */ #ifdef SUNOS_5 static kvm_t *kd; #endif /* SUNOS_5 */ #endif /* LOAD_AVE_TYPE && !HAVE_LIBKSTAT */ /* Put the 1 minute, 5 minute and 15 minute load averages into the first NELEM elements of LOADAVG. Return the number written (never more than 3, but may be less than NELEM), or -1 if an error occurred. */ int getloadavg (double loadavg[], int nelem) { int elem = 0; /* Return value. */ # ifdef NO_GET_LOAD_AVG # define LDAV_DONE /* Set errno to zero to indicate that there was no particular error; this function just can't work at all on this system. */ errno = 0; elem = -1; # endif # if !defined (LDAV_DONE) && defined (HAVE_LIBKSTAT) /* Use libkstat because we don't have to be root. */ # define LDAV_DONE kstat_ctl_t *kc; kstat_t *ksp; kstat_named_t *kn; kc = kstat_open (); if (kc == 0) return -1; ksp = kstat_lookup (kc, "unix", 0, "system_misc"); if (ksp == 0 ) return -1; if (kstat_read (kc, ksp, 0) == -1) return -1; kn = kstat_data_lookup (ksp, "avenrun_1min"); if (kn == 0) { /* Return -1 if no load average information is available. */ nelem = 0; elem = -1; } if (nelem >= 1) loadavg[elem++] = (double) kn->value.ul/FSCALE; if (nelem >= 2) { kn = kstat_data_lookup (ksp, "avenrun_5min"); if (kn != 0) { loadavg[elem++] = (double) kn->value.ul/FSCALE; if (nelem >= 3) { kn = kstat_data_lookup (ksp, "avenrun_15min"); if (kn != 0) loadavg[elem++] = (double) kn->value.ul/FSCALE; } } } kstat_close (kc); # endif /* HAVE_LIBKSTAT */ # if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC) /* Use pstat_getdynamic() because we don't have to be root. */ # define LDAV_DONE # undef LOAD_AVE_TYPE struct pst_dynamic dyn_info; if (pstat_getdynamic (&dyn_info, sizeof (dyn_info), 0, 0) < 0) return -1; if (nelem > 0) loadavg[elem++] = dyn_info.psd_avg_1_min; if (nelem > 1) loadavg[elem++] = dyn_info.psd_avg_5_min; if (nelem > 2) loadavg[elem++] = dyn_info.psd_avg_15_min; # endif /* hpux && HAVE_PSTAT_GETDYNAMIC */ # if !defined (LDAV_DONE) && defined (__linux__) # define LDAV_DONE # undef LOAD_AVE_TYPE # ifndef LINUX_LDAV_FILE # define LINUX_LDAV_FILE "/proc/loadavg" # endif char ldavgbuf[40]; double load_ave[3]; int fd, count; fd = open (LINUX_LDAV_FILE, O_RDONLY); if (fd == -1) return -1; count = read (fd, ldavgbuf, 40); (void) close (fd); if (count <= 0) return -1; /* The following sscanf must use the C locale. */ setlocale (LC_NUMERIC, "C"); count = sscanf (ldavgbuf, "%lf %lf %lf", &load_ave[0], &load_ave[1], &load_ave[2]); setlocale (LC_NUMERIC, ""); if (count < 1) return -1; for (elem = 0; elem < nelem && elem < count; elem++) loadavg[elem] = load_ave[elem]; return elem; # endif /* __linux__ */ # if !defined (LDAV_DONE) && defined (__NetBSD__) # define LDAV_DONE # undef LOAD_AVE_TYPE # ifndef NETBSD_LDAV_FILE # define NETBSD_LDAV_FILE "/kern/loadavg" # endif unsigned long int load_ave[3], scale; int count; FILE *fp; fp = fopen (NETBSD_LDAV_FILE, "r"); if (fp == NULL) return -1; count = fscanf (fp, "%lu %lu %lu %lu\n", &load_ave[0], &load_ave[1], &load_ave[2], &scale); (void) fclose (fp); if (count != 4) return -1; for (elem = 0; elem < nelem; elem++) loadavg[elem] = (double) load_ave[elem] / (double) scale; return elem; # endif /* __NetBSD__ */ # if !defined (LDAV_DONE) && defined (NeXT) # define LDAV_DONE /* The NeXT code was adapted from iscreen 3.2. */ host_t host; struct processor_set_basic_info info; unsigned info_count; /* We only know how to get the 1-minute average for this system, so even if the caller asks for more than 1, we only return 1. */ if (!getloadavg_initialized) { if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS) getloadavg_initialized = 1; } if (getloadavg_initialized) { info_count = PROCESSOR_SET_BASIC_INFO_COUNT; if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host, (processor_set_info_t) &info, &info_count) != KERN_SUCCESS) getloadavg_initialized = 0; else { if (nelem > 0) loadavg[elem++] = (double) info.load_average / LOAD_SCALE; } } if (!getloadavg_initialized) return -1; # endif /* NeXT */ # if !defined (LDAV_DONE) && defined (UMAX) # define LDAV_DONE /* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not have a /dev/kmem. Information about the workings of the running kernel can be gathered with inq_stats system calls. We only know how to get the 1-minute average for this system. */ struct proc_summary proc_sum_data; struct stat_descr proc_info; double load; register unsigned int i, j; if (cpus == 0) { register unsigned int c, i; struct cpu_config conf; struct stat_descr desc; desc.sd_next = 0; desc.sd_subsys = SUBSYS_CPU; desc.sd_type = CPUTYPE_CONFIG; desc.sd_addr = (char *) &conf; desc.sd_size = sizeof conf; if (inq_stats (1, &desc)) return -1; c = 0; for (i = 0; i < conf.config_maxclass; ++i) { struct class_stats stats; memset (&stats, '\0', sizeof stats); desc.sd_type = CPUTYPE_CLASS; desc.sd_objid = i; desc.sd_addr = (char *) &stats; desc.sd_size = sizeof stats; if (inq_stats (1, &desc)) return -1; c += stats.class_numcpus; } cpus = c; samples = cpus < 2 ? 3 : (2 * cpus / 3); } proc_info.sd_next = 0; proc_info.sd_subsys = SUBSYS_PROC; proc_info.sd_type = PROCTYPE_SUMMARY; proc_info.sd_addr = (char *) &proc_sum_data; proc_info.sd_size = sizeof (struct proc_summary); proc_info.sd_sizeused = 0; if (inq_stats (1, &proc_info) != 0) return -1; load = proc_sum_data.ps_nrunnable; j = 0; for (i = samples - 1; i > 0; --i) { load += proc_sum_data.ps_nrun[j]; if (j++ == PS_NRUNSIZE) j = 0; } if (nelem > 0) loadavg[elem++] = load / samples / cpus; # endif /* UMAX */ # if !defined (LDAV_DONE) && defined (DGUX) # define LDAV_DONE /* This call can return -1 for an error, but with good args it's not supposed to fail. The first argument is for no apparent reason of type 'long int *'. */ dg_sys_info ((long int *) &load_info, DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0); if (nelem > 0) loadavg[elem++] = load_info.one_minute; if (nelem > 1) loadavg[elem++] = load_info.five_minute; if (nelem > 2) loadavg[elem++] = load_info.fifteen_minute; # endif /* DGUX */ # if !defined (LDAV_DONE) && defined (apollo) # define LDAV_DONE /* Apollo code from lisch@mentorg.com (Ray Lischner). This system call is not documented. The load average is obtained as three long integers, for the load average over the past minute, five minutes, and fifteen minutes. Each value is a scaled integer, with 16 bits of integer part and 16 bits of fraction part. I'm not sure which operating system first supported this system call, but I know that SR10.2 supports it. */ extern void proc1_$get_loadav (); unsigned long load_ave[3]; proc1_$get_loadav (load_ave); if (nelem > 0) loadavg[elem++] = load_ave[0] / 65536.0; if (nelem > 1) loadavg[elem++] = load_ave[1] / 65536.0; if (nelem > 2) loadavg[elem++] = load_ave[2] / 65536.0; # endif /* apollo */ # if !defined (LDAV_DONE) && defined (OSF_MIPS) # define LDAV_DONE struct tbl_loadavg load_ave; table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave)); loadavg[elem++] = (load_ave.tl_lscale == 0 ? load_ave.tl_avenrun.d[0] : (load_ave.tl_avenrun.l[0] / (double) load_ave.tl_lscale)); # endif /* OSF_MIPS */ # if !defined (LDAV_DONE) && (defined (__MSDOS__) || defined (WINDOWS32)) # define LDAV_DONE /* A faithful emulation is going to have to be saved for a rainy day. */ for ( ; elem < nelem; elem++) { loadavg[elem] = 0.0; } # endif /* __MSDOS__ || WINDOWS32 */ # if !defined (LDAV_DONE) && defined (OSF_ALPHA) # define LDAV_DONE struct tbl_loadavg load_ave; table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave)); for (elem = 0; elem < nelem; elem++) loadavg[elem] = (load_ave.tl_lscale == 0 ? load_ave.tl_avenrun.d[elem] : (load_ave.tl_avenrun.l[elem] / (double) load_ave.tl_lscale)); # endif /* OSF_ALPHA */ # if !defined (LDAV_DONE) && defined (VMS) /* VMS specific code -- read from the Load Ave driver. */ LOAD_AVE_TYPE load_ave[3]; static int getloadavg_initialized = 0; # ifdef eunice struct { int dsc$w_length; char *dsc$a_pointer; } descriptor; # endif /* Ensure that there is a channel open to the load ave device. */ if (!getloadavg_initialized) { /* Attempt to open the channel. */ # ifdef eunice descriptor.dsc$w_length = 18; descriptor.dsc$a_pointer = "$$VMS_LOAD_AVERAGE"; # else $DESCRIPTOR (descriptor, "LAV0:"); # endif if (sys$assign (&descriptor, &channel, 0, 0) & 1) getloadavg_initialized = 1; } /* Read the load average vector. */ if (getloadavg_initialized && !(sys$qiow (0, channel, IO$_READVBLK, 0, 0, 0, load_ave, 12, 0, 0, 0, 0) & 1)) { sys$dassgn (channel); getloadavg_initialized = 0; } if (!getloadavg_initialized) return -1; # endif /* VMS */ # if !defined (LDAV_DONE) && defined(LOAD_AVE_TYPE) && !defined(VMS) /* UNIX-specific code -- read the average from /dev/kmem. */ # define LDAV_PRIVILEGED /* This code requires special installation. */ LOAD_AVE_TYPE load_ave[3]; /* Get the address of LDAV_SYMBOL. */ if (offset == 0) { # ifndef sgi # ifndef NLIST_STRUCT strcpy (nl[0].n_name, LDAV_SYMBOL); strcpy (nl[1].n_name, ""); # else /* NLIST_STRUCT */ # ifdef HAVE_STRUCT_NLIST_N_UN_N_NAME nl[0].n_un.n_name = LDAV_SYMBOL; nl[1].n_un.n_name = 0; # else /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */ nl[0].n_name = LDAV_SYMBOL; nl[1].n_name = 0; # endif /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */ # endif /* NLIST_STRUCT */ # ifndef SUNOS_5 if ( # if !(defined (_AIX) && !defined (ps2)) nlist (KERNEL_FILE, nl) # else /* _AIX */ knlist (nl, 1, sizeof (nl[0])) # endif >= 0) /* Omit "&& nl[0].n_type != 0 " -- it breaks on Sun386i. */ { # ifdef FIXUP_KERNEL_SYMBOL_ADDR FIXUP_KERNEL_SYMBOL_ADDR (nl); # endif offset = nl[0].n_value; } # endif /* !SUNOS_5 */ # else /* sgi */ int ldav_off; ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN); if (ldav_off != -1) offset = (long) ldav_off & 0x7fffffff; # endif /* sgi */ } /* Make sure we have /dev/kmem open. */ if (!getloadavg_initialized) { # ifndef SUNOS_5 channel = open ("/dev/kmem", 0); if (channel >= 0) { /* Set the channel to close on exec, so it does not litter any child's descriptor table. */ # ifdef F_SETFD # ifndef FD_CLOEXEC # define FD_CLOEXEC 1 # endif (void) fcntl (channel, F_SETFD, FD_CLOEXEC); # endif getloadavg_initialized = 1; } # else /* SUNOS_5 */ /* We pass 0 for the kernel, corefile, and swapfile names to use the currently running kernel. */ kd = kvm_open (0, 0, 0, O_RDONLY, 0); if (kd != 0) { /* nlist the currently running kernel. */ kvm_nlist (kd, nl); offset = nl[0].n_value; getloadavg_initialized = 1; } # endif /* SUNOS_5 */ } /* If we can, get the load average values. */ if (offset && getloadavg_initialized) { /* Try to read the load. */ # ifndef SUNOS_5 if (lseek (channel, offset, 0) == -1L || read (channel, (char *) load_ave, sizeof (load_ave)) != sizeof (load_ave)) { close (channel); getloadavg_initialized = 0; } # else /* SUNOS_5 */ if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave)) != sizeof (load_ave)) { kvm_close (kd); getloadavg_initialized = 0; } # endif /* SUNOS_5 */ } if (offset == 0 || !getloadavg_initialized) return -1; # endif /* LOAD_AVE_TYPE and not VMS */ # if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE) /* Including VMS. */ if (nelem > 0) loadavg[elem++] = LDAV_CVT (load_ave[0]); if (nelem > 1) loadavg[elem++] = LDAV_CVT (load_ave[1]); if (nelem > 2) loadavg[elem++] = LDAV_CVT (load_ave[2]); # define LDAV_DONE # endif /* !LDAV_DONE && LOAD_AVE_TYPE */ # ifdef LDAV_DONE return elem; # else /* Set errno to zero to indicate that there was no particular error; this function just can't work at all on this system. */ errno = 0; return -1; # endif } #endif /* ! HAVE_GETLOADAVG */ #ifdef TEST #include "makeint.h" int main (int argc, char **argv) { int naptime = 0; if (argc > 1) naptime = atoi (argv[1]); while (1) { double avg[3]; int loads; errno = 0; /* Don't be misled if it doesn't set errno. */ loads = getloadavg (avg, 3); if (loads == -1) { perror ("Error getting load average"); exit (1); } if (loads > 0) printf ("1-minute: %f ", avg[0]); if (loads > 1) printf ("5-minute: %f ", avg[1]); if (loads > 2) printf ("15-minute: %f ", avg[2]); if (loads > 0) putchar ('\n'); if (naptime == 0) break; sleep (naptime); } exit (0); } #endif /* TEST */ kbuild-3686/src/kmk/output.h0000664000175000017500000000711415053010075015775 0ustar locutuslocutus/* Output to stdout / stderr for GNU make Copyright (C) 2013-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #ifndef INCLUDED_MAKE_OUTPUT_H #define INCLUDED_MAKE_OUTPUT_H #include /* darwin*/ #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY /* Output run. */ struct output_run { unsigned int seqno; /* For interleaving out/err output. */ unsigned int len; /* The length of the output. */ struct output_run *next; /* Pointer to the next run. */ }; /* Output segment. */ struct output_segment { struct output_segment *next; size_t size; /* Segment size, everything included. */ struct output_run runs[1]; }; /* Output memory buffer. */ struct output_membuf { struct output_run *head_run; struct output_run *tail_run; /* Always in tail_seg. */ struct output_segment *head_seg; struct output_segment *tail_seg; size_t left; /* Number of bytes that can be appended to the tail_run. */ size_t total; /* Total segment allocation size. */ }; #endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */ struct output { #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY struct output_membuf out; struct output_membuf err; unsigned int seqno; /* The current run sequence number. */ #else int out; int err; #endif unsigned int syncout:1; /* True if we want to synchronize output. */ #ifdef KMK unsigned int dont_truncate:1; /* For die_with_child_output repeat. */ #endif }; extern struct output *output_context; extern unsigned int stdio_traced; #if defined(KMK) && !defined(NO_OUTPUT_SYNC) extern int output_metered; #endif #define OUTPUT_SET(_new) do{ output_context = (_new)->syncout ? (_new) : NULL; }while(0) #define OUTPUT_UNSET() do{ output_context = NULL; }while(0) #define OUTPUT_TRACED() do{ stdio_traced = 1; }while(0) #define OUTPUT_IS_TRACED() (!!stdio_traced) FILE *output_tmpfile (char **, const char *); /* Initialize and close a child output structure: if NULL do this program's output (this should only be done once). */ void output_init (struct output *out); void output_close (struct output *out); /* In situations where output may be about to be displayed but we're not sure if we've set it up yet, call this. */ void output_start (void); /* Show a message on stdout or stderr. Will start the output if needed. */ void outputs (int is_err, const char *msg); #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY ssize_t output_write_bin (struct output *out, int is_err, const char *src, size_t len); #endif ssize_t output_write_text (struct output *out, int is_err, const char *src, size_t len); #ifndef NO_OUTPUT_SYNC int output_tmpfd (void); /* Dump any child output content to stdout, and reset it. */ void output_dump (struct output *out); # ifdef KMK void output_reset (struct output *out); # endif #endif #ifdef DEBUG_STDOUT_CLOSE_ISSUE void my_check_stdout (const char *pszWhere); #endif #endif /* INLCUDED_MAKE_OUTPUT_H */ kbuild-3686/src/kmk/config.h.freebsd0000664000175000017500000003017615053010076017320 0ustar locutuslocutus/* config.h. Generated by configure. */ /* config.h.in. Generated from configure.in by autoheader. */ /* Define to 1 if the `closedir' function returns void instead of `int'. */ /* #undef CLOSEDIR_VOID */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if using `getloadavg.c'. */ /* #undef C_GETLOADAVG */ /* Define to 1 for DGUX with . */ /* #undef DGUX */ /* Use high resolution file timestamps if nonzero. */ #define FILE_TIMESTAMP_HI_RES 0 /* Define to 1 if the `getloadavg' function needs to be run setuid or setgid. */ /* #undef GETLOADAVG_PRIVILEGED */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ /* #undef HAVE_ALLOCA_H */ /* Define to 1 if your compiler conforms to the ANSI C standard. */ #define HAVE_ANSI_COMPILER 1 /* Define to 1 if you have the `atexit' function. */ #define HAVE_ATEXIT 1 /* Define to 1 if you have the `bsd_signal' function. */ /* #undef HAVE_BSD_SIGNAL */ /* Use case insensitive file names */ /* #undef HAVE_CASE_INSENSITIVE_FS */ /* Define to 1 if you have the clock_gettime function. */ /* #undef HAVE_CLOCK_GETTIME */ /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you don't. */ #define HAVE_DECL_SYS_SIGLIST 1 /* Define to 1 if you have the declaration of `_sys_siglist', and to 0 if you don't. */ #define HAVE_DECL__SYS_SIGLIST 0 /* Define to 1 if you have the declaration of `__sys_siglist', and to 0 if you don't. */ #define HAVE_DECL___SYS_SIGLIST 0 /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ /* #undef HAVE_DOPRNT */ /* Use platform specific coding */ /* #undef HAVE_DOS_PATHS */ /* Define to 1 if you have the `dup2' function. */ #define HAVE_DUP2 1 /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define to 1 if you have the `fdopen' function. */ #define HAVE_FDOPEN 1 /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getgroups' function. */ #define HAVE_GETGROUPS 1 /* Define to 1 if you have the `gethostbyname' function. */ /* #undef HAVE_GETHOSTBYNAME */ /* Define to 1 if you have the `gethostname' function. */ /* #undef HAVE_GETHOSTNAME */ /* Define to 1 if you have the `getloadavg' function. */ #define HAVE_GETLOADAVG 1 /* Define to 1 if you have the `getrlimit' function. */ #define HAVE_GETRLIMIT 1 /* Define to 1 if you have a standard gettimeofday function */ #define HAVE_GETTIMEOFDAY 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the `dgc' library (-ldgc). */ /* #undef HAVE_LIBDGC */ /* Define to 1 if you have the `kstat' library (-lkstat). */ /* #undef HAVE_LIBKSTAT */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you have the `lstat' function. */ #define HAVE_LSTAT 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MACH_MACH_H */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have the `mktemp' function. */ #define HAVE_MKTEMP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NLIST_H */ /* Define to 1 if you have the `pipe' function. */ #define HAVE_PIPE 1 /* Define to 1 if you have the `pstat_getdynamic' function. */ /* #undef HAVE_PSTAT_GETDYNAMIC */ /* Define to 1 if you have the `readlink' function. */ #define HAVE_READLINK 1 /* Define to 1 if you have the `realpath' function. */ #define HAVE_REALPATH 1 /* Define to 1 if defines the SA_RESTART constant. */ #define HAVE_SA_RESTART 1 /* Define to 1 if you have the `setegid' function. */ #define HAVE_SETEGID 1 /* Define to 1 if you have the `seteuid' function. */ #define HAVE_SETEUID 1 /* Define to 1 if you have the `setlinebuf' function. */ #define HAVE_SETLINEBUF 1 /* Define to 1 if you have the `setlocale' function. */ /* #undef HAVE_SETLOCALE */ /* Define to 1 if you have the `setregid' function. */ #define HAVE_SETREGID 1 /* Define to 1 if you have the `setreuid' function. */ #define HAVE_SETREUID 1 /* Define to 1 if you have the `setrlimit' function. */ #define HAVE_SETRLIMIT 1 /* Define to 1 if you have the `setvbuf' function. */ #define HAVE_SETVBUF 1 /* Define to 1 if you have the `sigaction' function. */ #define HAVE_SIGACTION 1 /* Define to 1 if you have the `sigsetmask' function. */ #define HAVE_SIGSETMASK 1 /* Define to 1 if you have the `socket' function. */ /* #undef HAVE_SOCKET */ /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 /* Define to 1 if you have the `strcmpi' function. */ /* #undef HAVE_STRCMPI */ /* Define to 1 if you have the `strcoll' function and it is properly defined. */ #define HAVE_STRCOLL 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the `stricmp' function. */ /* #undef HAVE_STRICMP */ /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strsignal' function. */ #define HAVE_STRSIGNAL 1 /* Define to 1 if `n_un.n_name' is member of `struct nlist'. */ /* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* 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, and it defines `DIR'. */ /* #undef HAVE_SYS_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_RESOURCE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIMEB_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_WAIT_H 1 /* Define to 1 if you have the \`union wait' type in . */ /* #undef HAVE_UNION_WAIT */ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VARARGS_H */ /* Define to 1 if you have the `vfork' function. */ #define HAVE_VFORK 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VFORK_H */ /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the `wait3' function. */ #define HAVE_WAIT3 1 /* Define to 1 if you have the `waitpid' function. */ #define HAVE_WAITPID 1 /* Define to 1 if `fork' works. */ #define HAVE_WORKING_FORK 1 /* Define to 1 if `vfork' works. */ #define HAVE_WORKING_VFORK 1 /* Build host information. (not used by kmk) */ #if defined(__X86__) || defined(__i386__) || defined(__I386__) #define MAKE_HOST "i386-unknown-freebsd6.2" #else #define MAKE_HOST "amd64-unknown-freebsd6.2" #endif /* Define to 1 to enable job server support in GNU make. */ #define MAKE_JOBSERVER 1 /* Define to 1 to enable symbolic link timestamp checking. */ #define MAKE_SYMLINKS 1 /* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend on `HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* #undef NLIST_NAME_UNION */ /* Define to 1 if struct nlist.n_name is a pointer rather than an array. */ /* #undef NLIST_STRUCT */ /* Define to 1 if your C compiler doesn't accept -c and -o together. */ /* #undef NO_MINUS_C_MINUS_O */ /* Name of package */ #define PACKAGE "make" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bug-make@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "GNU make" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "GNU make 3.82" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "make" /* Define to the version of this package. */ #define PACKAGE_VERSION "3.82" /* Define to the character that separates directories in PATH. */ #define PATH_SEPARATOR_CHAR ':' /* Define to 1 if the C compiler supports function prototypes. */ #define PROTOTYPES 1 /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* Define to the name of the SCCS 'get' command. */ #define SCCS_GET "get" /* Define to 1 if the SCCS 'get' command understands the '-G' option. */ /* #undef SCCS_GET_MINUS_G */ /* Define to 1 if the `setvbuf' function takes the buffering type as its second argument and the buffer pointer as the third, as on System V before release 3. */ /* #undef SETVBUF_REVERSED */ /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if the `S_IS*' macros in do not work properly. */ /* #undef STAT_MACROS_BROKEN */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define if struct stat contains a nanoseconds field */ /* #undef ST_MTIM_NSEC */ /* Define to 1 on System V Release 4. */ /* #undef SVR4 */ /* Define to 1 if you can safely include both and . */ #define TIME_WITH_SYS_TIME 1 /* Define to 1 for Encore UMAX. */ /* #undef UMAX */ /* Define to 1 for Encore UMAX 4.3 that has instead of . */ /* #undef UMAX4_3 */ /* Version number of package */ #define VERSION "3.82" /* Use platform specific coding */ /* #undef WINDOWS32 */ /* Define if using the dmalloc debugging malloc package */ /* #undef WITH_DMALLOC */ /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* # undef _ALL_SOURCE */ #endif /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Define like PROTOTYPES; this can be used by system headers. */ #define __PROTOTYPES 1 /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `int' if doesn't define. */ /* #undef gid_t */ /* Define to `int' if does not define. */ /* #undef pid_t */ /* Define to `int' if doesn't define. */ /* #undef uid_t */ /* Define uintmax_t if not defined in or . */ /* #undef uintmax_t */ /* Define as `fork' if `vfork' does not work. */ /* #undef vfork */ #include "inlined_memchr.h" kbuild-3686/src/kmk/testcase-includedep-esc-sub.kmk0000664000175000017500000000613515053010075022256 0ustar locutuslocutus# $Id: testcase-includedep-esc-sub.kmk 3318 2020-04-01 07:05:32Z bird $ ## @file # kBuild - testcase for the includdep directive with filename escaping, helper # file that gets included. # # # Copyright (c) 2007-2020 knut st. osmundsen # # This file is part of kBuild. # # kBuild 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 3 of the License, or # (at your option) any later version. # # kBuild 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 kBuild. If not, see # # testcase-includedep-esc-sub.kmk=included # spaces /phoney/file-with-two-spaces\ \ .c: \ /phoney/header-file-with-two-spaces\ \ .h # # From example-spaces.kmk # /phoney-dep-ignore: phoney\ space\ \ 1: /phoney-dep\ space\ \ 1 phoney\ colon\:\ 2: /phoney-dep\ colon\:\ 2 \ phoney\ hash\#\ 3 : /phoney-dep\ hash\#\ 3 phoney\ dollar$$\ 4 : /phoney-dep\ dollar$$\ 4 \ phoney\ slash-space\\\ 5: /phoney-dep\ slash-space\\\ 5 phoney\ slash-hash\\\#\ 6: /phoney-dep\ slash-hash\\\#\ 6 \ phoney\ slash-slash-hash\\\\\#\ 7: /phoney-dep\ slash-slash-hash\\\\\#\ 7 phoney\ equal\=\ 8: /phoney-dep\ equal\=\ 8 phoney\ semI\;\ 9: /phoney-dep\ semi\;\ 9 # Note! The percent is only escaped on the target side! phoney\ percent\%\ 10: /phoney-dep\ percent%\ 10 \ # Note! The pipe is only escaped on the dependency list side! phoney\ pipe|\ 11: /phoney-dep\ pipe\|\ 11 phoney\ plus+\ 12: \ /phoney-dep\ plus+\ 12 phoney\ trailing-slash13\\: /phoney-dep\ trailing-slash13\ \ phoney\ trailing-slash13b\\: /phoney-dep\ trailing-slash13b\ \ \ \ \ phoney\ trailing-slash14\\: \ /phoney-dep\ trailing-slash14\\ \ /phoney-dep-ignore phoney\ 15-trailing-space\ : /phoney-dep\ 15-trailing-space\ /phoney-dep-ignore # Note! No stripping spaces! Trailing space here that gets stripped instead of escaped. phoney\ 16-no-trailing-space\\: /phoney-dep\ 16-no-trailing-space\ phoney\ 17-3x-escaped-newlines\ becomes-single-space: /phoney-dep\ 17-3x-escaped-newlines\ \ \ \ becomes-single-space # Note! Must have a trailing space or comment. phoney\ 18-3x-escaped-trailing-spaces-no-newline\ \ \\: \ /phoney-dep\ 18-3x-escaped-trailing-spaces-no-newline\ \ \ phoney\ 19-target-trailing-space-with-padding\ : /phoney-dep\ 19-target-trailing-space-with-padding\ /phoney-dep-ignore phoney\ 20-target-trailing-space-with-newline-padding\ \ \ : /phoney-dep\ 20-target-trailing-space-with-newline-padding\ /phoney-dep-ignore phoney\ 21-target-trailing-space-with-newline-padding-and-tail\ \ \ \ \ my-tail-21: /phoney-dep\ 21-target-trailing-space-with-newline-padding-and-tail\ \ \ \ my-tail-21 all-trailing-slashes1: /phoney-dep\ trailing-slash13\ \ all-trailing-slashes2: /phoney-dep\ trailing-slash13b\ \ \ \ \ kbuild-3686/src/kmk/testcase-math.kmk0000664000175000017500000000651615053010076017540 0ustar locutuslocutus# $Id: testcase-math.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild - testcase for the math functions. # # # Copyright (c) 2007-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild 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 3 of the License, or # (at your option) any later version. # # kBuild 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 kBuild. If not, see # # DEPTH = ../.. include $(PATH_KBUILD)/header.kmk ifneq ($(not 1),) $(error The 'not' function is missing) endif ifneq ($(eq 1,1),1) $(error The 'eq' function is missing) endif ASSERT_TRUE = $(if $(not $(1)),$(error failure: '$(1)' isn't true)) ASSERT_FALSE = $(if $(1) ,$(error failure: '$(1)' isn't false)) $(call ASSERT_TRUE, $(int-eq 0x0, 0)) $(call ASSERT_FALSE,$(int-eq 1, 0)) $(call ASSERT_FALSE,$(int-eq 1123123123, 9898787987)) $(call ASSERT_TRUE, $(int-eq 1234567890, 1234567890)) $(call ASSERT_TRUE, $(int-eq 0x1c, 28)) $(call ASSERT_TRUE, $(int-eq 1c, 28)) $(call ASSERT_TRUE, $(int-ne 0x123, -0x123)) $(call ASSERT_TRUE, $(int-ne 123, -0x123)) $(call ASSERT_FALSE,$(int-ne 0x100, 256)) $(call ASSERT_FALSE,$(int-ne 0x0, 0)) $(call ASSERT_FALSE,$(int-ne 0x1c, 28)) $(call ASSERT_TRUE, $(int-le 0, 0)) $(call ASSERT_TRUE, $(int-le -0, 0)) $(call ASSERT_FALSE,$(int-le 5, 1)) $(call ASSERT_FALSE,$(int-lt 5, 1)) $(call ASSERT_FALSE,$(int-lt 5, 5)) $(call ASSERT_TRUE, $(int-lt 9, 10)) $(call ASSERT_TRUE, $(int-lt -9, -8)) $(call ASSERT_TRUE, $(int-ge 0, 0)) $(call ASSERT_TRUE, $(int-ge -0, 0)) $(call ASSERT_TRUE, $(int-ge 1, 0)) $(call ASSERT_TRUE, $(int-ge -55, -55)) $(call ASSERT_TRUE, $(int-ge 512, 400)) $(call ASSERT_TRUE, $(int-ge -18, -19)) $(call ASSERT_FALSE,$(int-ge -19, -18)) $(call ASSERT_FALSE,$(int-ge 15, 20)) $(call ASSERT_FALSE,$(int-gt 15, 20)) $(call ASSERT_FALSE,$(int-gt 15, 15)) $(call ASSERT_TRUE, $(int-gt 20, 15)) ASSERT2 = $(if $(not $(int-eq $(1),$(2))),$(error failure: '$(1)' -ne '$(2)')) $(call ASSERT2,$(int-add 1, 1),0x2) $(call ASSERT2,$(int-add 1, 1, 1, 1, 1, 1, 1),7) $(call ASSERT2,$(int-add 1, -1),0) $(call ASSERT2,$(int-sub 1, -1),2) $(call ASSERT2,$(int-sub 1, 5),-4) $(call ASSERT2,$(int-mul 0x10, 0x20),0x200) $(call ASSERT2,$(int-mul 0x20, 0x10),0x200) $(call ASSERT2,$(int-mul 4, 7),28) $(call ASSERT2,$(int-mul 2, 2, 2, 2, 2, 4, 1, 1, 1, 1),128) $(call ASSERT2,$(int-div 0x1000, 0x100),0x10) $(call ASSERT2,$(int-div 999, 10),99) $(call ASSERT2,$(int-div 4096, 4,2,2,2,2),64) #$(call ASSERT2,$(int-div 0x1230023213, 0),0x0) $(call ASSERT2,$(int-mod 19, 10),9) $(call ASSERT2,$(int-mod 9, 10),9) $(call ASSERT2,$(int-mod 30, 10),0) $(call ASSERT2,$(int-not 0),-1) $(call ASSERT2,$(int-and 1, 1),1) $(call ASSERT2,$(int-and 0x123123214, 0xfff),0x214) $(call ASSERT2,$(int-and 0x123123214, 0xf0f, 0xf),4) $(call ASSERT2,$(int-or 1, 1, 1, 2, 2),3) $(call ASSERT2,$(int-xor 1, 1, 2, 2),0) $(call ASSERT2,$(int-xor 1, 2, 4),7) all_recursive: $(ECHO) The math works. 6 * 7 = $(int-mul 6,7) kbuild-3686/src/kmk/main.c0000664000175000017500000042054015053010075015356 0ustar locutuslocutus/* Argument parsing and main program of GNU Make. Copyright (C) 1988-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include "makeint.h" #include "os.h" #include "filedef.h" #include "dep.h" #include "variable.h" #include "job.h" #include "commands.h" #include "rule.h" #include "debug.h" #include "getopt.h" #ifdef KMK # include "kbuild.h" #endif #ifdef CONFIG_WITH_KMK_BUILTIN_STATS # include "kmkbuiltin.h" #endif #include #ifdef _AMIGA # include # include #endif #ifdef WINDOWS32 # include # include # include "pathstuff.h" # ifndef CONFIG_NEW_WIN_CHILDREN # include "sub_proc.h" # else # include "w32/winchildren.h" # endif # include "w32err.h" #endif #ifdef __EMX__ # include # include #endif #ifdef HAVE_FCNTL_H # include #endif #ifdef CONFIG_WITH_COMPILER # include "kmk_cc_exec.h" #endif #ifdef KMK /* for get_online_cpu_count */ # if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) # include # endif # ifdef __OS2__ # define INCL_BASE # include # endif # ifdef __HAIKU__ # include # endif #endif /* KMK*/ #if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) # define SET_STACK_SIZE #endif #ifdef SET_STACK_SIZE # include #endif #ifdef _AMIGA int __stack = 20000; /* Make sure we have 20K of stack space */ #endif #ifdef VMS int vms_use_mcr_command = 0; int vms_always_use_cmd_file = 0; int vms_gnv_shell = 0; int vms_legacy_behavior = 0; int vms_comma_separator = 0; int vms_unix_simulation = 0; int vms_report_unix_paths = 0; /* Evaluates if a VMS environment option is set, only look at first character */ static int get_vms_env_flag (const char *name, int default_value) { char * value; char x; value = getenv (name); if (value == NULL) return default_value; x = toupper (value[0]); switch (x) { case '1': case 'T': case 'E': return 1; break; case '0': case 'F': case 'D': return 0; } } #endif #ifdef CONFIG_WITH_PRINT_STATS_SWITCH void print_variable_stats (void); void print_dir_stats (void); void print_file_stats (void); #endif #if defined HAVE_WAITPID || defined HAVE_WAIT3 # define HAVE_WAIT_NOHANG #endif #if !defined(HAVE_UNISTD_H) && !defined(_MSC_VER) /* bird */ int chdir (); #endif #ifndef STDC_HEADERS # ifndef sun /* Sun has an incorrect decl in a header. */ void exit (int) __attribute__ ((noreturn)); # endif double atof (); #endif static void clean_jobserver (int status); static void print_data_base (void); static void print_version (void); static void decode_switches (int argc, const char **argv, int env); static void decode_env_switches (const char *envar, unsigned int len); static struct variable *define_makeflags (int all, int makefile); static char *quote_for_env (char *out, const char *in); static void initialize_global_hash_tables (void); /* The structure that describes an accepted command switch. */ struct command_switch { int c; /* The switch character. */ enum /* Type of the value. */ { flag, /* Turn int flag on. */ flag_off, /* Turn int flag off. */ string, /* One string per invocation. */ strlist, /* One string per switch. */ filename, /* A string containing a file name. */ positive_int, /* A positive integer. */ floating, /* A floating-point number (double). */ ignore /* Ignored. */ } type; void *value_ptr; /* Pointer to the value-holding variable. */ unsigned int env:1; /* Can come from MAKEFLAGS. */ unsigned int toenv:1; /* Should be put in MAKEFLAGS. */ unsigned int no_makefile:1; /* Don't propagate when remaking makefiles. */ const void *noarg_value; /* Pointer to value used if no arg given. */ const void *default_value; /* Pointer to default value. */ const char *long_name; /* Long option name. */ }; /* True if C is a switch value that corresponds to a short option. */ #define short_option(c) ((c) <= CHAR_MAX) /* The structure used to hold the list of strings given in command switches of a type that takes strlist arguments. */ struct stringlist { const char **list; /* Nil-terminated list of strings. */ unsigned int idx; /* Index into above. */ unsigned int max; /* Number of pointers allocated. */ }; /* The recognized command switches. */ /* Nonzero means do extra verification (that may slow things down). */ int verify_flag; /* Nonzero means do not print commands to be executed (-s). */ int silent_flag; /* Nonzero means just touch the files that would appear to need remaking (-t) */ int touch_flag; /* Nonzero means just print what commands would need to be executed, don't actually execute them (-n). */ int just_print_flag; #ifdef CONFIG_PRETTY_COMMAND_PRINTING /* Nonzero means to print commands argument for argument skipping blanks. */ int pretty_command_printing; #endif #ifdef CONFIG_WITH_PRINT_STATS_SWITCH /* Nonzero means to print internal statistics before exiting. */ int print_stats_flag; #endif #ifdef CONFIG_WITH_PRINT_TIME_SWITCH /* Minimum number of seconds to report, -1 if disabled. */ int print_time_min = -1; static int default_print_time_min = -1; static int no_val_print_time_min = 0; static big_int make_start_ts = -1; int print_time_width = 5; #endif /* Print debugging info (--debug). */ static struct stringlist *db_flags = 0; static int debug_flag = 0; int db_level = 0; /* Synchronize output (--output-sync). */ char *output_sync_option = 0; #ifdef WINDOWS32 /* Suspend make in main for a short time to allow debugger to attach */ int suspend_flag = 0; #endif /* Environment variables override makefile definitions. */ int env_overrides = 0; /* Nonzero means ignore status codes returned by commands executed to remake files. Just treat them all as successful (-i). */ int ignore_errors_flag = 0; /* Nonzero means don't remake anything, just print the data base that results from reading the makefile (-p). */ int print_data_base_flag = 0; /* Nonzero means don't remake anything; just return a nonzero status if the specified targets are not up to date (-q). */ int question_flag = 0; /* Nonzero means do not use any of the builtin rules (-r) / variables (-R). */ int no_builtin_rules_flag = 0; int no_builtin_variables_flag = 0; /* Nonzero means keep going even if remaking some file fails (-k). */ int keep_going_flag; int default_keep_going_flag = 0; /* Nonzero means check symlink mtimes. */ int check_symlink_flag = 0; /* Nonzero means print directory before starting and when done (-w). */ int print_directory_flag = 0; /* Nonzero means ignore print_directory_flag and never print the directory. This is necessary because print_directory_flag is set implicitly. */ int inhibit_print_directory_flag = 0; /* Nonzero means print version information. */ int print_version_flag = 0; /* List of makefiles given with -f switches. */ static struct stringlist *makefiles = 0; /* Size of the stack when we started. */ #ifdef SET_STACK_SIZE struct rlimit stack_limit; #endif /* Number of job slots for parallelism. */ unsigned int job_slots; #define INVALID_JOB_SLOTS (-1) static unsigned int master_job_slots = 0; static int arg_job_slots = INVALID_JOB_SLOTS; #ifdef KMK static int default_job_slots = INVALID_JOB_SLOTS; #else static const int default_job_slots = INVALID_JOB_SLOTS; #endif /* Value of job_slots that means no limit. */ static const int inf_jobs = 0; /* Authorization for the jobserver. */ static char *jobserver_auth = NULL; /* Handle for the mutex used on Windows to synchronize output of our children under -O. */ char *sync_mutex = NULL; /* Maximum load average at which multiple jobs will be run. Negative values mean unlimited, while zero means limit to zero load (which could be useful to start infinite jobs remotely but one at a time locally). */ #ifndef NO_FLOAT double max_load_average = -1.0; double default_load_average = -1.0; #else int max_load_average = -1; int default_load_average = -1; #endif /* List of directories given with -C switches. */ static struct stringlist *directories = 0; /* List of include directories given with -I switches. */ static struct stringlist *include_directories = 0; /* List of files given with -o switches. */ static struct stringlist *old_files = 0; /* List of files given with -W switches. */ static struct stringlist *new_files = 0; /* List of strings to be eval'd. */ static struct stringlist *eval_strings = 0; /* If nonzero, we should just print usage and exit. */ static int print_usage_flag = 0; /* If nonzero, we should print a warning message for each reference to an undefined variable. */ int warn_undefined_variables_flag; /* If nonzero, always build all targets, regardless of whether they appear out of date or not. */ static int always_make_set = 0; int always_make_flag = 0; /* If nonzero, we're in the "try to rebuild makefiles" phase. */ int rebuilding_makefiles = 0; /* Remember the original value of the SHELL variable, from the environment. */ struct variable shell_var; /* This character introduces a command: it's the first char on the line. */ char cmd_prefix = '\t'; #ifdef KMK /* Process priority. 0 = no change; 1 = idle / max nice; 2 = below normal / nice 10; 3 = normal / nice 0; 4 = high / nice -10; 5 = realtime / nice -19; */ int process_priority = 0; /* Process affinity mask; 0 means any CPU. */ int process_affinity = 0; #endif /* KMK */ #if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS) /* When set, we'll gather expensive statistics like for the heap. */ int make_expensive_statistics = 0; #endif #if defined (WINDOWS32) && defined (CONFIG_NEW_WIN_CHILDREN) /* --job-object[=mode]. */ char *win_job_object_mode = NULL; /* --job-object-name=name */ char *win_job_object_name = NULL; /** --job-object-no-kill. */ int win_job_object_no_kill = 0; #endif /* The usage output. We write it this way to make life easier for the translators, especially those trying to translate to right-to-left languages like Hebrew. */ static const char *const usage[] = { N_("Options:\n"), N_("\ -b, -m Ignored for compatibility.\n"), N_("\ -B, --always-make Unconditionally make all targets.\n"), N_("\ -C DIRECTORY, --directory=DIRECTORY\n\ Change to DIRECTORY before doing anything.\n"), N_("\ -d Print lots of debugging information.\n"), N_("\ --debug[=FLAGS] Print various types of debugging information.\n"), N_("\ -e, --environment-overrides\n\ Environment variables override makefiles.\n"), N_("\ --eval=STRING Evaluate STRING as a makefile statement.\n"), N_("\ -f FILE, --file=FILE, --makefile=FILE\n\ Read FILE as a makefile.\n"), N_("\ -h, --help Print this message and exit.\n"), N_("\ -i, --ignore-errors Ignore errors from recipes.\n"), N_("\ -I DIRECTORY, --include-dir=DIRECTORY\n\ Search DIRECTORY for included makefiles.\n"), #ifdef KMK N_("\ -j [N], --jobs[=N] Allow N jobs at once; infinite jobs with no arg.\n\ The default is the number of active CPUs.\n"), #else N_("\ -j [N], --jobs[=N] Allow N jobs at once; infinite jobs with no arg.\n"), #endif N_("\ -k, --keep-going Keep going when some targets can't be made.\n"), N_("\ -l [N], --load-average[=N], --max-load[=N]\n\ Don't start multiple jobs unless load is below N.\n"), N_("\ -L, --check-symlink-times Use the latest mtime between symlinks and target.\n"), N_("\ -n, --just-print, --dry-run, --recon\n\ Don't actually run any recipe; just print them.\n"), N_("\ -o FILE, --old-file=FILE, --assume-old=FILE\n\ Consider FILE to be very old and don't remake it.\n"), #ifndef KMK N_("\ -O[TYPE], --output-sync[=TYPE]\n\ Synchronize output of parallel jobs by TYPE.\n"), #elif defined(KBUILD_OS_WINDOWS) N_("\ -O[TYPE], --output-sync[=TYPE]\n\ Synchronize output of parallel jobs by TYPE:\n\ none = no synchronization.\n\ line = receip line output\n\ target = entire receip output (default)\n\ recurse = entire recursive invocation\n"), #else N_("\ -O[TYPE], --output-sync[=TYPE]\n\ Synchronize output of parallel jobs by TYPE:\n\ none = no synchronization (default).\n\ line = receip line output\n\ target = entire receip output\n\ recurse = entire recursive invocation\n"), #endif N_("\ -p, --print-data-base Print make's internal database.\n"), N_("\ -q, --question Run no recipe; exit status says if up to date.\n"), N_("\ -r, --no-builtin-rules Disable the built-in implicit rules.\n"), N_("\ -R, --no-builtin-variables Disable the built-in variable settings.\n"), N_("\ -s, --silent, --quiet Don't echo recipes.\n"), N_("\ -S, --no-keep-going, --stop\n\ Turns off -k.\n"), N_("\ -t, --touch Touch targets instead of remaking them.\n"), N_("\ --trace Print tracing information.\n"), N_("\ -v, --version Print the version number of make and exit.\n"), N_("\ -w, --print-directory Print the current directory.\n"), N_("\ --no-print-directory Turn off -w, even if it was turned on implicitly.\n"), N_("\ -W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE\n\ Consider FILE to be infinitely new.\n"), N_("\ --warn-undefined-variables Warn when an undefined variable is referenced.\n"), #ifdef KMK N_("\ --affinity=mask Sets the CPU affinity on some hosts.\n"), N_("\ --priority=1-5 Sets the process priority / nice level:\n\ 1 = idle / max nice;\n\ 2 = below normal / nice 10;\n\ 3 = normal / nice 0;\n\ 4 = high / nice -10;\n\ 5 = realtime / nice -19;\n"), N_("\ --nice Alias for --priority=1\n"), #endif /* KMK */ #ifdef CONFIG_PRETTY_COMMAND_PRINTING N_("\ --pretty-command-printing Makes the command echo easier to read.\n"), #endif #ifdef CONFIG_WITH_PRINT_STATS_SWITCH N_("\ --print-stats Print make statistics.\n"), #endif #ifdef CONFIG_WITH_PRINT_TIME_SWITCH N_("\ --print-time[=MIN-SEC] Print file build times starting at arg.\n"), #endif #ifdef CONFIG_WITH_MAKE_STATS N_("\ --statistics Gather extra statistics for $(make-stats ).\n"), #endif #if defined (WINDOWS32) && defined (CONFIG_NEW_WIN_CHILDREN) N_("\ --job-object=mode Windows job object mode:\n\ login = Per login session (default).\n\ root = Root make instance only.\n\ each = Each make instances.\n\ none = No job objects.\n"), N_("\ --job-object-name=name Name of windows job object to open or create.\n\ The default name depends on the level.\n"), N_("\ --job-object-no-kill Do not kill orphaned child processes when done.\n"), #endif NULL }; /* The table of command switches. Order matters here: this is the order MAKEFLAGS will be constructed. So be sure all simple flags (single char, no argument) come first. */ static const struct command_switch switches[] = { { 'b', ignore, 0, 0, 0, 0, 0, 0, 0 }, { 'B', flag, &always_make_set, 1, 1, 0, 0, 0, "always-make" }, { 'd', flag, &debug_flag, 1, 1, 0, 0, 0, 0 }, #ifdef WINDOWS32 { 'D', flag, &suspend_flag, 1, 1, 0, 0, 0, "suspend-for-debug" }, #endif { 'e', flag, &env_overrides, 1, 1, 0, 0, 0, "environment-overrides", }, { 'h', flag, &print_usage_flag, 0, 0, 0, 0, 0, "help" }, { 'i', flag, &ignore_errors_flag, 1, 1, 0, 0, 0, "ignore-errors" }, { 'k', flag, &keep_going_flag, 1, 1, 0, 0, &default_keep_going_flag, "keep-going" }, { 'L', flag, &check_symlink_flag, 1, 1, 0, 0, 0, "check-symlink-times" }, { 'm', ignore, 0, 0, 0, 0, 0, 0, 0 }, { 'n', flag, &just_print_flag, 1, 1, 1, 0, 0, "just-print" }, { 'p', flag, &print_data_base_flag, 1, 1, 0, 0, 0, "print-data-base" }, #ifdef CONFIG_PRETTY_COMMAND_PRINTING { CHAR_MAX+50, flag, (char *) &pretty_command_printing, 1, 1, 1, 0, 0, "pretty-command-printing" }, #endif #ifdef CONFIG_WITH_PRINT_STATS_SWITCH { CHAR_MAX+51, flag, (char *) &print_stats_flag, 1, 1, 1, 0, 0, "print-stats" }, #endif #ifdef CONFIG_WITH_PRINT_TIME_SWITCH { CHAR_MAX+52, positive_int, (char *) &print_time_min, 1, 1, 0, (char *) &no_val_print_time_min, (char *) &default_print_time_min, "print-time" }, #endif #ifdef KMK { CHAR_MAX+54, positive_int, (char *) &process_priority, 1, 1, 0, (char *) &process_priority, (char *) &process_priority, "priority" }, { CHAR_MAX+55, positive_int, (char *) &process_affinity, 1, 1, 0, (char *) &process_affinity, (char *) &process_affinity, "affinity" }, { CHAR_MAX+56, flag, (char *) &process_priority, 1, 1, 0, 0, 0, "nice" }, #endif { 'q', flag, &question_flag, 1, 1, 1, 0, 0, "question" }, { 'r', flag, &no_builtin_rules_flag, 1, 1, 0, 0, 0, "no-builtin-rules" }, { 'R', flag, &no_builtin_variables_flag, 1, 1, 0, 0, 0, "no-builtin-variables" }, { 's', flag, &silent_flag, 1, 1, 0, 0, 0, "silent" }, { 'S', flag_off, &keep_going_flag, 1, 1, 0, 0, &default_keep_going_flag, "no-keep-going" }, #if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS) { CHAR_MAX+57, flag, (char *) &make_expensive_statistics, 1, 1, 1, 0, 0, "statistics" }, #endif { 't', flag, &touch_flag, 1, 1, 1, 0, 0, "touch" }, { 'v', flag, &print_version_flag, 1, 1, 0, 0, 0, "version" }, { 'w', flag, &print_directory_flag, 1, 1, 0, 0, 0, "print-directory" }, /* These options take arguments. */ { 'C', filename, &directories, 0, 0, 0, 0, 0, "directory" }, { 'f', filename, &makefiles, 0, 0, 0, 0, 0, "file" }, { 'I', filename, &include_directories, 1, 1, 0, 0, 0, "include-dir" }, { 'j', positive_int, &arg_job_slots, 1, 1, 0, &inf_jobs, &default_job_slots, "jobs" }, #ifndef NO_FLOAT { 'l', floating, &max_load_average, 1, 1, 0, &default_load_average, &default_load_average, "load-average" }, #else { 'l', positive_int, &max_load_average, 1, 1, 0, &default_load_average, &default_load_average, "load-average" }, #endif { 'o', filename, &old_files, 0, 0, 0, 0, 0, "old-file" }, { 'O', string, &output_sync_option, 1, 1, 0, "target", 0, "output-sync" }, { 'W', filename, &new_files, 0, 0, 0, 0, 0, "what-if" }, /* These are long-style options. */ { CHAR_MAX+1, strlist, &db_flags, 1, 1, 0, "basic", 0, "debug" }, { CHAR_MAX+2, string, &jobserver_auth, 1, 1, 0, 0, 0, "jobserver-auth" }, { CHAR_MAX+3, flag, &trace_flag, 1, 1, 0, 0, 0, "trace" }, { CHAR_MAX+4, flag, &inhibit_print_directory_flag, 1, 1, 0, 0, 0, "no-print-directory" }, { CHAR_MAX+5, flag, &warn_undefined_variables_flag, 1, 1, 0, 0, 0, "warn-undefined-variables" }, { CHAR_MAX+6, strlist, &eval_strings, 1, 0, 0, 0, 0, "eval" }, { CHAR_MAX+7, string, &sync_mutex, 1, 1, 0, 0, 0, "sync-mutex" }, #if defined (WINDOWS32) && defined (CONFIG_NEW_WIN_CHILDREN) { CHAR_MAX+58, string, &win_job_object_mode, 1, 1, 1, 0, 0, "job-object" }, { CHAR_MAX+59, string, &win_job_object_name, 1, 1, 1, 0, 0, "job-object-name" }, { CHAR_MAX+60, flag, &win_job_object_no_kill, 1, 1, 1, 0, 0, "job-object-no-kill" }, #endif { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; /* Secondary long names for options. */ static struct option long_option_aliases[] = { { "quiet", no_argument, 0, 's' }, { "stop", no_argument, 0, 'S' }, { "new-file", required_argument, 0, 'W' }, { "assume-new", required_argument, 0, 'W' }, { "assume-old", required_argument, 0, 'o' }, { "max-load", optional_argument, 0, 'l' }, { "dry-run", no_argument, 0, 'n' }, { "recon", no_argument, 0, 'n' }, { "makefile", required_argument, 0, 'f' }, }; /* List of goal targets. */ #ifndef KMK static #endif struct goaldep *goals, *lastgoal; /* List of variables which were defined on the command line (or, equivalently, in MAKEFLAGS). */ struct command_variable { struct command_variable *next; struct variable *variable; }; static struct command_variable *command_variables; /* The name we were invoked with. */ #ifdef WINDOWS32 /* On MS-Windows, we chop off the .exe suffix in 'main', so this cannot be 'const'. */ char *program; #else const char *program; #endif /* Our current directory before processing any -C options. */ char *directory_before_chdir; /* Our current directory after processing all -C options. */ char *starting_directory; /* Value of the MAKELEVEL variable at startup (or 0). */ unsigned int makelevel; /* Pointer to the value of the .DEFAULT_GOAL special variable. The value will be the name of the goal to remake if the command line does not override it. It can be set by the makefile, or else it's the first target defined in the makefile whose name does not start with '.'. */ struct variable * default_goal_var; /* Pointer to structure for the file .DEFAULT whose commands are used for any file that has none of its own. This is zero if the makefiles do not define .DEFAULT. */ struct file *default_file; /* Nonzero if we have seen the magic '.POSIX' target. This turns on pedantic compliance with POSIX.2. */ int posix_pedantic; /* Nonzero if we have seen the '.SECONDEXPANSION' target. This turns on secondary expansion of prerequisites. */ int second_expansion; #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION /* Nonzero if we have seen the '.SECONDTARGETEXPANSION' target. This turns on secondary expansion of targets. */ int second_target_expansion; #endif /* Nonzero if we have seen the '.ONESHELL' target. This causes the entire recipe to be handed to SHELL as a single string, potentially containing newlines. */ int one_shell; /* One of OUTPUT_SYNC_* if the "--output-sync" option was given. This attempts to synchronize the output of parallel jobs such that the results of each job stay together. */ #ifdef KMK int output_sync = OUTPUT_SYNC_TARGET; #else int output_sync = OUTPUT_SYNC_NONE; #endif /* Nonzero if the "--trace" option was given. */ int trace_flag = 0; #ifndef CONFIG_WITH_EXTENDED_NOTPARALLEL /* Nonzero if we have seen the '.NOTPARALLEL' target. This turns off parallel builds for this invocation of make. */ #else /* CONFIG_WITH_EXTENDED_NOTPARALLEL */ /* Negative if we have seen the '.NOTPARALLEL' target with an empty dependency list. Zero if no '.NOTPARALLEL' or no file in the dependency list is being executed. Positive when a file in the '.NOTPARALLEL' dependency list is in progress, the value is the number of notparallel files in progress (running or queued for running). In short, any nonzero value means no more parallel builing. */ #endif /* CONFIG_WITH_EXTENDED_NOTPARALLEL */ int not_parallel; /* Nonzero if some rule detected clock skew; we keep track so (a) we only print one warning about it during the run, and (b) we can print a final warning at the end of the run. */ int clock_skew_detected; /* Map of possible stop characters for searching strings. */ #ifndef UCHAR_MAX # define UCHAR_MAX 255 #endif #ifdef _MSC_VER __declspec(align(512)) /* bird: improve cacheline & tlb mojo */ #endif unsigned short stopchar_map[UCHAR_MAX + 1] = {0}; /* If output-sync is enabled we'll collect all the output generated due to options, while reading makefiles, etc. */ struct output make_sync; #ifdef KMK /** Current umask() value. */ mode_t g_fUMask = 0022; #endif /* Mask of signals that are being caught with fatal_error_signal. */ #ifdef POSIX sigset_t fatal_signal_set; #else # ifdef HAVE_SIGSETMASK int fatal_signal_mask; # endif #endif #if !HAVE_DECL_BSD_SIGNAL && !defined bsd_signal # if !defined HAVE_SIGACTION # define bsd_signal signal # else typedef RETSIGTYPE (*bsd_signal_ret_t) (int); static bsd_signal_ret_t bsd_signal (int sig, bsd_signal_ret_t func) { struct sigaction act, oact; act.sa_handler = func; act.sa_flags = SA_RESTART; sigemptyset (&act.sa_mask); sigaddset (&act.sa_mask, sig); if (sigaction (sig, &act, &oact) != 0) return SIG_ERR; return oact.sa_handler; } # endif #endif #ifdef CONFIG_WITH_ALLOC_CACHES struct alloccache dep_cache; struct alloccache goaldep_cache; struct alloccache nameseq_cache; struct alloccache file_cache; struct alloccache commands_cache; struct alloccache variable_cache; struct alloccache variable_set_cache; struct alloccache variable_set_list_cache; static void initialize_global_alloc_caches (void) { alloccache_init (&dep_cache, sizeof (struct dep), "dep", NULL, NULL); alloccache_init (&goaldep_cache, sizeof (struct goaldep), "goaldep", NULL, NULL); alloccache_init (&nameseq_cache, sizeof (struct nameseq), "nameseq", NULL, NULL); alloccache_init (&file_cache, sizeof (struct file), "file", NULL, NULL); alloccache_init (&commands_cache, sizeof (struct commands), "commands", NULL, NULL); alloccache_init (&variable_cache, sizeof (struct variable), "variable", NULL, NULL); alloccache_init (&variable_set_cache, sizeof (struct variable_set), "variable_set", NULL, NULL); alloccache_init (&variable_set_list_cache, sizeof (struct variable_set_list), "variable_set_list", NULL, NULL); } #endif /* CONFIG_WITH_ALLOC_CACHES */ static void initialize_global_hash_tables (void) { init_hash_global_variable_set (); strcache_init (); init_hash_files (); hash_init_directories (); hash_init_function_table (); } /* This character map locate stop chars when parsing GNU makefiles. Each element is true if we should stop parsing on that character. */ static void initialize_stopchar_map (void) { int i; stopchar_map[(int)'\0'] = MAP_NUL; stopchar_map[(int)'#'] = MAP_COMMENT; stopchar_map[(int)';'] = MAP_SEMI; stopchar_map[(int)'='] = MAP_EQUALS; stopchar_map[(int)':'] = MAP_COLON; stopchar_map[(int)'%'] = MAP_PERCENT; stopchar_map[(int)'|'] = MAP_PIPE; stopchar_map[(int)'.'] = MAP_DOT | MAP_USERFUNC; stopchar_map[(int)','] = MAP_COMMA; stopchar_map[(int)'$'] = MAP_VARIABLE; stopchar_map[(int)'-'] = MAP_USERFUNC; stopchar_map[(int)'_'] = MAP_USERFUNC; stopchar_map[(int)' '] = MAP_BLANK; stopchar_map[(int)'\t'] = MAP_BLANK; stopchar_map[(int)'/'] = MAP_DIRSEP; #if defined(VMS) stopchar_map[(int)':'] |= MAP_DIRSEP; stopchar_map[(int)']'] |= MAP_DIRSEP; stopchar_map[(int)'>'] |= MAP_DIRSEP; #elif defined(HAVE_DOS_PATHS) stopchar_map[(int)'\\'] |= MAP_DIRSEP; #endif for (i = 1; i <= UCHAR_MAX; ++i) { if (isspace (i) && NONE_SET (stopchar_map[i], MAP_BLANK)) /* Don't mark blank characters as newline characters. */ stopchar_map[i] |= MAP_NEWLINE; else if (isalnum (i)) stopchar_map[i] |= MAP_USERFUNC; } } static const char * expand_command_line_file (const char *name) { const char *cp; char *expanded = 0; if (name[0] == '\0') O (fatal, NILF, _("empty string invalid as file name")); if (name[0] == '~') { expanded = tilde_expand (name); if (expanded && expanded[0] != '\0') name = expanded; } /* This is also done in parse_file_seq, so this is redundant for names read from makefiles. It is here for names passed on the command line. */ while (name[0] == '.' && name[1] == '/') { name += 2; while (name[0] == '/') /* Skip following slashes: ".//foo" is "foo", not "/foo". */ ++name; } if (name[0] == '\0') { /* Nothing else but one or more "./", maybe plus slashes! */ name = "./"; } cp = strcache_add (name); free (expanded); return cp; } /* Toggle -d on receipt of SIGUSR1. */ #ifdef SIGUSR1 static RETSIGTYPE debug_signal_handler (int sig UNUSED) { db_level = db_level ? DB_NONE : DB_BASIC; } #endif static void decode_debug_flags (void) { const char **pp; if (debug_flag) db_level = DB_ALL; if (db_flags) for (pp=db_flags->list; *pp; ++pp) { const char *p = *pp; while (1) { switch (tolower (p[0])) { case 'a': db_level |= DB_ALL; break; case 'b': db_level |= DB_BASIC; break; case 'i': db_level |= DB_BASIC | DB_IMPLICIT; break; case 'j': db_level |= DB_JOBS; break; case 'm': db_level |= DB_BASIC | DB_MAKEFILES; break; case 'n': db_level = 0; break; case 'v': db_level |= DB_BASIC | DB_VERBOSE; break; #ifdef DB_KMK case 'k': db_level |= DB_KMK; break; #endif /* DB_KMK */ default: OS (fatal, NILF, _("unknown debug level specification '%s'"), p); } while (*(++p) != '\0') if (*p == ',' || *p == ' ') { ++p; break; } if (*p == '\0') break; } } if (db_level) verify_flag = 1; if (! db_level) debug_flag = 0; } static void decode_output_sync_flags (void) { #ifdef NO_OUTPUT_SYNC output_sync = OUTPUT_SYNC_NONE; #else if (output_sync_option) { if (streq (output_sync_option, "none")) output_sync = OUTPUT_SYNC_NONE; else if (streq (output_sync_option, "line")) output_sync = OUTPUT_SYNC_LINE; else if (streq (output_sync_option, "target")) output_sync = OUTPUT_SYNC_TARGET; else if (streq (output_sync_option, "recurse")) output_sync = OUTPUT_SYNC_RECURSE; else OS (fatal, NILF, _("unknown output-sync type '%s'"), output_sync_option); } if (sync_mutex) RECORD_SYNC_MUTEX (sync_mutex); #endif } #ifdef KMK static void set_make_priority_and_affinity (void) { # ifdef WINDOWS32 DWORD dwClass, dwPriority; if (process_affinity) if (!SetProcessAffinityMask (GetCurrentProcess (), process_affinity)) fprintf (stderr, "warning: SetProcessAffinityMask (,%#x) failed with last error %d\n", process_affinity, GetLastError ()); switch (process_priority) { case 0: return; case 1: dwClass = IDLE_PRIORITY_CLASS; dwPriority = THREAD_PRIORITY_IDLE; break; case 2: dwClass = BELOW_NORMAL_PRIORITY_CLASS; dwPriority = THREAD_PRIORITY_BELOW_NORMAL; break; case 3: dwClass = NORMAL_PRIORITY_CLASS; dwPriority = THREAD_PRIORITY_NORMAL; break; case 4: dwClass = HIGH_PRIORITY_CLASS; dwPriority = 0xffffffff; break; case 5: dwClass = REALTIME_PRIORITY_CLASS; dwPriority = 0xffffffff; break; default: ON (fatal, NILF, _("invalid priority %d\n"), process_priority); } if (!SetPriorityClass (GetCurrentProcess (), dwClass)) fprintf (stderr, "warning: SetPriorityClass (,%#x) failed with last error %d\n", dwClass, GetLastError ()); if (dwPriority != 0xffffffff && !SetThreadPriority (GetCurrentThread (), dwPriority)) fprintf (stderr, "warning: SetThreadPriority (,%#x) failed with last error %d\n", dwPriority, GetLastError ()); #elif defined(__HAIKU__) int32 iNewPriority; status_t error; switch (process_priority) { case 0: return; case 1: iNewPriority = B_LOWEST_ACTIVE_PRIORITY; break; case 2: iNewPriority = B_LOW_PRIORITY; break; case 3: iNewPriority = B_NORMAL_PRIORITY; break; case 4: iNewPriority = B_URGENT_DISPLAY_PRIORITY; break; case 5: iNewPriority = B_REAL_TIME_DISPLAY_PRIORITY; break; default: ON (fatal, NILF, _("invalid priority %d\n"), process_priority); } error = set_thread_priority (find_thread (NULL), iNewPriority); if (error != B_OK) fprintf (stderr, "warning: set_thread_priority (,%d) failed: %s\n", iNewPriority, strerror (error)); # else /*#elif HAVE_NICE */ int nice_level = 0; switch (process_priority) { case 0: return; case 1: nice_level = 19; break; case 2: nice_level = 10; break; case 3: nice_level = 0; break; case 4: nice_level = -10; break; case 5: nice_level = -19; break; default: ON (fatal, NILF, _("invalid priority %d\n"), process_priority); } errno = 0; if (nice (nice_level) == -1 && errno != 0) fprintf (stderr, "warning: nice (%d) failed: %s\n", nice_level, strerror (errno)); # endif } #endif /* KMK */ #ifdef WINDOWS32 #ifndef NO_OUTPUT_SYNC /* This is called from start_job_command when it detects that output_sync option is in effect. The handle to the synchronization mutex is passed, as a string, to sub-makes via the --sync-mutex command-line argument. */ void # ifdef CONFIG_NEW_WIN_CHILDREN prepare_mutex_handle_string (const char *mtxname) { if (!sync_mutex) { sync_mutex = xstrdup(mtxname); define_makeflags (1, 0); } } # else prepare_mutex_handle_string (sync_handle_t handle) { if (!sync_mutex) { /* Prepare the mutex handle string for our children. */ /* 2 hex digits per byte + 2 characters for "0x" + null. */ sync_mutex = xmalloc ((2 * sizeof (sync_handle_t)) + 2 + 1); sprintf (sync_mutex, "0x%Ix", handle); define_makeflags (1, 0); } } # endif #endif /* NO_OUTPUT_SYNC */ # ifndef KMK /* I'd rather have WER collect dumps. */ /* * HANDLE runtime exceptions by avoiding a requestor on the GUI. Capture * exception and print it to stderr instead. * * If ! DB_VERBOSE, just print a simple message and exit. * If DB_VERBOSE, print a more verbose message. * If compiled for DEBUG, let exception pass through to GUI so that * debuggers can attach. */ LONG WINAPI handle_runtime_exceptions (struct _EXCEPTION_POINTERS *exinfo) { PEXCEPTION_RECORD exrec = exinfo->ExceptionRecord; LPSTR cmdline = GetCommandLine (); LPSTR prg = strtok (cmdline, " "); CHAR errmsg[1024]; #ifdef USE_EVENT_LOG HANDLE hEventSource; LPTSTR lpszStrings[1]; #endif if (! ISDB (DB_VERBOSE)) { sprintf (errmsg, _("%s: Interrupt/Exception caught (code = 0x%lx, addr = 0x%p)\n"), prg, exrec->ExceptionCode, exrec->ExceptionAddress); fprintf (stderr, errmsg); exit (255); } sprintf (errmsg, _("\nUnhandled exception filter called from program %s\nExceptionCode = %lx\nExceptionFlags = %lx\nExceptionAddress = 0x%p\n"), prg, exrec->ExceptionCode, exrec->ExceptionFlags, exrec->ExceptionAddress); if (exrec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && exrec->NumberParameters >= 2) sprintf (&errmsg[strlen(errmsg)], (exrec->ExceptionInformation[0] ? _("Access violation: write operation at address 0x%p\n") : _("Access violation: read operation at address 0x%p\n")), (PVOID)exrec->ExceptionInformation[1]); /* turn this on if we want to put stuff in the event log too */ #ifdef USE_EVENT_LOG hEventSource = RegisterEventSource (NULL, "GNU Make"); lpszStrings[0] = errmsg; if (hEventSource != NULL) { ReportEvent (hEventSource, /* handle of event source */ EVENTLOG_ERROR_TYPE, /* event type */ 0, /* event category */ 0, /* event ID */ NULL, /* current user's SID */ 1, /* strings in lpszStrings */ 0, /* no bytes of raw data */ lpszStrings, /* array of error strings */ NULL); /* no raw data */ (VOID) DeregisterEventSource (hEventSource); } #endif /* Write the error to stderr too */ fprintf (stderr, errmsg); #ifdef DEBUG return EXCEPTION_CONTINUE_SEARCH; #else exit (255); return (255); /* not reached */ #endif } # endif /* !KMK */ /* * On WIN32 systems we don't have the luxury of a /bin directory that * is mapped globally to every drive mounted to the system. Since make could * be invoked from any drive, and we don't want to propagate /bin/sh * to every single drive. Allow ourselves a chance to search for * a value for default shell here (if the default path does not exist). */ int find_and_set_default_shell (const char *token) { int sh_found = 0; char *atoken = 0; const char *search_token; const char *tokend; PATH_VAR(sh_path); extern const char *default_shell; if (!token) search_token = default_shell; else search_token = atoken = xstrdup (token); /* If the user explicitly requests the DOS cmd shell, obey that request. However, make sure that's what they really want by requiring the value of SHELL either equal, or have a final path element of, "cmd" or "cmd.exe" case-insensitive. */ tokend = search_token + strlen (search_token) - 3; if (((tokend == search_token || (tokend > search_token && (tokend[-1] == '/' || tokend[-1] == '\\'))) && !strcasecmp (tokend, "cmd")) || ((tokend - 4 == search_token || (tokend - 4 > search_token && (tokend[-5] == '/' || tokend[-5] == '\\'))) && !strcasecmp (tokend - 4, "cmd.exe"))) { batch_mode_shell = 1; unixy_shell = 0; # if 1 /* bird: sprintf? wtf. */ default_shell = unix_slashes (xstrdup (search_token)); # else sprintf (sh_path, "%s", search_token); default_shell = xstrdup (w32ify (sh_path, 0)); # endif DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"), default_shell)); sh_found = 1; } else if (!no_default_sh_exe && (token == NULL || !strcmp (search_token, default_shell))) { /* no new information, path already set or known */ sh_found = 1; } else if (_access (search_token, 0) == 0) { /* search token path was found */ # if 1 /* bird: sprintf? wtf. */ default_shell = unix_slashes (xstrdup (search_token)); # else sprintf (sh_path, "%s", search_token); default_shell = xstrdup (w32ify (sh_path, 0)); # endif DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"), default_shell)); sh_found = 1; } else { char *p; struct variable *v = lookup_variable (STRING_SIZE_TUPLE ("PATH")); /* Search Path for shell */ if (v && v->value) { char *ep; p = v->value; ep = strchr (p, PATH_SEPARATOR_CHAR); while (ep && *ep) { *ep = '\0'; # if 1 /* bird: insanity insurance */ _snprintf (sh_path, GET_PATH_MAX, "%s/%s", p, search_token); # else sprintf (sh_path, "%s/%s", p, search_token); # endif if (_access (sh_path, 0) == 0) { # if 1 /* bird: we can modify sh_path directly. */ default_shell = xstrdup (unix_slashes (sh_path)); # else default_shell = xstrdup (w32ify (sh_path, 0)); # endif sh_found = 1; *ep = PATH_SEPARATOR_CHAR; /* terminate loop */ p += strlen (p); } else { *ep = PATH_SEPARATOR_CHAR; p = ++ep; } ep = strchr (p, PATH_SEPARATOR_CHAR); } /* be sure to check last element of Path */ if (p && *p) { # if 1 /* bird: insanity insurance */ _snprintf (sh_path, GET_PATH_MAX, "%s/%s", p, search_token); # else sprintf (sh_path, "%s/%s", p, search_token); # endif if (_access (sh_path, 0) == 0) { # if 1 /* bird: we can modify sh_path directly. */ default_shell = xstrdup (unix_slashes (sh_path)); # else default_shell = xstrdup (w32ify (sh_path, 0)); # endif sh_found = 1; } } if (sh_found) DB (DB_VERBOSE, (_("find_and_set_shell() path search set default_shell = %s\n"), default_shell)); } } /* naive test */ if (!unixy_shell && sh_found && (strstr (default_shell, "sh") || strstr (default_shell, "SH"))) { unixy_shell = 1; batch_mode_shell = 0; } #ifdef BATCH_MODE_ONLY_SHELL batch_mode_shell = 1; #endif free (atoken); return (sh_found); } /* bird: */ # ifdef CONFIG_NEW_WIN32_CTRL_EVENT # include static UINT g_tidMainThread = 0; static int volatile g_sigPending = 0; /* lazy bird */ # ifndef _M_IX86 static LONG volatile g_lTriggered = 0; static CONTEXT g_Ctx; # endif # ifdef _M_IX86 static __declspec(naked) void dispatch_stub(void) { __asm { pushfd pushad cld } fflush(stdout); /*fprintf(stderr, "dbg: raising %s on the main thread (%d)\n", g_sigPending == SIGINT ? "SIGINT" : "SIGBREAK", _getpid());*/ raise(g_sigPending); __asm { popad popfd ret } } # else /* !_M_IX86 */ static void dispatch_stub(void) { fflush(stdout); /*fprintf(stderr, "dbg: raising %s on the main thread (%d)\n", g_sigPending == SIGINT ? "SIGINT" : "SIGBREAK", _getpid());*/ raise(g_sigPending); SetThreadContext(GetCurrentThread(), &g_Ctx); fprintf(stderr, "fatal error: SetThreadContext failed with last error %d\n", GetLastError()); for (;;) exit(131); } # endif /* !_M_IX86 */ static BOOL WINAPI ctrl_event(DWORD CtrlType) { int sig = (CtrlType == CTRL_C_EVENT) ? SIGINT : SIGBREAK; HANDLE hThread; CONTEXT Ctx; /*fprintf(stderr, "dbg: ctrl_event sig=%d\n", sig);*/ # ifndef _M_IX86 /* only once. */ if (InterlockedExchange(&g_lTriggered, 1)) { Sleep(1); return TRUE; } # endif /* open the main thread and suspend it. */ hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, g_tidMainThread); SuspendThread(hThread); /* Get the thread context and if we've get a valid Esp, dispatch it on the main thread otherwise raise the signal in the ctrl-event thread (this). */ memset(&Ctx, 0, sizeof(Ctx)); Ctx.ContextFlags = CONTEXT_FULL; if (GetThreadContext(hThread, &Ctx) # ifdef _M_IX86 && Ctx.Esp >= 0x1000 # else && Ctx.Rsp >= 0x1000 # endif ) { # ifdef _M_IX86 ((uintptr_t *)Ctx.Esp)[-1] = Ctx.Eip; Ctx.Esp -= sizeof(uintptr_t); Ctx.Eip = (uintptr_t)&dispatch_stub; # else g_Ctx = Ctx; Ctx.Rsp -= 0x80; Ctx.Rsp &= ~(uintptr_t)0xf; Ctx.Rsp += 8; /* (Stack aligned before call instruction, not after.) */ Ctx.Rip = (uintptr_t)&dispatch_stub; # endif SetThreadContext(hThread, &Ctx); g_sigPending = sig; ResumeThread(hThread); CloseHandle(hThread); } else { fprintf(stderr, "dbg: raising %s on the ctrl-event thread (%d)\n", sig == SIGINT ? "SIGINT" : "SIGBREAK", _getpid()); raise(sig); ResumeThread(hThread); CloseHandle(hThread); exit(130); } Sleep(1); return TRUE; } # endif /* CONFIG_NEW_WIN32_CTRL_EVENT */ #endif /* WINDOWS32 */ #ifdef KMK /* Determins the number of CPUs that are currently online. This is used to setup the default number of job slots. */ static int get_online_cpu_count(void) { # ifdef WINDOWS32 /* Windows: Count the active CPUs. */ int cpus; /* Process groups (W7+). */ typedef DWORD (WINAPI *PFNGETACTIVEPROCESSORCOUNT)(DWORD); PFNGETACTIVEPROCESSORCOUNT pfnGetActiveProcessorCount; pfnGetActiveProcessorCount = (PFNGETACTIVEPROCESSORCOUNT)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetActiveProcessorCount"); if (pfnGetActiveProcessorCount) cpus = pfnGetActiveProcessorCount(ALL_PROCESSOR_GROUPS); /* Legacy (<= Vista). */ else { int i; SYSTEM_INFO si; GetSystemInfo(&si); for (i = cpus = 0; i < sizeof(si.dwActiveProcessorMask) * 8; i++) { if (si.dwActiveProcessorMask & 1) cpus++; si.dwActiveProcessorMask >>= 1; } } if (!cpus) cpus = 1; # ifndef CONFIG_NEW_WIN_CHILDREN if (cpus > 64) cpus = 64; /* (wait for multiple objects limit) */ # endif return cpus; # elif defined(__OS2__) /* OS/2: Count the active CPUs. */ int cpus, i, j; MPAFFINITY mp; if (DosQueryThreadAffinity(AFNTY_SYSTEM, &mp)) return 1; for (j = cpus = 0; j < sizeof(mp.mask) / sizeof(mp.mask[0]); j++) for (i = 0; i < 32; i++) if (mp.mask[j] & (1UL << i)) cpus++; return cpus ? cpus : 1; # else /* UNIX like systems, try sysconf and sysctl. */ int cpus = -1; # if defined(CTL_HW) int mib[2]; size_t sz; # endif # ifdef _SC_NPROCESSORS_ONLN cpus = sysconf(_SC_NPROCESSORS_ONLN); if (cpus >= 1) return cpus; cpus = -1; # endif # if defined(CTL_HW) # ifdef HW_AVAILCPU sz = sizeof(cpus); mib[0] = CTL_HW; mib[1] = HW_AVAILCPU; if (!sysctl(mib, 2, &cpus, &sz, NULL, 0) && cpus >= 1) return cpus; cpus = -1; # endif /* HW_AVAILCPU */ sz = sizeof(cpus); mib[0] = CTL_HW; mib[1] = HW_NCPU; if (!sysctl(mib, 2, &cpus, &sz, NULL, 0) && cpus >= 1) return cpus; cpus = -1; # endif /* CTL_HW */ /* no idea / failure, just return 1. */ return 1; # endif } #endif /* KMK */ #ifdef __MSDOS__ static void msdos_return_to_initial_directory (void) { if (directory_before_chdir) chdir (directory_before_chdir); } #endif /* __MSDOS__ */ static void reset_jobserver (void) { jobserver_clear (); free (jobserver_auth); jobserver_auth = NULL; } #ifdef _AMIGA int main (int argc, char **argv) #else int main (int argc, char **argv, char **envp) #endif { static char *stdin_nm = 0; #ifdef CONFIG_WITH_MAKE_STATS unsigned long long uStartTick = CURRENT_CLOCK_TICK(); #endif int makefile_status = MAKE_SUCCESS; struct goaldep *read_files; PATH_VAR (current_directory); unsigned int restarts = 0; unsigned int syncing = 0; int argv_slots; #ifdef WINDOWS32 const char *unix_path = NULL; const char *windows32_path = NULL; # ifndef ELECTRIC_HEAP /* Drop this because it prevents JIT debugging. */ # ifndef KMK /* Don't want none of this crap. */ SetUnhandledExceptionFilter (handle_runtime_exceptions); # endif # endif /* !ELECTRIC_HEAP */ # ifdef KMK /* Clear the SEM_NOGPFAULTERRORBOX flag so WER will generate dumps when we run under cygwin. To void popups, set WER registry value DontShowUI to 1. */ if (getenv("KMK_NO_SET_ERROR_MODE") == NULL) SetErrorMode(SetErrorMode(0) & ~SEM_NOGPFAULTERRORBOX); # endif /* start off assuming we have no shell */ unixy_shell = 0; no_default_sh_exe = 1; #endif #ifdef CONFIG_WITH_PRINT_TIME_SWITCH make_start_ts = nano_timestamp (); #endif output_init (&make_sync); initialize_stopchar_map(); #ifdef SET_STACK_SIZE /* Get rid of any avoidable limit on stack size. */ { struct rlimit rlim; /* Set the stack limit huge so that alloca does not fail. */ if (getrlimit (RLIMIT_STACK, &rlim) == 0 && rlim.rlim_cur > 0 && rlim.rlim_cur < rlim.rlim_max) { stack_limit = rlim; rlim.rlim_cur = rlim.rlim_max; setrlimit (RLIMIT_STACK, &rlim); } else stack_limit.rlim_cur = 0; } #endif /* Needed for OS/2 */ initialize_main (&argc, &argv); #ifdef KMK init_kbuild (argc, argv); #endif #ifdef MAKE_MAINTAINER_MODE /* In maintainer mode we always enable verification. */ verify_flag = 1; #endif #if defined (__MSDOS__) && !defined (_POSIX_SOURCE) /* Request the most powerful version of 'system', to make up for the dumb default shell. */ __system_flags = (__system_redirect | __system_use_shell | __system_allow_multiple_cmds | __system_allow_long_cmds | __system_handle_null_commands | __system_emulate_chdir); #endif /* Set up gettext/internationalization support. */ setlocale (LC_ALL, ""); /* The cast to void shuts up compiler warnings on systems that disable NLS. */ #ifdef LOCALEDIR /* bird */ (void)bindtextdomain (PACKAGE, LOCALEDIR); (void)textdomain (PACKAGE); #endif #ifdef POSIX sigemptyset (&fatal_signal_set); #define ADD_SIG(sig) sigaddset (&fatal_signal_set, sig) #else #ifdef HAVE_SIGSETMASK fatal_signal_mask = 0; #define ADD_SIG(sig) fatal_signal_mask |= sigmask (sig) #else #define ADD_SIG(sig) (void)sig #endif #endif #define FATAL_SIG(sig) \ if (bsd_signal (sig, fatal_error_signal) == SIG_IGN) \ bsd_signal (sig, SIG_IGN); \ else \ ADD_SIG (sig); #ifdef SIGHUP FATAL_SIG (SIGHUP); #endif #ifdef SIGQUIT FATAL_SIG (SIGQUIT); #endif FATAL_SIG (SIGINT); FATAL_SIG (SIGTERM); #ifdef __MSDOS__ /* Windows 9X delivers FP exceptions in child programs to their parent! We don't want Make to die when a child divides by zero, so we work around that lossage by catching SIGFPE. */ FATAL_SIG (SIGFPE); #endif #ifdef SIGDANGER FATAL_SIG (SIGDANGER); #endif #ifdef SIGXCPU FATAL_SIG (SIGXCPU); #endif #ifdef SIGXFSZ FATAL_SIG (SIGXFSZ); #endif #ifdef KMK /* Get the incoming umask so we don't have to modify it later to get it. */ umask(g_fUMask = umask(0077)); #endif #ifdef CONFIG_NEW_WIN32_CTRL_EVENT /* bird: dispatch signals in our own way to try avoid deadlocks. */ g_tidMainThread = GetCurrentThreadId (); SetConsoleCtrlHandler (ctrl_event, TRUE); #endif /* CONFIG_NEW_WIN32_CTRL_EVENT */ #undef FATAL_SIG /* Do not ignore the child-death signal. This must be done before any children could possibly be created; otherwise, the wait functions won't work on systems with the SVR4 ECHILD brain damage, if our invoker is ignoring this signal. */ #ifdef HAVE_WAIT_NOHANG # if defined SIGCHLD (void) bsd_signal (SIGCHLD, SIG_DFL); # endif # if defined SIGCLD && SIGCLD != SIGCHLD (void) bsd_signal (SIGCLD, SIG_DFL); # endif #endif output_init (NULL); /* Figure out where this program lives. */ if (argv[0] == 0) argv[0] = (char *)""; if (argv[0][0] == '\0') #ifdef KMK program = "kmk"; #else program = "make"; #endif else { program = strrchr (argv[0], '/'); #if defined(__MSDOS__) || defined(__EMX__) if (program == 0) program = strrchr (argv[0], '\\'); else { /* Some weird environments might pass us argv[0] with both kinds of slashes; we must find the rightmost. */ char *p = strrchr (argv[0], '\\'); if (p && p > program) program = p; } if (program == 0 && argv[0][1] == ':') program = argv[0] + 1; #endif #ifdef WINDOWS32 if (program == 0) { /* Extract program from full path */ program = strrchr (argv[0], '\\'); if (program) { int argv0_len = strlen (program); if (argv0_len > 4 && streq (&program[argv0_len - 4], ".exe")) /* Remove .exe extension */ program[argv0_len - 4] = '\0'; } } #endif #ifdef VMS set_program_name (argv[0]); program = program_name; { const char *shell; char pwdbuf[256]; char *pwd; shell = getenv ("SHELL"); if (shell != NULL) vms_gnv_shell = 1; /* Need to know if CRTL set to report UNIX paths. Use getcwd as it works on all versions of VMS. */ pwd = getcwd(pwdbuf, 256); if (pwd[0] == '/') vms_report_unix_paths = 1; vms_use_mcr_command = get_vms_env_flag ("GNV$MAKE_USE_MCR", 0); vms_always_use_cmd_file = get_vms_env_flag ("GNV$MAKE_USE_CMD_FILE", 0); /* Legacy behavior is on VMS is older behavior that needed to be changed to be compatible with standard make behavior. For now only completely disable when running under a Bash shell. TODO: Update VMS built in recipes and macros to not need this behavior, at which time the default may change. */ vms_legacy_behavior = get_vms_env_flag ("GNV$MAKE_OLD_VMS", !vms_gnv_shell); /* VMS was changed to use a comma separator in the past, but that is incompatible with built in functions that expect space separated lists. Allow this to be selectively turned off. */ vms_comma_separator = get_vms_env_flag ("GNV$MAKE_COMMA", vms_legacy_behavior); /* Some Posix shell syntax options are incompatible with VMS syntax. VMS requires double quotes for strings and escapes quotes differently. When this option is active, VMS will try to simulate Posix shell simulations instead of using VMS DCL behavior. */ vms_unix_simulation = get_vms_env_flag ("GNV$MAKE_SHELL_SIM", !vms_legacy_behavior); } if (need_vms_symbol () && !vms_use_mcr_command) create_foreign_command (program_name, argv[0]); #else if (program == 0) program = argv[0]; else ++program; #endif } /* Set up to access user data (files). */ user_access (); # ifdef CONFIG_WITH_COMPILER kmk_cc_init (); # endif #ifdef CONFIG_WITH_ALLOC_CACHES initialize_global_alloc_caches (); #endif initialize_global_hash_tables (); #ifdef KMK init_kbuild_object (); #endif /* Figure out where we are. */ #ifdef WINDOWS32 if (getcwd_fs (current_directory, GET_PATH_MAX) == 0) #else if (getcwd (current_directory, GET_PATH_MAX) == 0) #endif { #ifdef HAVE_GETCWD perror_with_name ("getcwd", ""); #else OS (error, NILF, "getwd: %s", current_directory); #endif current_directory[0] = '\0'; directory_before_chdir = 0; } else directory_before_chdir = xstrdup (current_directory); #ifdef __MSDOS__ /* Make sure we will return to the initial directory, come what may. */ atexit (msdos_return_to_initial_directory); #endif /* Initialize the special variables. */ define_variable_cname (".VARIABLES", "", o_default, 0)->special = 1; /* define_variable_cname (".TARGETS", "", o_default, 0)->special = 1; */ define_variable_cname (".RECIPEPREFIX", "", o_default, 0)->special = 1; define_variable_cname (".SHELLFLAGS", "-c", o_default, 0); define_variable_cname (".LOADED", "", o_default, 0); /* Set up .FEATURES Use a separate variable because define_variable_cname() is a macro and some compilers (MSVC) don't like conditionals in macros. */ { const char *features = "target-specific order-only second-expansion" " else-if shortest-stem undefine oneshell" #ifndef NO_ARCHIVES " archives" #endif #ifdef MAKE_JOBSERVER " jobserver" #endif #ifndef NO_OUTPUT_SYNC " output-sync" #endif #ifdef MAKE_SYMLINKS " check-symlink" #endif #ifdef HAVE_GUILE " guile" #endif #ifdef MAKE_LOAD " load" #endif #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET " explicit-multitarget" #endif #ifdef CONFIG_WITH_PREPEND_ASSIGNMENT " prepend-assignment" #endif ; define_variable_cname (".FEATURES", features, o_default, 0); } #ifdef KMK /* Initialize the default number of jobs to the cpu/core/smt count. */ default_job_slots = arg_job_slots = job_slots = get_online_cpu_count (); #endif /* KMK */ /* Configure GNU Guile support */ guile_gmake_setup (NILF); /* Read in variables from the environment. It is important that this be done before $(MAKE) is figured out so its definitions will not be from the environment. */ #ifndef _AMIGA { unsigned int i; for (i = 0; envp[i] != 0; ++i) { struct variable *v; const char *ep = envp[i]; /* By default, export all variables culled from the environment. */ enum variable_export export = v_export; unsigned int len; while (! STOP_SET (*ep, MAP_EQUALS)) ++ep; /* If there's no equals sign it's a malformed environment. Ignore. */ if (*ep == '\0') continue; #ifdef WINDOWS32 if (!unix_path && strneq (envp[i], "PATH=", 5)) unix_path = ep+1; else if (!strnicmp (envp[i], "Path=", 5)) { if (!windows32_path) windows32_path = ep+1; /* PATH gets defined after the loop exits. */ continue; } #endif /* Length of the variable name, and skip the '='. */ len = ep++ - envp[i]; /* If this is MAKE_RESTARTS, check to see if the "already printed the enter statement" flag is set. */ if (len == 13 && strneq (envp[i], "MAKE_RESTARTS", 13)) { if (*ep == '-') { OUTPUT_TRACED (); ++ep; } restarts = (unsigned int) atoi (ep); export = v_noexport; } v = define_variable (envp[i], len, ep, o_env, 1); /* POSIX says the value of SHELL set in the makefile won't change the value of SHELL given to subprocesses. */ if (streq (v->name, "SHELL")) { #ifndef __MSDOS__ export = v_noexport; #endif #ifndef CONFIG_WITH_STRCACHE2 shell_var.name = xstrdup ("SHELL"); #else shell_var.name = v->name; #endif shell_var.length = 5; #ifndef CONFIG_WITH_VALUE_LENGTH shell_var.value = xstrdup (ep); #else shell_var.value = xstrndup (v->value, v->value_length); shell_var.value_length = v->value_length; #endif } v->export = export; } } #ifdef WINDOWS32 /* If we didn't find a correctly spelled PATH we define PATH as * either the first misspelled value or an empty string */ if (!unix_path) define_variable_cname ("PATH", windows32_path ? windows32_path : "", o_env, 1)->export = v_export; #endif #else /* For Amiga, read the ENV: device, ignoring all dirs */ { BPTR env, file, old; char buffer[1024]; int len; __aligned struct FileInfoBlock fib; env = Lock ("ENV:", ACCESS_READ); if (env) { old = CurrentDir (DupLock (env)); Examine (env, &fib); while (ExNext (env, &fib)) { if (fib.fib_DirEntryType < 0) /* File */ { /* Define an empty variable. It will be filled in variable_lookup(). Makes startup quite a bit faster. */ define_variable (fib.fib_FileName, strlen (fib.fib_FileName), "", o_env, 1)->export = v_export; } } UnLock (env); UnLock (CurrentDir (old)); } } #endif /* Decode the switches. */ decode_env_switches (STRING_SIZE_TUPLE ("GNUMAKEFLAGS")); /* Clear GNUMAKEFLAGS to avoid duplication. */ define_variable_cname ("GNUMAKEFLAGS", "", o_env, 0); #ifdef KMK decode_env_switches (STRING_SIZE_TUPLE ("KMK_FLAGS")); #else /* !KMK */ decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS")); #if 0 /* People write things like: MFLAGS="CC=gcc -pipe" "CFLAGS=-g" and we set the -p, -i and -e switches. Doesn't seem quite right. */ decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS")); #endif #endif /* !KMK */ /* In output sync mode we need to sync any output generated by reading the makefiles, such as in $(info ...) or stderr from $(shell ...) etc. */ syncing = make_sync.syncout = (output_sync == OUTPUT_SYNC_LINE || output_sync == OUTPUT_SYNC_TARGET); OUTPUT_SET (&make_sync); /* Remember the job slots set through the environment vs. command line. */ { int env_slots = arg_job_slots; arg_job_slots = INVALID_JOB_SLOTS; decode_switches (argc, (const char **)argv, 0); argv_slots = arg_job_slots; if (arg_job_slots == INVALID_JOB_SLOTS) arg_job_slots = env_slots; } /* Set a variable specifying whether stdout/stdin is hooked to a TTY. */ #ifdef HAVE_ISATTY if (isatty (fileno (stdout))) if (! lookup_variable (STRING_SIZE_TUPLE ("MAKE_TERMOUT"))) { const char *tty = TTYNAME (fileno (stdout)); define_variable_cname ("MAKE_TERMOUT", tty ? tty : DEFAULT_TTYNAME, o_default, 0)->export = v_export; } if (isatty (fileno (stderr))) if (! lookup_variable (STRING_SIZE_TUPLE ("MAKE_TERMERR"))) { const char *tty = TTYNAME (fileno (stderr)); define_variable_cname ("MAKE_TERMERR", tty ? tty : DEFAULT_TTYNAME, o_default, 0)->export = v_export; } #endif /* Reset in case the switches changed our minds. */ syncing = (output_sync == OUTPUT_SYNC_LINE || output_sync == OUTPUT_SYNC_TARGET); #ifdef KMK set_make_priority_and_affinity (); #endif if (make_sync.syncout && ! syncing) output_close (&make_sync); make_sync.syncout = syncing; OUTPUT_SET (&make_sync); /* Figure out the level of recursion. */ { struct variable *v = lookup_variable (STRING_SIZE_TUPLE (MAKELEVEL_NAME)); if (v && v->value[0] != '\0' && v->value[0] != '-') makelevel = (unsigned int) atoi (v->value); else makelevel = 0; } #ifdef WINDOWS32 if (suspend_flag) { fprintf (stderr, "%s (pid = %ld)\n", argv[0], GetCurrentProcessId ()); fprintf (stderr, _("%s is suspending for 30 seconds..."), argv[0]); Sleep (30 * 1000); fprintf (stderr, _("done sleep(30). Continuing.\n")); } #endif /* Set always_make_flag if -B was given and we've not restarted already. */ always_make_flag = always_make_set && (restarts == 0); /* Print version information, and exit. */ if (print_version_flag) { print_version (); die (MAKE_SUCCESS); } if (ISDB (DB_BASIC)) print_version (); #ifndef VMS /* Set the "MAKE_COMMAND" variable to the name we were invoked with. (If it is a relative pathname with a slash, prepend our directory name so the result will run the same program regardless of the current dir. If it is a name with no slash, we can only hope that PATH did not find it in the current directory.) */ #ifdef WINDOWS32 /* * Convert from backslashes to forward slashes for * programs like sh which don't like them. Shouldn't * matter if the path is one way or the other for * CreateProcess(). */ if (strpbrk (argv[0], "/:\\") || strstr (argv[0], "..") || strneq (argv[0], "//", 2)) # if 1 /* bird */ { PATH_VAR (tmp_path_buf); argv[0] = xstrdup (unix_slashes_resolved (argv[0], tmp_path_buf, GET_PATH_MAX)); } # else /* bird */ //argv[0] = xstrdup (w32ify (argv[0], 1)); # endif /* bird */ #else /* WINDOWS32 */ #if defined (__MSDOS__) || defined (__EMX__) if (strchr (argv[0], '\\')) { char *p; argv[0] = xstrdup (argv[0]); for (p = argv[0]; *p; p++) if (*p == '\\') *p = '/'; } /* If argv[0] is not in absolute form, prepend the current directory. This can happen when Make is invoked by another DJGPP program that uses a non-absolute name. */ if (current_directory[0] != '\0' && argv[0] != 0 && (argv[0][0] != '/' && (argv[0][0] == '\0' || argv[0][1] != ':')) # ifdef __EMX__ /* do not prepend cwd if argv[0] contains no '/', e.g. "make" */ && (strchr (argv[0], '/') != 0 || strchr (argv[0], '\\') != 0) # endif ) argv[0] = xstrdup (concat (3, current_directory, "/", argv[0])); #else /* !__MSDOS__ */ if (current_directory[0] != '\0' && argv[0] != 0 && argv[0][0] != '/' && strchr (argv[0], '/') != 0 #ifdef HAVE_DOS_PATHS && (argv[0][0] != '\\' && (!argv[0][0] || argv[0][1] != ':')) && strchr (argv[0], '\\') != 0 #endif ) argv[0] = xstrdup (concat (3, current_directory, "/", argv[0])); #endif /* !__MSDOS__ */ #endif /* WINDOWS32 */ #endif /* We may move, but until we do, here we are. */ starting_directory = current_directory; /* Set up the job_slots value and the jobserver. This can't be usefully set in the makefile, and we want to verify the authorization is valid before make has a chance to start using it for something else. */ if (jobserver_auth) { if (argv_slots == INVALID_JOB_SLOTS) { if (jobserver_parse_auth (jobserver_auth)) { /* Success! Use the jobserver. */ job_slots = 0; goto job_setup_complete; } O (error, NILF, _("warning: jobserver unavailable: using -j1. Add '+' to parent make rule.")); arg_job_slots = 1; } /* The user provided a -j setting on the command line: use it. */ else if (!restarts) /* If restarts is >0 we already printed this message. */ O (error, NILF, _("warning: -jN forced in submake: disabling jobserver mode.")); /* We failed to use our parent's jobserver. */ reset_jobserver (); job_slots = (unsigned int)arg_job_slots; } else if (arg_job_slots == INVALID_JOB_SLOTS) #ifdef KMK job_slots = default_job_slots; /* The default is set to CPU count early in main. */ #else /* The default is one job at a time. */ job_slots = 1; #endif else /* Use whatever was provided. */ job_slots = (unsigned int)arg_job_slots; job_setup_complete: #if defined (WINDOWS32) && defined(CONFIG_NEW_WIN_CHILDREN) /* Initialize the windows child management. */ MkWinChildInit(job_slots); #endif /* The extra indirection through $(MAKE_COMMAND) is done for hysterical raisins. */ #ifdef VMS if (vms_use_mcr_command) define_variable_cname ("MAKE_COMMAND", vms_command (argv[0]), o_default, 0); else define_variable_cname ("MAKE_COMMAND", program, o_default, 0); #else define_variable_cname ("MAKE_COMMAND", argv[0], o_default, 0); #endif define_variable_cname ("MAKE", "$(MAKE_COMMAND)", o_default, 1); #ifdef KMK (void) define_variable ("KMK", 3, argv[0], o_default, 1); #endif if (command_variables != 0) { struct command_variable *cv; struct variable *v; unsigned int len = 0; char *value, *p; /* Figure out how much space will be taken up by the command-line variable definitions. */ for (cv = command_variables; cv != 0; cv = cv->next) { v = cv->variable; len += 2 * strlen (v->name); if (! v->recursive) ++len; ++len; len += 2 * strlen (v->value); ++len; } /* Now allocate a buffer big enough and fill it. */ p = value = alloca (len); for (cv = command_variables; cv != 0; cv = cv->next) { v = cv->variable; p = quote_for_env (p, v->name); if (! v->recursive) *p++ = ':'; *p++ = '='; p = quote_for_env (p, v->value); *p++ = ' '; } p[-1] = '\0'; /* Kill the final space and terminate. */ /* Define an unchangeable variable with a name that no POSIX.2 makefile could validly use for its own variable. */ define_variable_cname ("-*-command-variables-*-", value, o_automatic, 0); /* Define the variable; this will not override any user definition. Normally a reference to this variable is written into the value of MAKEFLAGS, allowing the user to override this value to affect the exported value of MAKEFLAGS. In POSIX-pedantic mode, we cannot allow the user's setting of MAKEOVERRIDES to affect MAKEFLAGS, so a reference to this hidden variable is written instead. */ #ifdef KMK define_variable_cname ("KMK_OVERRIDES", "${-*-command-variables-*-}", o_env, 1); #else define_variable_cname ("MAKEOVERRIDES", "${-*-command-variables-*-}", o_env, 1); #endif #ifdef VMS vms_export_dcl_symbol ("MAKEOVERRIDES", "${-*-command-variables-*-}"); #endif } /* If there were -C flags, move ourselves about. */ if (directories != 0) { unsigned int i; for (i = 0; directories->list[i] != 0; ++i) { const char *dir = directories->list[i]; #ifdef WINDOWS32 /* WINDOWS32 chdir() doesn't work if the directory has a trailing '/' But allow -C/ just in case someone wants that. */ { char *p = (char *)dir + strlen (dir) - 1; while (p > dir && (p[0] == '/' || p[0] == '\\')) --p; p[1] = '\0'; } #endif if (chdir (dir) < 0) pfatal_with_name (dir); } } #ifdef KMK /* If no [Mm]akefile.kmk in the current directory, we may want to ascend to a parent directory that contains one. This is explicitly ordered by placing [Mm]akefile.kup files in the directory. And since 2024-11-04 we automatically do this when here is a goal (e.g. main.o) on the command line and no other default makefiles around. This new behvior simplifies compiling individial source files from the editor without requiring us to sprinkle Makefile.kup-files around the tree, esp. in 3rd party code. If no -C arguments were given, fake one to indicate chdir. */ if (makefiles == 0) { struct stat st; if (stat ("Makefile.kmk", &st) < 0 && stat ("makefile.kmk", &st) < 0) { static char fake_path[3*16 + 32] = ".."; char *cur = &fake_path[2]; int up_levels = 1; /* If there are any .kup-files. */ if (( stat ("Makefile.kup", &st) == 0 && S_ISREG (st.st_mode) ) || ( stat ("makefile.kup", &st) == 0 && S_ISREG (st.st_mode) ) ) { while (up_levels < 16) { /* File with higher precedence. */ strcpy (cur, "/Makefile.kmk"); if (stat (fake_path, &st) == 0) break; cur[1] = 'm'; if (stat (fake_path, &st) == 0) break; /* the .kup files */ strcpy (cur, "/Makefile.kup"); if ( stat (fake_path, &st) != 0 || !S_ISREG (st.st_mode)) { cur[1] = 'm'; if ( stat (fake_path, &st) != 0 || !S_ISREG (st.st_mode)) break; } /* ok */ strcpy (cur, "/.."); cur += 3; up_levels++; } if (up_levels >= 16) O (fatal, NILF, _("Makefile.kup recursion is too deep.")); } /* If there are no default makefiles either and one or more goals on the command line, go looking for kmk-files up the parent tree. */ else if (goals != NULL && stat ("GNUmakefile", &st) < 0 && stat ("makefile", &st) < 0 && stat ("Makefile", &st) < 0 #ifdef WINDOWS32 && stat ("makefile.mak", &st) < 0 #endif ) while (up_levels < 16) { /* File with higher precedence.s */ strcpy (cur, "/Makefile.kmk"); if (stat (fake_path, &st) == 0) break; cur[1] = 'm'; if (stat (fake_path, &st) == 0) break; /* ok */ strcpy (cur, "/.."); cur += 3; up_levels++; } else up_levels = 0; if (up_levels > 0 && up_levels < 16) { /* attempt to change to the directory. */ *cur = '\0'; if (chdir (fake_path) < 0) pfatal_with_name (fake_path); /* add the string to the directories. */ if (!directories) { directories = xmalloc (sizeof(*directories)); directories->list = xmalloc (5 * sizeof (char *)); directories->max = 5; directories->idx = 0; } else if (directories->idx == directories->max - 1) { directories->max += 5; directories->list = xrealloc ((void *)directories->list, directories->max * sizeof (char *)); } directories->list[directories->idx++] = fake_path; } } } #endif /* KMK */ #ifdef WINDOWS32 /* * THIS BLOCK OF CODE MUST COME AFTER chdir() CALL ABOVE IN ORDER * TO NOT CONFUSE THE DEPENDENCY CHECKING CODE IN implicit.c. * * The functions in dir.c can incorrectly cache information for "." * before we have changed directory and this can cause file * lookups to fail because the current directory (.) was pointing * at the wrong place when it was first evaluated. */ #ifdef KMK /* this is really a candidate for all platforms... */ { extern const char *default_shell; const char *bin = get_kbuild_bin_path(); char *newshell; size_t len = strlen (bin); default_shell = newshell = xmalloc (len + sizeof("/kmk_ash.exe")); memcpy (newshell, bin, len); strcpy (newshell + len, "/kmk_ash.exe"); no_default_sh_exe = 0; batch_mode_shell = 1; unixy_shell = 1; } #else /* !KMK */ no_default_sh_exe = !find_and_set_default_shell (NULL); #endif /* !KMK */ #endif /* WINDOWS32 */ /* Except under -s, always do -w in sub-makes and under -C. */ if (!silent_flag && (directories != 0 || makelevel > 0)) print_directory_flag = 1; /* Let the user disable that with --no-print-directory. */ if (inhibit_print_directory_flag) print_directory_flag = 0; /* If -R was given, set -r too (doesn't make sense otherwise!) */ if (no_builtin_variables_flag) no_builtin_rules_flag = 1; /* Construct the list of include directories to search. */ construct_include_path (include_directories == 0 ? 0 : include_directories->list); /* If we chdir'ed, figure out where we are now. */ if (directories) { #ifdef WINDOWS32 if (getcwd_fs (current_directory, GET_PATH_MAX) == 0) #else if (getcwd (current_directory, GET_PATH_MAX) == 0) #endif { #ifdef HAVE_GETCWD perror_with_name ("getcwd", ""); #else OS (error, NILF, "getwd: %s", current_directory); #endif starting_directory = 0; } else starting_directory = current_directory; } define_variable_cname ("CURDIR", current_directory, o_file, 0); /* Read any stdin makefiles into temporary files. */ if (makefiles != 0) { unsigned int i; for (i = 0; i < makefiles->idx; ++i) if (makefiles->list[i][0] == '-' && makefiles->list[i][1] == '\0') { /* This makefile is standard input. Since we may re-exec and thus re-read the makefiles, we read standard input into a temporary file and read from that. */ FILE *outfile; char *template; const char *tmpdir; if (stdin_nm) O (fatal, NILF, _("Makefile from standard input specified twice.")); #ifdef VMS # define DEFAULT_TMPDIR "/sys$scratch/" #else # ifdef P_tmpdir # define DEFAULT_TMPDIR P_tmpdir # else # define DEFAULT_TMPDIR "/tmp" # endif #endif #define DEFAULT_TMPFILE "GmXXXXXX" if (((tmpdir = getenv ("TMPDIR")) == NULL || *tmpdir == '\0') #if defined (__MSDOS__) || defined (WINDOWS32) || defined (__EMX__) /* These are also used commonly on these platforms. */ && ((tmpdir = getenv ("TEMP")) == NULL || *tmpdir == '\0') && ((tmpdir = getenv ("TMP")) == NULL || *tmpdir == '\0') #endif ) tmpdir = DEFAULT_TMPDIR; template = alloca (strlen (tmpdir) + CSTRLEN (DEFAULT_TMPFILE) + 2); strcpy (template, tmpdir); #ifdef HAVE_DOS_PATHS if (strchr ("/\\", template[strlen (template) - 1]) == NULL) strcat (template, "/"); #else # ifndef VMS if (template[strlen (template) - 1] != '/') strcat (template, "/"); # endif /* !VMS */ #endif /* !HAVE_DOS_PATHS */ strcat (template, DEFAULT_TMPFILE); outfile = output_tmpfile (&stdin_nm, template); if (outfile == 0) pfatal_with_name (_("fopen (temporary file)")); while (!feof (stdin) && ! ferror (stdin)) { char buf[2048]; unsigned int n = fread (buf, 1, sizeof (buf), stdin); if (n > 0 && fwrite (buf, 1, n, outfile) != n) pfatal_with_name (_("fwrite (temporary file)")); } fclose (outfile); /* Replace the name that read_all_makefiles will see with the name of the temporary file. */ makefiles->list[i] = strcache_add (stdin_nm); /* Make sure the temporary file will not be remade. */ { struct file *f = enter_file (strcache_add (stdin_nm)); f->updated = 1; f->update_status = us_success; f->command_state = cs_finished; /* Can't be intermediate, or it'll be removed too early for make re-exec. */ f->intermediate = 0; f->dontcare = 0; } } } #if !defined(__EMX__) || defined(__KLIBC__) /* Don't use a SIGCHLD handler for good old EMX (bird) */ #if !defined(HAVE_WAIT_NOHANG) || defined(MAKE_JOBSERVER) /* Set up to handle children dying. This must be done before reading in the makefiles so that 'shell' function calls will work. If we don't have a hanging wait we have to fall back to old, broken functionality here and rely on the signal handler and counting children. If we're using the jobs pipe we need a signal handler so that SIGCHLD is not ignored; we need it to interrupt the read(2) of the jobserver pipe if we're waiting for a token. If none of these are true, we don't need a signal handler at all. */ { # if defined SIGCHLD bsd_signal (SIGCHLD, child_handler); # endif # if defined SIGCLD && SIGCLD != SIGCHLD bsd_signal (SIGCLD, child_handler); # endif } #ifdef HAVE_PSELECT /* If we have pselect() then we need to block SIGCHLD so it's deferred. */ { sigset_t block; sigemptyset (&block); sigaddset (&block, SIGCHLD); if (sigprocmask (SIG_SETMASK, &block, NULL) < 0) pfatal_with_name ("sigprocmask(SIG_SETMASK, SIGCHLD)"); } #endif #endif #endif /* Let the user send us SIGUSR1 to toggle the -d flag during the run. */ #ifdef SIGUSR1 bsd_signal (SIGUSR1, debug_signal_handler); #endif /* Define the initial list of suffixes for old-style rules. */ set_default_suffixes (); /* Define the file rules for the built-in suffix rules. These will later be converted into pattern rules. We used to do this in install_default_implicit_rules, but since that happens after reading makefiles, it results in the built-in pattern rules taking precedence over makefile-specified suffix rules, which is wrong. */ install_default_suffix_rules (); /* Define some internal and special variables. */ define_automatic_variables (); /* Set up the MAKEFLAGS and MFLAGS variables for makefiles to see. Initialize it to be exported but allow the makefile to reset it. */ define_makeflags (0, 0)->export = v_export; /* Define the default variables. */ define_default_variables (); default_file = enter_file (strcache_add (".DEFAULT")); default_goal_var = define_variable_cname (".DEFAULT_GOAL", "", o_file, 0); /* Evaluate all strings provided with --eval. Also set up the $(-*-eval-flags-*-) variable. */ if (eval_strings) { char *p, *value; unsigned int i; unsigned int len = (CSTRLEN ("--eval=") + 1) * eval_strings->idx; for (i = 0; i < eval_strings->idx; ++i) { #ifndef CONFIG_WITH_VALUE_LENGTH p = xstrdup (eval_strings->list[i]); len += 2 * strlen (p); eval_buffer (p, NULL); #else unsigned int sub_len = strlen(eval_strings->list[i]); p = xstrndup (eval_strings->list[i], sub_len); len += 2 * sub_len; eval_buffer (p, NULL, p + sub_len); #endif free (p); } p = value = alloca (len); for (i = 0; i < eval_strings->idx; ++i) { strcpy (p, "--eval="); p += CSTRLEN ("--eval="); p = quote_for_env (p, eval_strings->list[i]); *(p++) = ' '; } p[-1] = '\0'; define_variable_cname ("-*-eval-flags-*-", value, o_automatic, 0); } /* Read all the makefiles. */ read_files = read_all_makefiles (makefiles == 0 ? 0 : makefiles->list); #ifdef WINDOWS32 /* look one last time after reading all Makefiles */ if (no_default_sh_exe) no_default_sh_exe = !find_and_set_default_shell (NULL); #endif /* WINDOWS32 */ #if defined (__MSDOS__) || defined (__EMX__) || defined (VMS) /* We need to know what kind of shell we will be using. */ { extern int _is_unixy_shell (const char *_path); struct variable *shv = lookup_variable (STRING_SIZE_TUPLE ("SHELL")); extern int unixy_shell; extern const char *default_shell; if (shv && *shv->value) { char *shell_path = recursively_expand (shv); if (shell_path && _is_unixy_shell (shell_path)) unixy_shell = 1; else unixy_shell = 0; if (shell_path) default_shell = shell_path; } } #endif /* __MSDOS__ || __EMX__ */ { int old_builtin_rules_flag = no_builtin_rules_flag; int old_builtin_variables_flag = no_builtin_variables_flag; /* Decode switches again, for variables set by the makefile. */ decode_env_switches (STRING_SIZE_TUPLE ("GNUMAKEFLAGS")); /* Clear GNUMAKEFLAGS to avoid duplication. */ define_variable_cname ("GNUMAKEFLAGS", "", o_override, 0); #ifdef KMK decode_env_switches (STRING_SIZE_TUPLE ("KMK_FLAGS")); #else /* !KMK */ decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS")); #if 0 decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS")); #endif #endif /* !KMK */ /* Reset in case the switches changed our mind. */ syncing = (output_sync == OUTPUT_SYNC_LINE || output_sync == OUTPUT_SYNC_TARGET); if (make_sync.syncout && ! syncing) output_close (&make_sync); make_sync.syncout = syncing; OUTPUT_SET (&make_sync); /* If we've disabled builtin rules, get rid of them. */ if (no_builtin_rules_flag && ! old_builtin_rules_flag) { if (suffix_file->builtin) { free_dep_chain (suffix_file->deps); suffix_file->deps = 0; } define_variable_cname ("SUFFIXES", "", o_default, 0); } /* If we've disabled builtin variables, get rid of them. */ if (no_builtin_variables_flag && ! old_builtin_variables_flag) undefine_default_variables (); } #if defined (__MSDOS__) || defined (__EMX__) || defined (VMS) if (arg_job_slots != 1 # ifdef __EMX__ && _osmode != OS2_MODE /* turn off -j if we are in DOS mode */ # endif ) { O (error, NILF, _("Parallel jobs (-j) are not supported on this platform.")); O (error, NILF, _("Resetting to single job (-j1) mode.")); arg_job_slots = job_slots = 1; } #endif /* If we have >1 slot at this point, then we're a top-level make. Set up the jobserver. Every make assumes that it always has one job it can run. For the submakes it's the token they were given by their parent. For the top make, we just subtract one from the number the user wants. */ if (job_slots > 1 && jobserver_setup (job_slots - 1)) { /* Fill in the jobserver_auth for our children. */ jobserver_auth = jobserver_get_auth (); if (jobserver_auth) { /* We're using the jobserver so set job_slots to 0. */ master_job_slots = job_slots; job_slots = 0; } } /* If we're not using parallel jobs, then we don't need output sync. This is so people can enable output sync in GNUMAKEFLAGS or similar, but not have it take effect unless parallel builds are enabled. */ if (syncing && job_slots == 1) { OUTPUT_UNSET (); output_close (&make_sync); syncing = 0; output_sync = OUTPUT_SYNC_NONE; } #ifndef MAKE_SYMLINKS if (check_symlink_flag) { O (error, NILF, _("Symbolic links not supported: disabling -L.")); check_symlink_flag = 0; } #endif /* Set up MAKEFLAGS and MFLAGS again, so they will be right. */ define_makeflags (1, 0); /* Make each 'struct goaldep' point at the 'struct file' for the file depended on. Also do magic for special targets. */ snap_deps (); /* Convert old-style suffix rules to pattern rules. It is important to do this before installing the built-in pattern rules below, so that makefile-specified suffix rules take precedence over built-in pattern rules. */ convert_to_pattern (); /* Install the default implicit pattern rules. This used to be done before reading the makefiles. But in that case, built-in pattern rules were in the chain before user-defined ones, so they matched first. */ install_default_implicit_rules (); /* Compute implicit rule limits. */ count_implicit_rule_limits (); /* Construct the listings of directories in VPATH lists. */ build_vpath_lists (); /* Mark files given with -o flags as very old and as having been updated already, and files given with -W flags as brand new (time-stamp as far as possible into the future). If restarts is set we'll do -W later. */ if (old_files != 0) { const char **p; for (p = old_files->list; *p != 0; ++p) { struct file *f = enter_file (*p); f->last_mtime = f->mtime_before_update = OLD_MTIME; f->updated = 1; f->update_status = us_success; f->command_state = cs_finished; } } if (!restarts && new_files != 0) { const char **p; for (p = new_files->list; *p != 0; ++p) { struct file *f = enter_file (*p); f->last_mtime = f->mtime_before_update = NEW_MTIME; } } /* Initialize the remote job module. */ remote_setup (); /* Dump any output we've collected. */ OUTPUT_UNSET (); output_close (&make_sync); if (read_files != 0) { /* Update any makefiles if necessary. */ FILE_TIMESTAMP *makefile_mtimes = 0; unsigned int mm_idx = 0; char **aargv = NULL; const char **nargv; int nargc; enum update_status status; DB (DB_BASIC, (_("Updating makefiles....\n"))); /* Remove any makefiles we don't want to try to update. Also record the current modtimes so we can compare them later. */ { register struct goaldep *d, *last; last = 0; d = read_files; while (d != 0) { struct file *f = d->file; if (f->double_colon) for (f = f->double_colon; f != NULL; f = f->prev) { if (f->deps == 0 && f->cmds != 0) { /* This makefile is a :: target with commands, but no dependencies. So, it will always be remade. This might well cause an infinite loop, so don't try to remake it. (This will only happen if your makefiles are written exceptionally stupidly; but if you work for Athena, that's how you write your makefiles.) */ DB (DB_VERBOSE, (_("Makefile '%s' might loop; not remaking it.\n"), f->name)); if (last == 0) read_files = d->next; else last->next = d->next; /* Free the storage. */ free_goaldep (d); d = last == 0 ? read_files : last->next; break; } } if (f == NULL || !f->double_colon) { makefile_mtimes = xrealloc (makefile_mtimes, (mm_idx+1) * sizeof (FILE_TIMESTAMP)); makefile_mtimes[mm_idx++] = file_mtime_no_search (d->file); last = d; d = d->next; } } } /* Set up 'MAKEFLAGS' specially while remaking makefiles. */ define_makeflags (1, 1); { int orig_db_level = db_level; if (! ISDB (DB_MAKEFILES)) db_level = DB_NONE; rebuilding_makefiles = 1; status = update_goal_chain (read_files); rebuilding_makefiles = 0; db_level = orig_db_level; } switch (status) { case us_question: /* The only way this can happen is if the user specified -q and asked for one of the makefiles to be remade as a target on the command line. Since we're not actually updating anything with -q we can treat this as "did nothing". */ case us_none: /* Did nothing. */ break; case us_failed: /* Failed to update. Figure out if we care. */ { /* Nonzero if any makefile was successfully remade. */ int any_remade = 0; /* Nonzero if any makefile we care about failed in updating or could not be found at all. */ int any_failed = 0; unsigned int i; struct goaldep *d; for (i = 0, d = read_files; d != 0; ++i, d = d->next) { if (d->file->updated) { /* This makefile was updated. */ if (d->file->update_status == us_success) { /* It was successfully updated. */ any_remade |= (file_mtime_no_search (d->file) != makefile_mtimes[i]); } else if (! (d->flags & RM_DONTCARE)) { FILE_TIMESTAMP mtime; /* The update failed and this makefile was not from the MAKEFILES variable, so we care. */ OS (error, NILF, _("Failed to remake makefile '%s'."), d->file->name); mtime = file_mtime_no_search (d->file); any_remade |= (mtime != NONEXISTENT_MTIME && mtime != makefile_mtimes[i]); makefile_status = MAKE_FAILURE; } } else /* This makefile was not found at all. */ if (! (d->flags & RM_DONTCARE)) { const char *dnm = dep_name (d); size_t l = strlen (dnm); /* This is a makefile we care about. See how much. */ if (d->flags & RM_INCLUDED) /* An included makefile. We don't need to die, but we do want to complain. */ error (NILF, l, _("Included makefile '%s' was not found."), dnm); else { /* A normal makefile. We must die later. */ error (NILF, l, _("Makefile '%s' was not found"), dnm); any_failed = 1; } } } /* Reset this to empty so we get the right error message below. */ read_files = 0; if (any_remade) goto re_exec; if (any_failed) die (MAKE_FAILURE); break; } case us_success: re_exec: /* Updated successfully. Re-exec ourselves. */ remove_intermediates (0); if (print_data_base_flag) print_data_base (); clean_jobserver (0); if (makefiles != 0) { /* These names might have changed. */ int i, j = 0; for (i = 1; i < argc; ++i) if (strneq (argv[i], "-f", 2)) /* XXX */ { if (argv[i][2] == '\0') /* This cast is OK since we never modify argv. */ argv[++i] = (char *) makefiles->list[j]; else argv[i] = xstrdup (concat (2, "-f", makefiles->list[j])); ++j; } } /* Add -o option for the stdin temporary file, if necessary. */ nargc = argc; if (stdin_nm) { void *m = xmalloc ((nargc + 2) * sizeof (char *)); aargv = m; memcpy (aargv, argv, argc * sizeof (char *)); aargv[nargc++] = xstrdup (concat (2, "-o", stdin_nm)); aargv[nargc] = 0; nargv = m; } else nargv = (const char**)argv; if (directories != 0 && directories->idx > 0) { int bad = 1; if (directory_before_chdir != 0) { if (chdir (directory_before_chdir) < 0) perror_with_name ("chdir", ""); else bad = 0; } if (bad) O (fatal, NILF, _("Couldn't change back to original directory.")); } ++restarts; if (ISDB (DB_BASIC)) { const char **p; printf (_("Re-executing[%u]:"), restarts); for (p = nargv; *p != 0; ++p) printf (" %s", *p); putchar ('\n'); fflush (stdout); } #ifndef _AMIGA { char **p; for (p = environ; *p != 0; ++p) { if (strneq (*p, MAKELEVEL_NAME "=", MAKELEVEL_LENGTH+1)) { *p = alloca (40); sprintf (*p, "%s=%u", MAKELEVEL_NAME, makelevel); #ifdef VMS vms_putenv_symbol (*p); #endif } else if (strneq (*p, "MAKE_RESTARTS=", CSTRLEN ("MAKE_RESTARTS="))) { *p = alloca (40); sprintf (*p, "MAKE_RESTARTS=%s%u", OUTPUT_IS_TRACED () ? "-" : "", restarts); restarts = 0; } } } #else /* AMIGA */ { char buffer[256]; sprintf (buffer, "%u", makelevel); SetVar (MAKELEVEL_NAME, buffer, -1, GVF_GLOBAL_ONLY); sprintf (buffer, "%s%u", OUTPUT_IS_TRACED () ? "-" : "", restarts); SetVar ("MAKE_RESTARTS", buffer, -1, GVF_GLOBAL_ONLY); restarts = 0; } #endif /* If we didn't set the restarts variable yet, add it. */ if (restarts) { char *b = alloca (40); sprintf (b, "MAKE_RESTARTS=%s%u", OUTPUT_IS_TRACED () ? "-" : "", restarts); putenv (b); } fflush (stdout); fflush (stderr); #ifdef _AMIGA exec_command (nargv); exit (0); #elif defined (__EMX__) { /* It is not possible to use execve() here because this would cause the parent process to be terminated with exit code 0 before the child process has been terminated. Therefore it may be the best solution simply to spawn the child process including all file handles and to wait for its termination. */ int pid; int r; pid = child_execute_job (NULL, 1, nargv, environ); /* is this loop really necessary? */ do { pid = wait (&r); } while (pid <= 0); /* use the exit code of the child process */ exit (WIFEXITED(r) ? WEXITSTATUS(r) : EXIT_FAILURE); } #else #ifdef SET_STACK_SIZE /* Reset limits, if necessary. */ if (stack_limit.rlim_cur) setrlimit (RLIMIT_STACK, &stack_limit); #endif # if !defined(WINDOWS32) || !defined(CONFIG_NEW_WIN_CHILDREN) exec_command ((char **)nargv, environ); # else MkWinChildReExecMake ((char **)nargv, environ); # endif #endif free (aargv); break; } /* Free the makefile mtimes. */ free (makefile_mtimes); } /* Set up 'MAKEFLAGS' again for the normal targets. */ define_makeflags (1, 0); /* Set always_make_flag if -B was given. */ always_make_flag = always_make_set; /* If restarts is set we haven't set up -W files yet, so do that now. */ if (restarts && new_files != 0) { const char **p; for (p = new_files->list; *p != 0; ++p) { struct file *f = enter_file (*p); f->last_mtime = f->mtime_before_update = NEW_MTIME; } } /* If there is a temp file from reading a makefile from stdin, get rid of it now. */ if (stdin_nm && unlink (stdin_nm) < 0 && errno != ENOENT) perror_with_name (_("unlink (temporary file): "), stdin_nm); /* If there were no command-line goals, use the default. */ if (goals == 0) { char *p; if (default_goal_var->recursive) p = variable_expand (default_goal_var->value); else { p = variable_buffer_output (variable_buffer, default_goal_var->value, strlen (default_goal_var->value)); *p = '\0'; p = variable_buffer; } if (*p != '\0') { struct file *f = lookup_file (p); /* If .DEFAULT_GOAL is a non-existent target, enter it into the table and let the standard logic sort it out. */ if (f == 0) { struct nameseq *ns; ns = PARSE_SIMPLE_SEQ (&p, struct nameseq); if (ns) { /* .DEFAULT_GOAL should contain one target. */ if (ns->next != 0) O (fatal, NILF, _(".DEFAULT_GOAL contains more than one target")); #ifndef CONFIG_WITH_VALUE_LENGTH f = enter_file (strcache_add (ns->name)); #else f = enter_file (ns->name); #endif ns->name = 0; /* It was reused by enter_file(). */ free_ns_chain (ns); } } if (f) { goals = alloc_goaldep (); goals->file = f; } } } else lastgoal->next = 0; if (!goals) { if (read_files == 0) O (fatal, NILF, _("No targets specified and no makefile found")); O (fatal, NILF, _("No targets")); } /* Update the goals. */ DB (DB_BASIC, (_("Updating goal targets....\n"))); { switch (update_goal_chain (goals)) { case us_none: /* Nothing happened. */ /* FALLTHROUGH */ case us_success: /* Keep the previous result. */ break; case us_question: /* We are under -q and would run some commands. */ makefile_status = MAKE_TROUBLE; break; case us_failed: /* Updating failed. POSIX.2 specifies exit status >1 for this; */ makefile_status = MAKE_FAILURE; break; } /* If we detected some clock skew, generate one last warning */ if (clock_skew_detected) O (error, NILF, _("warning: Clock skew detected. Your build may be incomplete.")); MAKE_STATS_2(if (uStartTick) printf("main ticks elapsed: %llu\n", (unsigned long long)(CURRENT_CLOCK_TICK() - uStartTick)) ); /* Exit. */ die (makefile_status); } /* NOTREACHED */ exit (MAKE_SUCCESS); } /* Parsing of arguments, decoding of switches. */ static char options[1 + sizeof (switches) / sizeof (switches[0]) * 3]; static struct option long_options[(sizeof (switches) / sizeof (switches[0])) + (sizeof (long_option_aliases) / sizeof (long_option_aliases[0]))]; /* Fill in the string and vector for getopt. */ static void init_switches (void) { char *p; unsigned int c; unsigned int i; if (options[0] != '\0') /* Already done. */ return; p = options; /* Return switch and non-switch args in order, regardless of POSIXLY_CORRECT. Non-switch args are returned as option 1. */ *p++ = '-'; for (i = 0; switches[i].c != '\0'; ++i) { long_options[i].name = (switches[i].long_name == 0 ? "" : switches[i].long_name); long_options[i].flag = 0; long_options[i].val = switches[i].c; if (short_option (switches[i].c)) *p++ = switches[i].c; switch (switches[i].type) { case flag: case flag_off: case ignore: long_options[i].has_arg = no_argument; break; case string: case strlist: case filename: case positive_int: case floating: if (short_option (switches[i].c)) *p++ = ':'; if (switches[i].noarg_value != 0) { if (short_option (switches[i].c)) *p++ = ':'; long_options[i].has_arg = optional_argument; } else long_options[i].has_arg = required_argument; break; } } *p = '\0'; for (c = 0; c < (sizeof (long_option_aliases) / sizeof (long_option_aliases[0])); ++c) long_options[i++] = long_option_aliases[c]; long_options[i].name = 0; } /* Non-option argument. It might be a variable definition. */ static void handle_non_switch_argument (const char *arg, int env) { struct variable *v; if (arg[0] == '-' && arg[1] == '\0') /* Ignore plain '-' for compatibility. */ return; #ifdef VMS { /* VMS DCL quoting can result in foo="bar baz" showing up here. Need to remove the double quotes from the value. */ char * eq_ptr; char * new_arg; eq_ptr = strchr (arg, '='); if ((eq_ptr != NULL) && (eq_ptr[1] == '"')) { int len; int seg1; int seg2; len = strlen(arg); new_arg = alloca(len); seg1 = eq_ptr - arg + 1; strncpy(new_arg, arg, (seg1)); seg2 = len - seg1 - 1; strncpy(&new_arg[seg1], &eq_ptr[2], seg2); new_arg[seg1 + seg2] = 0; if (new_arg[seg1 + seg2 - 1] == '"') new_arg[seg1 + seg2 - 1] = 0; arg = new_arg; } } #endif v = try_variable_definition (0, arg IF_WITH_VALUE_LENGTH_PARAM(NULL), o_command, 0); if (v != 0) { /* It is indeed a variable definition. If we don't already have this one, record a pointer to the variable for later use in define_makeflags. */ struct command_variable *cv; for (cv = command_variables; cv != 0; cv = cv->next) if (cv->variable == v) break; if (! cv) { cv = xmalloc (sizeof (*cv)); cv->variable = v; cv->next = command_variables; command_variables = cv; } } else if (! env) { /* Not an option or variable definition; it must be a goal target! Enter it as a file and add it to the dep chain of goals. */ struct file *f = enter_file (strcache_add (expand_command_line_file (arg))); f->cmd_target = 1; if (goals == 0) { goals = alloc_goaldep (); lastgoal = goals; } else { lastgoal->next = alloc_goaldep (); lastgoal = lastgoal->next; } lastgoal->file = f; { /* Add this target name to the MAKECMDGOALS variable. */ struct variable *gv; const char *value; gv = lookup_variable (STRING_SIZE_TUPLE ("MAKECMDGOALS")); if (gv == 0) value = f->name; else { /* Paste the old and new values together */ unsigned int oldlen, newlen; char *vp; oldlen = strlen (gv->value); newlen = strlen (f->name); vp = alloca (oldlen + 1 + newlen + 1); memcpy (vp, gv->value, oldlen); vp[oldlen] = ' '; memcpy (&vp[oldlen + 1], f->name, newlen + 1); value = vp; } define_variable_cname ("MAKECMDGOALS", value, o_default, 0); } } } /* Print a nice usage method. */ static void print_usage (int bad) { const char *const *cpp; FILE *usageto; if (print_version_flag) print_version (); usageto = bad ? stderr : stdout; fprintf (usageto, _("Usage: %s [options] [target] ...\n"), program); for (cpp = usage; *cpp; ++cpp) fputs (_(*cpp), usageto); #ifdef KMK if (!remote_description || *remote_description == '\0') fprintf (usageto, _("\nThis program is built for %s/%s/%s [" __DATE__ " " __TIME__ "]\n"), KBUILD_HOST, KBUILD_HOST_ARCH, KBUILD_HOST_CPU); else fprintf (usageto, _("\nThis program is built for %s/%s/%s (%s) [" __DATE__ " " __TIME__ "]\n"), KBUILD_HOST, KBUILD_HOST_ARCH, KBUILD_HOST_CPU, remote_description); #else /* !KMK */ if (!remote_description || *remote_description == '\0') fprintf (usageto, _("\nThis program built for %s\n"), make_host); else fprintf (usageto, _("\nThis program built for %s (%s)\n"), make_host, remote_description); #endif /* !KMK */ fprintf (usageto, _("Report bugs to \n")); } /* Decode switches from ARGC and ARGV. They came from the environment if ENV is nonzero. */ static void decode_switches (int argc, const char **argv, int env) { int bad = 0; register const struct command_switch *cs; register struct stringlist *sl; register int c; /* getopt does most of the parsing for us. First, get its vectors set up. */ init_switches (); /* Let getopt produce error messages for the command line, but not for options from the environment. */ opterr = !env; /* Reset getopt's state. */ optind = 0; while (optind < argc) { const char *coptarg; /* Parse the next argument. */ c = getopt_long (argc, (char*const*)argv, options, long_options, NULL); coptarg = optarg; if (c == EOF) /* End of arguments, or "--" marker seen. */ break; else if (c == 1) /* An argument not starting with a dash. */ handle_non_switch_argument (coptarg, env); else if (c == '?') /* Bad option. We will print a usage message and die later. But continue to parse the other options so the user can see all he did wrong. */ bad = 1; else for (cs = switches; cs->c != '\0'; ++cs) if (cs->c == c) { /* Whether or not we will actually do anything with this switch. We test this individually inside the switch below rather than just once outside it, so that options which are to be ignored still consume args. */ int doit = !env || cs->env; switch (cs->type) { default: abort (); case ignore: break; case flag: case flag_off: if (doit) *(int *) cs->value_ptr = cs->type == flag; break; case string: case strlist: case filename: if (!doit) break; if (! coptarg) coptarg = xstrdup (cs->noarg_value); else if (*coptarg == '\0') { char opt[2] = "c"; const char *op = opt; if (short_option (cs->c)) opt[0] = cs->c; else op = cs->long_name; error (NILF, strlen (op), _("the '%s%s' option requires a non-empty string argument"), short_option (cs->c) ? "-" : "--", op); bad = 1; break; } if (cs->type == string) { char **val = (char **)cs->value_ptr; free (*val); *val = xstrdup (coptarg); break; } sl = *(struct stringlist **) cs->value_ptr; if (sl == 0) { sl = xmalloc (sizeof (struct stringlist)); sl->max = 5; sl->idx = 0; sl->list = xmalloc (5 * sizeof (char *)); *(struct stringlist **) cs->value_ptr = sl; } else if (sl->idx == sl->max - 1) { sl->max += 5; /* MSVC erroneously warns without a cast here. */ sl->list = xrealloc ((void *)sl->list, sl->max * sizeof (char *)); } if (cs->type == filename) sl->list[sl->idx++] = expand_command_line_file (coptarg); else sl->list[sl->idx++] = xstrdup (coptarg); sl->list[sl->idx] = 0; break; case positive_int: /* See if we have an option argument; if we do require that it's all digits, not something like "10foo". */ if (coptarg == 0 && argc > optind) { const char *cp; for (cp=argv[optind]; ISDIGIT (cp[0]); ++cp) ; if (cp[0] == '\0') coptarg = argv[optind++]; } if (!doit) break; if (coptarg) { int i = atoi (coptarg); const char *cp; /* Yes, I realize we're repeating this in some cases. */ for (cp = coptarg; ISDIGIT (cp[0]); ++cp) ; if (i < 1 || cp[0] != '\0') { error (NILF, 0, _("the '-%c' option requires a positive integer argument"), cs->c); bad = 1; } else *(unsigned int *) cs->value_ptr = i; } else *(unsigned int *) cs->value_ptr = *(unsigned int *) cs->noarg_value; break; #ifndef NO_FLOAT case floating: if (coptarg == 0 && optind < argc && (ISDIGIT (argv[optind][0]) || argv[optind][0] == '.')) coptarg = argv[optind++]; if (doit) *(double *) cs->value_ptr = (coptarg != 0 ? atof (coptarg) : *(double *) cs->noarg_value); break; #endif } /* We've found the switch. Stop looking. */ break; } } /* There are no more options according to getting getopt, but there may be some arguments left. Since we have asked for non-option arguments to be returned in order, this only happens when there is a "--" argument to prevent later arguments from being options. */ while (optind < argc) handle_non_switch_argument (argv[optind++], env); if (!env && (bad || print_usage_flag)) { print_usage (bad); die (bad ? MAKE_FAILURE : MAKE_SUCCESS); } /* If there are any options that need to be decoded do it now. */ decode_debug_flags (); decode_output_sync_flags (); #if defined (WINDOWS32) && defined (CONFIG_NEW_WIN_CHILDREN) /* validate the job object mode value . */ if (win_job_object_mode == NULL) win_job_object_mode = xstrdup ("login"); else if ( strcmp (win_job_object_mode, "none") != 0 && strcmp (win_job_object_mode, "login") != 0 && strcmp (win_job_object_mode, "root") != 0 && strcmp (win_job_object_mode, "each") != 0) OS (fatal, NILF, _("unknown job object mode '%s'"), win_job_object_mode); #endif } /* Decode switches from environment variable ENVAR (which is LEN chars long). We do this by chopping the value into a vector of words, prepending a dash to the first word if it lacks one, and passing the vector to decode_switches. */ static void decode_env_switches (const char *envar, unsigned int len) { char *varref = alloca (2 + len + 2); char *value, *p, *buf; int argc; const char **argv; /* Get the variable's value. */ varref[0] = '$'; varref[1] = '('; memcpy (&varref[2], envar, len); varref[2 + len] = ')'; varref[2 + len + 1] = '\0'; value = variable_expand (varref); /* Skip whitespace, and check for an empty value. */ NEXT_TOKEN (value); len = strlen (value); if (len == 0) return; /* Allocate a vector that is definitely big enough. */ argv = alloca ((1 + len + 1) * sizeof (char *)); /* getopt will look at the arguments starting at ARGV[1]. Prepend a spacer word. */ argv[0] = 0; argc = 1; /* We need a buffer to copy the value into while we split it into words and unquote it. Set up in case we need to prepend a dash later. */ buf = alloca (1 + len + 1); buf[0] = '-'; p = buf+1; argv[argc] = p; while (*value != '\0') { if (*value == '\\' && value[1] != '\0') ++value; /* Skip the backslash. */ else if (ISBLANK (*value)) { /* End of the word. */ *p++ = '\0'; argv[++argc] = p; do ++value; while (ISBLANK (*value)); continue; } *p++ = *value++; } *p = '\0'; argv[++argc] = 0; assert (p < buf + len + 2); if (argv[1][0] != '-' && strchr (argv[1], '=') == 0) /* The first word doesn't start with a dash and isn't a variable definition, so add a dash. */ argv[1] = buf; /* Parse those words. */ decode_switches (argc, argv, 1); } /* Quote the string IN so that it will be interpreted as a single word with no magic by decode_env_switches; also double dollar signs to avoid variable expansion in make itself. Write the result into OUT, returning the address of the next character to be written. Allocating space for OUT twice the length of IN is always sufficient. */ static char * quote_for_env (char *out, const char *in) { while (*in != '\0') { if (*in == '$') *out++ = '$'; else if (ISBLANK (*in) || *in == '\\') *out++ = '\\'; *out++ = *in++; } return out; } /* Define the MAKEFLAGS and MFLAGS variables to reflect the settings of the command switches. Include options with args if ALL is nonzero. Don't include options with the 'no_makefile' flag set if MAKEFILE. */ static struct variable * define_makeflags (int all, int makefile) { #ifdef KMK static const char ref[] = "$(KMK_OVERRIDES)"; #else static /*<- bird*/ const char ref[] = "$(MAKEOVERRIDES)"; #endif static /*<- bird*/ const char posixref[] = "$(-*-command-variables-*-)"; static /*<- bird*/ const char evalref[] = "$(-*-eval-flags-*-)"; const struct command_switch *cs; char *flagstring; char *p; /* We will construct a linked list of 'struct flag's describing all the flags which need to go in MAKEFLAGS. Then, once we know how many there are and their lengths, we can put them all together in a string. */ struct flag { struct flag *next; const struct command_switch *cs; const char *arg; }; struct flag *flags = 0; struct flag *last = 0; unsigned int flagslen = 0; #define ADD_FLAG(ARG, LEN) \ do { \ struct flag *new = alloca (sizeof (struct flag)); \ new->cs = cs; \ new->arg = (ARG); \ new->next = 0; \ if (! flags) \ flags = new; \ else \ last->next = new; \ last = new; \ if (new->arg == 0) \ /* Just a single flag letter: " -x" */ \ flagslen += 3; \ else \ /* " -xfoo", plus space to escape "foo". */ \ flagslen += 1 + 1 + 1 + (3 * (LEN)); \ if (!short_option (cs->c)) \ /* This switch has no single-letter version, so we use the long. */ \ flagslen += 2 + strlen (cs->long_name); \ } while (0) for (cs = switches; cs->c != '\0'; ++cs) if (cs->toenv && (!makefile || !cs->no_makefile)) switch (cs->type) { case ignore: break; case flag: case flag_off: if ((!*(int *) cs->value_ptr) == (cs->type == flag_off) && (cs->default_value == 0 || *(int *) cs->value_ptr != *(int *) cs->default_value)) ADD_FLAG (0, 0); break; case positive_int: if (all) { if ((cs->default_value != 0 && (*(unsigned int *) cs->value_ptr == *(unsigned int *) cs->default_value))) break; else if (cs->noarg_value != 0 && (*(unsigned int *) cs->value_ptr == *(unsigned int *) cs->noarg_value)) ADD_FLAG ("", 0); /* Optional value omitted; see below. */ else { char *buf = alloca (30); sprintf (buf, "%u", *(unsigned int *) cs->value_ptr); ADD_FLAG (buf, strlen (buf)); } } break; #ifndef NO_FLOAT case floating: if (all) { if (cs->default_value != 0 && (*(double *) cs->value_ptr == *(double *) cs->default_value)) break; else if (cs->noarg_value != 0 && (*(double *) cs->value_ptr == *(double *) cs->noarg_value)) ADD_FLAG ("", 0); /* Optional value omitted; see below. */ else { char *buf = alloca (100); sprintf (buf, "%g", *(double *) cs->value_ptr); ADD_FLAG (buf, strlen (buf)); } } break; #endif case string: if (all) { p = *((char **)cs->value_ptr); if (p) ADD_FLAG (p, strlen (p)); } break; case filename: case strlist: if (all) { struct stringlist *sl = *(struct stringlist **) cs->value_ptr; if (sl != 0) { unsigned int i; for (i = 0; i < sl->idx; ++i) ADD_FLAG (sl->list[i], strlen (sl->list[i])); } } break; default: abort (); } #undef ADD_FLAG /* Four more for the possible " -- ", plus variable references. */ flagslen += 4 + CSTRLEN (posixref) + 1 + CSTRLEN (evalref) + 1; /* Construct the value in FLAGSTRING. We allocate enough space for a preceding dash and trailing null. */ flagstring = alloca (1 + flagslen + 1); memset (flagstring, '\0', 1 + flagslen + 1); p = flagstring; /* Start with a dash, for MFLAGS. */ *p++ = '-'; /* Add simple options as a group. */ while (flags != 0 && !flags->arg && short_option (flags->cs->c)) { *p++ = flags->cs->c; flags = flags->next; } /* Now add more complex flags: ones with options and/or long names. */ while (flags) { *p++ = ' '; *p++ = '-'; /* Add the flag letter or name to the string. */ if (short_option (flags->cs->c)) *p++ = flags->cs->c; else { /* Long options require a double-dash. */ *p++ = '-'; strcpy (p, flags->cs->long_name); p += strlen (p); } /* An omitted optional argument has an ARG of "". */ if (flags->arg && flags->arg[0] != '\0') { if (!short_option (flags->cs->c)) /* Long options require '='. */ *p++ = '='; p = quote_for_env (p, flags->arg); } flags = flags->next; } /* If no flags at all, get rid of the initial dash. */ if (p == &flagstring[1]) { flagstring[0] = '\0'; p = flagstring; } #ifdef KMK /* Define MFLAGS before appending variable definitions. Omit an initial empty dash. Since MFLAGS is not parsed for flags, there is no reason to override any makefile redefinition. */ define_variable_cname ("MFLAGS", flagstring + (flagstring[0] == '-' && flagstring[1] == ' ' ? 2 : 0), o_env, 1); #endif /* !KMK */ /* Write a reference to -*-eval-flags-*-, which contains all the --eval flag options. */ if (eval_strings) { *p++ = ' '; memcpy (p, evalref, CSTRLEN (evalref)); p += CSTRLEN (evalref); } if (all && command_variables) { /* Write a reference to $(MAKEOVERRIDES), which contains all the command-line variable definitions. Separate the variables from the switches with a "--" arg. */ strcpy (p, " -- "); p += 4; /* Copy in the string. */ if (posix_pedantic) { memcpy (p, posixref, CSTRLEN (posixref)); p += CSTRLEN (posixref); } else { memcpy (p, ref, CSTRLEN (ref)); p += CSTRLEN (ref); } } /* If there is a leading dash, omit it. */ if (flagstring[0] == '-') ++flagstring; #ifdef KMK /* Provide simple access to some of the options. */ { char val[32]; sprintf (val, "%u", job_slots ? job_slots : master_job_slots); define_variable_cname ("KMK_OPTS_JOBS", val, o_default, 1); sprintf (val, "%u", default_job_slots); define_variable_cname ("KMK_OPTS_JOBS_DEFAULT", val, o_default, 1); define_variable_cname ("KMK_OPTS_KEEP_GOING", keep_going_flag ? "1" : "0", o_default, 1); define_variable_cname ("KMK_OPTS_JUST_PRINT", just_print_flag ? "1" : "0", o_default, 1); define_variable_cname ("KMK_OPTS_PRETTY_COMMAND_PRINTING", pretty_command_printing ? "1" : "0", o_default, 1); sprintf (val, "%u", process_priority); define_variable_cname ("KMK_OPTS_PRORITY", val, o_default, 1); sprintf (val, "%u", process_affinity); define_variable_cname ("KMK_OPTS_AFFINITY", val, o_default, 1); # if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS) define_variable_cname ("KMK_OPTS_STATISTICS", make_expensive_statistics ? "1" : "0", o_default, 1); # endif # ifdef CONFIG_WITH_PRINT_TIME_SWITCH sprintf (val, "%u", print_time_min); define_variable_cname ("KMK_OPTS_PRINT_TIME", val, o_default, 1); # endif } #endif /* This used to use o_env, but that lost when a makefile defined MAKEFLAGS. Makefiles set MAKEFLAGS to add switches, but we still want to redefine its value with the full set of switches. Then we used o_file, but that lost when users added -e, causing a previous MAKEFLAGS env. var. to take precedence over the new one. Of course, an override or command definition will still take precedence. */ #ifdef KMK return define_variable_cname ("KMK_FLAGS", flagstring, env_overrides ? o_env_override : o_file, 1); #else return define_variable_cname ("MAKEFLAGS", flagstring, env_overrides ? o_env_override : o_file, 1); #endif } /* Print version information. */ static void print_version (void) { static int printed_version = 0; const char *precede = print_data_base_flag ? "# " : ""; if (printed_version) /* Do it only once. */ return; #ifdef KMK printf ("%skmk - kBuild version %d.%d.%d (r%u)\n\ \n", precede, KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, KBUILD_SVN_REV); printf("%sBased on GNU Make %s:\n", precede, version_string); #else /* !KMK */ printf ("%sGNU Make %s\n", precede, version_string); if (!remote_description || *remote_description == '\0') printf (_("%sBuilt for %s\n"), precede, make_host); else printf (_("%sBuilt for %s (%s)\n"), precede, make_host, remote_description); #endif /* !KMK */ /* Print this untranslated. The coding standards recommend translating the (C) to the copyright symbol, but this string is going to change every year, and none of the rest of it should be translated (including the word "Copyright"), so it hardly seems worth it. */ printf ("%sCopyright (C) 1988-2016 Free Software Foundation, Inc.\n", precede); printf (_("%sLicense GPLv3+: GNU GPL version 3 or later \n\ %sThis is free software: you are free to change and redistribute it.\n\ %sThere is NO WARRANTY, to the extent permitted by law.\n"), precede, precede, precede); #ifdef KMK printf ("\n\ %skBuild modifications:\n\ %s Copyright (c) 2005-2018 knut st. osmundsen.\n\ \n\ %skmkbuiltin commands derived from *BSD sources:\n\ %s Copyright (c) 1983 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994\n\ %s The Regents of the University of California. All rights reserved.\n\ %s Copyright (c) 1998 Todd C. Miller \n", precede, precede, precede, precede, precede, precede); # ifdef KBUILD_PATH printf (_("\n\ %sKBUILD_PATH: '%s' (default '%s')\n\ %sKBUILD_BIN_PATH: '%s' (default '%s')\n\ \n"), precede, get_kbuild_path(), KBUILD_PATH, precede, get_kbuild_bin_path(), KBUILD_BIN_PATH); # else /* !KBUILD_PATH */ printf ("\n\ %sKBUILD_PATH: '%s'\n\ %sKBUILD_BIN_PATH: '%s'\n\ \n", precede, get_kbuild_path(), precede, get_kbuild_bin_path()); # endif /* !KBUILD_PATH */ if (!remote_description || *remote_description == '\0') printf (_("%sThis program is a %s build, built for %s/%s/%s [" __DATE__ " " __TIME__ "]\n\n"), precede, KBUILD_TYPE, KBUILD_HOST, KBUILD_HOST_ARCH, KBUILD_HOST_CPU); else printf (_("%sThis program is a %s build, built for %s/%s/%s (%s) [" __DATE__ " " __TIME__ "]\n\n"), precede, KBUILD_TYPE, KBUILD_HOST, KBUILD_HOST_ARCH, KBUILD_HOST_CPU, remote_description); #endif /* KMK */ printed_version = 1; /* Flush stdout so the user doesn't have to wait to see the version information while make thinks about things. */ fflush (stdout); } /* Print a bunch of information about this and that. */ static void print_data_base (void) { time_t when = time ((time_t *) 0); print_version (); printf (_("\n# Make data base, printed on %s"), ctime (&when)); print_variable_data_base (); print_dir_data_base (); print_rule_data_base (); print_file_data_base (); print_vpath_data_base (); #ifdef KMK print_kbuild_data_base (); #endif #ifndef CONFIG_WITH_STRCACHE2 strcache_print_stats ("#"); #else strcache2_print_stats_all ("#"); #endif #ifdef CONFIG_WITH_ALLOC_CACHES alloccache_print_all (); #endif #ifdef CONFIG_WITH_COMPILER kmk_cc_print_stats (); #endif when = time ((time_t *) 0); printf (_("\n# Finished Make data base on %s\n"), ctime (&when)); } #ifdef CONFIG_WITH_PRINT_STATS_SWITCH static void print_stats () { time_t when; when = time ((time_t *) 0); printf (_("\n# Make statistics, printed on %s"), ctime (&when)); /* Allocators: */ # ifdef CONFIG_WITH_COMPILER kmk_cc_print_stats (); # endif # ifndef CONFIG_WITH_STRCACHE2 strcache_print_stats ("#"); # else strcache2_print_stats_all ("#"); # endif # ifdef CONFIG_WITH_ALLOC_CACHES alloccache_print_all (); # endif print_heap_stats (); /* Make stuff: */ print_variable_stats (); print_file_stats (); print_dir_stats (); # ifdef KMK print_kbuild_define_stats (); # endif # ifdef CONFIG_WITH_KMK_BUILTIN_STATS kmk_builtin_print_stats (stdout, "# "); # endif # ifdef CONFIG_WITH_COMPILER kmk_cc_print_stats (); # endif when = time ((time_t *) 0); printf (_("\n# Finished Make statistics on %s\n"), ctime (&when)); } #endif /* CONFIG_WITH_PRINT_STATS_SWITCH */ static void clean_jobserver (int status) { /* Sanity: have we written all our jobserver tokens back? If our exit status is 2 that means some kind of syntax error; we might not have written all our tokens so do that now. If tokens are left after any other error code, that's bad. */ if (jobserver_enabled() && jobserver_tokens) { if (status != 2) ON (error, NILF, "INTERNAL: Exiting with %u jobserver tokens (should be 0)!", jobserver_tokens); else /* Don't write back the "free" token */ while (--jobserver_tokens) jobserver_release (0); } /* Sanity: If we're the master, were all the tokens written back? */ if (master_job_slots) { /* We didn't write one for ourself, so start at 1. */ unsigned int tokens = 1 + jobserver_acquire_all (); if (tokens != master_job_slots) ONN (error, NILF, "INTERNAL: Exiting with %u jobserver tokens available; should be %u!", tokens, master_job_slots); reset_jobserver (); } } /* Exit with STATUS, cleaning up as necessary. */ void #ifdef KMK die_with_job_output (int status, struct output *out) #else die (int status) #endif { static char dying = 0; #ifdef KMK static char need_2nd_error = 0; static char need_2nd_error_output = 0; #endif if (!dying) { int err; dying = 1; if (print_version_flag) print_version (); #ifdef KMK /* Flag 2nd error message. */ if (status != 0 && ( job_slots_used > 0 || print_data_base_flag || print_stats_flag)) { need_2nd_error = 1; need_2nd_error_output = job_slots_used >= 2 && out != NULL && out != &make_sync; if (need_2nd_error_output) output_metered = 0; } #endif /* KMK */ /* Wait for children to die. */ err = (status != 0); while (job_slots_used > 0) reap_children (1, err); /* Let the remote job module clean up its state. */ remote_cleanup (); /* Remove the intermediate files. */ remove_intermediates (0); if (print_data_base_flag) print_data_base (); #ifdef CONFIG_WITH_PRINT_STATS_SWITCH if (print_stats_flag) print_stats (); #endif if (verify_flag) verify_file_data_base (); #ifdef NDEBUG /* bird: Don't waste time on debug sanity checks. */ if (print_data_base_flag || db_level) #endif verify_file_data_base (); clean_jobserver (status); if (output_context) { /* die() might be called in a recipe output context due to an $(error ...) function. */ output_close (output_context); if (output_context != &make_sync) output_close (&make_sync); OUTPUT_UNSET (); } output_close (NULL); /* Try to move back to the original directory. This is essential on MS-DOS (where there is really only one process), and on Unix it puts core files in the original directory instead of the -C directory. Must wait until after remove_intermediates(), or unlinks of relative pathnames fail. */ if (directory_before_chdir != 0) { /* If it fails we don't care: shut up GCC. */ int _x UNUSED; _x = chdir (directory_before_chdir); } #ifdef CONFIG_WITH_PRINT_TIME_SWITCH if (print_time_min != -1) { big_int elapsed = nano_timestamp () - make_start_ts; if (elapsed >= print_time_min * BIG_INT_C(1000000000)) { char buf[64]; format_elapsed_nano (buf, sizeof (buf), elapsed); message (1, strlen (buf), _("%*s"), print_time_width, buf); } } #endif } #ifdef KMK /* The failure might be lost in a -j run, so mention the failure again before exiting. */ if (need_2nd_error != 0) ON (error, NILF, _("*** Exiting with status %d"), status); if (out) { out->dont_truncate = 0; if (need_2nd_error_output && output_metered > 20) output_dump (out); else output_reset (out); output_close (out); } #endif exit (status); } #ifdef KMK void die (int status) { die_with_job_output (status, NULL); } #endif kbuild-3686/src/kmk/acinclude.m40000664000175000017500000001371215053010075016456 0ustar locutuslocutusdnl acinclude.m4 -- Extra macros needed for GNU make. dnl dnl Automake will incorporate this into its generated aclocal.m4. dnl Copyright (C) 1998-2016 Free Software Foundation, Inc. dnl This file is part of GNU Make. dnl dnl GNU Make is free software; you can redistribute it and/or modify it under dnl the terms of the GNU General Public License as published by the Free dnl Software Foundation; either version 3 of the License, or (at your option) dnl any later version. dnl dnl GNU Make is distributed in the hope that it will be useful, but WITHOUT dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. dnl more details. dnl dnl You should have received a copy of the GNU General Public License along dnl with this program. If not, see . dnl --------------------------------------------------------------------------- dnl Got this from the lynx 2.8 distribution. dnl by T.E.Dickey dnl and Jim Spath dnl and Philippe De Muyter dnl dnl Created: 1997/1/28 dnl Updated: 1997/12/23 dnl --------------------------------------------------------------------------- dnl After checking for functions in the default $LIBS, make a further check dnl for the functions that are netlib-related (these aren't always in the dnl libc, etc., and have to be handled specially because there are conflicting dnl and broken implementations. dnl Common library requirements (in order): dnl -lresolv -lsocket -lnsl dnl -lnsl -lsocket dnl -lsocket dnl -lbsd AC_DEFUN([CF_NETLIBS],[ cf_test_netlibs=no AC_MSG_CHECKING(for network libraries) AC_CACHE_VAL(cf_cv_netlibs,[ AC_MSG_RESULT(working...) cf_cv_netlibs="" cf_test_netlibs=yes AC_CHECK_FUNCS(gethostname,,[ CF_RECHECK_FUNC(gethostname,nsl,cf_cv_netlibs,[ CF_RECHECK_FUNC(gethostname,socket,cf_cv_netlibs)])]) # # FIXME: sequent needs this library (i.e., -lsocket -linet -lnsl), but # I don't know the entrypoints - 97/7/22 TD AC_CHECK_LIB(inet,main,cf_cv_netlibs="-linet $cf_cv_netlibs") # if test "$ac_cv_func_lsocket" != no ; then AC_CHECK_FUNCS(socket,,[ CF_RECHECK_FUNC(socket,socket,cf_cv_netlibs,[ CF_RECHECK_FUNC(socket,bsd,cf_cv_netlibs)])]) fi # AC_CHECK_FUNCS(gethostbyname,,[ CF_RECHECK_FUNC(gethostbyname,nsl,cf_cv_netlibs)]) ]) LIBS="$LIBS $cf_cv_netlibs" test $cf_test_netlibs = no && echo "$cf_cv_netlibs" >&AC_FD_MSG ])dnl dnl --------------------------------------------------------------------------- dnl Re-check on a function to see if we can pick it up by adding a library. dnl $1 = function to check dnl $2 = library to check in dnl $3 = environment to update (e.g., $LIBS) dnl $4 = what to do if this fails dnl dnl This uses 'unset' if the shell happens to support it, but leaves the dnl configuration variable set to 'unknown' if not. This is a little better dnl than the normal autoconf test, which gives misleading results if a test dnl for the function is made (e.g., with AC_CHECK_FUNC) after this macro is dnl used (autoconf does not distinguish between a null token and one that is dnl set to 'no'). AC_DEFUN([CF_RECHECK_FUNC],[ AC_CHECK_LIB($2,$1,[ CF_UPPER(cf_tr_func,$1) AC_DEFINE_UNQUOTED(HAVE_$cf_tr_func,1,[Define if you have function $1]) ac_cv_func_$1=yes $3="-l$2 [$]$3"],[ ac_cv_func_$1=unknown unset ac_cv_func_$1 2>/dev/null $4], [[$]$3]) ])dnl dnl --------------------------------------------------------------------------- dnl Make an uppercase version of a variable dnl $1=uppercase($2) AC_DEFUN([CF_UPPER], [ changequote(,)dnl $1=`echo $2 | tr '[a-z]' '[A-Z]'` changequote([,])dnl ])dnl dnl --------------------------------------------------------------------------- dnl From Paul Eggert dnl Update for Darwin by Troy Runkel dnl Update for AIX by Olexiy Buyanskyy (Savannah bug 32485) AC_DEFUN([AC_STRUCT_ST_MTIM_NSEC], [AC_CACHE_CHECK([for nanoseconds field of struct stat], ac_cv_struct_st_mtim_nsec, [ac_save_CPPFLAGS="$CPPFLAGS" ac_cv_struct_st_mtim_nsec=no # st_mtim.tv_nsec -- the usual case # st_mtim._tv_nsec -- Solaris 2.6, if # (defined _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED == 1 # && !defined __EXTENSIONS__) # st_mtim.st__tim.tv_nsec -- UnixWare 2.1.2 # st_mtime_n -- AIX 5.2 and above # st_mtimespec.tv_nsec -- Darwin (Mac OSX) for ac_val in st_mtim.tv_nsec st_mtim._tv_nsec st_mtim.st__tim.tv_nsec st_mtime_n st_mtimespec.tv_nsec; do CPPFLAGS="$ac_save_CPPFLAGS -DST_MTIM_NSEC=$ac_val" AC_TRY_COMPILE([#include #include ], [struct stat s; s.ST_MTIM_NSEC;], [ac_cv_struct_st_mtim_nsec=$ac_val; break]) done CPPFLAGS="$ac_save_CPPFLAGS" ]) if test $ac_cv_struct_st_mtim_nsec != no; then AC_DEFINE_UNQUOTED([ST_MTIM_NSEC], [$ac_cv_struct_st_mtim_nsec], [Define if struct stat contains a nanoseconds field]) fi ] ) dnl bird: Copy of above for atime AC_DEFUN([AC_STRUCT_ST_ATIM_NSEC], [AC_CACHE_CHECK([for nanoseconds access time field of struct stat], ac_cv_struct_st_atim_nsec, [ac_save_CPPFLAGS="$CPPFLAGS" ac_cv_struct_st_atim_nsec=no # st_atim.tv_nsec -- the usual case # st_atim._tv_nsec -- Solaris 2.6, if # (defined _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED == 1 # && !defined __EXTENSIONS__) # st_atim.st__tim.tv_nsec -- UnixWare 2.1.2 # st_atime_n -- AIX 5.2 and above # st_atimespec.tv_nsec -- Darwin (Mac OSX) for ac_val in st_atim.tv_nsec st_atim._tv_nsec st_atim.st__tim.tv_nsec st_atime_n st_atimespec.tv_nsec; do CPPFLAGS="$ac_save_CPPFLAGS -DST_ATIM_NSEC=$ac_val" AC_TRY_COMPILE([#include #include ], [struct stat s; s.ST_ATIM_NSEC;], [ac_cv_struct_st_atim_nsec=$ac_val; break]) done CPPFLAGS="$ac_save_CPPFLAGS" ]) if test $ac_cv_struct_st_atim_nsec != no; then AC_DEFINE_UNQUOTED([ST_ATIM_NSEC], [$ac_cv_struct_st_atim_nsec], [Define if struct stat contains a nanoseconds field]) fi ] ) kbuild-3686/src/kmk/config.h.linux0000664000175000017500000003371015053010075017041 0ustar locutuslocutus/* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.ac by autoheader. */ /* * bird: Move up this bunch so we can include features.h early. */ /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # define _ALL_SOURCE 1 #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # define _POSIX_PTHREAD_SEMANTICS 1 #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # define _TANDEM_SOURCE 1 #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # define __EXTENSIONS__ 1 #endif #include /* bird */ /* Define to 1 if the `closedir' function returns void instead of `int'. */ /* #undef CLOSEDIR_VOID */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if using `getloadavg.c'. */ /* #undef C_GETLOADAVG */ /* Define to 1 for DGUX with . */ /* #undef DGUX */ /* Use high resolution file timestamps if nonzero. */ #define FILE_TIMESTAMP_HI_RES 1 /* Define to 1 if the `getloadavg' function needs to be run setuid or setgid. */ /* #undef GETLOADAVG_PRIVILEGED */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ #define HAVE_ALLOCA_H 1 /* Define to 1 if you have the `atexit' function. */ #define HAVE_ATEXIT 1 /* Use case insensitive file names */ /* #undef HAVE_CASE_INSENSITIVE_FS */ /* Define to 1 if you have the clock_gettime function. */ #define HAVE_CLOCK_GETTIME 1 /* Define to 1 if you have the declaration of `bsd_signal', and to 0 if you don't. */ #if !defined(KBUILD_ARCH_X86) && !defined(KBUILD_ARCH_AMD64) # define HAVE_DECL_BSD_SIGNAL 1 #endif /* Define to 1 if you have the declaration of `dlerror', and to 0 if you don't. */ #define HAVE_DECL_DLERROR 1 /* Define to 1 if you have the declaration of `dlopen', and to 0 if you don't. */ #define HAVE_DECL_DLOPEN 1 /* Define to 1 if you have the declaration of `dlsym', and to 0 if you don't. */ #define HAVE_DECL_DLSYM 1 /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you don't. */ #define HAVE_DECL_SYS_SIGLIST 1 /* Define to 1 if you have the declaration of `_sys_siglist', and to 0 if you don't. */ #define HAVE_DECL__SYS_SIGLIST 1 /* Define to 1 if you have the declaration of `__sys_siglist', and to 0 if you don't. */ #define HAVE_DECL___SYS_SIGLIST 0 /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Use platform specific coding */ /* #undef HAVE_DOS_PATHS */ /* Define to 1 if you have the `dup' function. */ #define HAVE_DUP 1 /* Define to 1 if you have the `dup2' function. */ #define HAVE_DUP2 1 /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define to 1 if you have the `fdopen' function. */ #define HAVE_FDOPEN 1 /* Define to 1 if you have the `fileno' function. */ #define HAVE_FILENO 1 /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getgroups' function. */ #define HAVE_GETGROUPS 1 /* Define to 1 if you have the `gethostbyname' function. */ /* #undef HAVE_GETHOSTBYNAME */ /* Define to 1 if you have the `gethostname' function. */ /* #undef HAVE_GETHOSTNAME */ /* Define to 1 if you have the `getloadavg' function. */ #define HAVE_GETLOADAVG 1 /* Define to 1 if you have the `getrlimit' function. */ #define HAVE_GETRLIMIT 1 /* Define to 1 if you have a standard gettimeofday function */ #define HAVE_GETTIMEOFDAY 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the `isatty' function. */ #define HAVE_ISATTY 1 /* Define to 1 if you have the `dgc' library (-ldgc). */ /* #undef HAVE_LIBDGC */ /* Define to 1 if you have the `kstat' library (-lkstat). */ /* #undef HAVE_LIBKSTAT */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you have the `lstat' function. */ #define HAVE_LSTAT 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MACH_MACH_H */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have the `mktemp' function. */ #define HAVE_MKTEMP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NLIST_H */ /* Define to 1 if you have the `pipe' function. */ #define HAVE_PIPE 1 /* Define to 1 if you have the `pselect' function. */ #define HAVE_PSELECT 1 /* Define to 1 if you have the `pstat_getdynamic' function. */ /* #undef HAVE_PSTAT_GETDYNAMIC */ /* Define to 1 if you have the `readlink' function. */ #define HAVE_READLINK 1 /* Define to 1 if you have the `realpath' function. */ #define HAVE_REALPATH 1 /* Define to 1 if defines the SA_RESTART constant. */ #define HAVE_SA_RESTART 1 /* Define to 1 if you have the `setegid' function. */ #define HAVE_SETEGID 1 /* Define to 1 if you have the `seteuid' function. */ #define HAVE_SETEUID 1 /* Define to 1 if you have the `setlinebuf' function. */ #define HAVE_SETLINEBUF 1 /* Define to 1 if you have the `setlocale' function. */ /* #undef HAVE_SETLOCALE */ /* Define to 1 if you have the `setregid' function. */ #define HAVE_SETREGID 1 /* Define to 1 if you have the `setreuid' function. */ #define HAVE_SETREUID 1 /* Define to 1 if you have the `setrlimit' function. */ #define HAVE_SETRLIMIT 1 /* Define to 1 if you have the `setvbuf' function. */ #define HAVE_SETVBUF 1 /* Define to 1 if you have the `sigaction' function. */ #define HAVE_SIGACTION 1 /* Define to 1 if you have the `sigsetmask' function. */ #define HAVE_SIGSETMASK 1 /* Define to 1 if you have the `socket' function. */ /* #undef HAVE_SOCKET */ /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 /* Define to 1 if you have the `strcmpi' function. */ /* #undef HAVE_STRCMPI */ /* Define to 1 if you have the `strcoll' function and it is properly defined. */ #define HAVE_STRCOLL 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the `stricmp' function. */ /* #undef HAVE_STRICMP */ /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strncasecmp' function. */ #define HAVE_STRNCASECMP 1 /* Define to 1 if you have the `strncmpi' function. */ /* #undef HAVE_STRNCMPI */ /* Define to 1 if you have the `strndup' function. */ #define HAVE_STRNDUP 1 /* Define to 1 if you have the `strnicmp' function. */ /* #undef HAVE_STRNICMP */ /* Define to 1 if you have the `strsignal' function. */ #define HAVE_STRSIGNAL 1 /* Define to 1 if `n_un.n_name' is a member of `struct nlist'. */ /* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* 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, and it defines `DIR'. */ /* #undef HAVE_SYS_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_RESOURCE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SELECT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIMEB_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_WAIT_H 1 /* Define to 1 if you have the `ttyname' function. */ #define HAVE_TTYNAME 1 /* Define to 1 if the system has the type `uintmax_t'. */ #define HAVE_UINTMAX_T 1 /* Define to 1 if you have the 'union wait' type in . */ /* #undef HAVE_UNION_WAIT */ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if the system has the type `unsigned long long int'. */ #define HAVE_UNSIGNED_LONG_LONG_INT 1 /* Define to 1 if you have the `vfork' function. */ #define HAVE_VFORK 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VFORK_H */ /* Define to 1 if you have the `wait3' function. */ #define HAVE_WAIT3 1 /* Define to 1 if you have the `waitpid' function. */ #define HAVE_WAITPID 1 /* Define to 1 if `fork' works. */ #define HAVE_WORKING_FORK 1 /* Define to 1 if `vfork' works. */ #define HAVE_WORKING_VFORK 1 /* Build host information. (not used by kmk) */ #if defined(KBUILD_ARCH_X86) # define MAKE_HOST "i686-pc-linux-gnu" #elif defined(KBUILD_ARCH_AMD64) # define MAKE_HOST "amd64-pc-linux-gnu" #else # define MAKE_HOST "aarch64-unknown-linux-gnu" #endif /* Define to 1 to enable job server support in GNU make. */ #define MAKE_JOBSERVER 1 /* Define to 1 to enable 'load' support in GNU make. */ /* #undef MAKE_LOAD */ /* Define to 1 to enable symbolic link timestamp checking. */ #define MAKE_SYMLINKS 1 /* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend on `HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* #undef NLIST_NAME_UNION */ /* Define to 1 if struct nlist.n_name is a pointer rather than an array. */ /* #undef NLIST_STRUCT */ /* Name of package */ #define PACKAGE "make" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bug-make@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "GNU make" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "GNU make 4.2.1" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "make" /* Define to the home page for this package. */ #define PACKAGE_URL "http://kbuild.org/" /* Define to the version of this package. */ #define PACKAGE_VERSION "4.2.1" /* Define to the character that separates directories in PATH. */ #define PATH_SEPARATOR_CHAR ':' /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* Define to the name of the SCCS 'get' command. */ #define SCCS_GET "get" /* Define to 1 if the SCCS 'get' command understands the '-G' option. */ /* #undef SCCS_GET_MINUS_G */ /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if the `S_IS*' macros in do not work properly. */ /* #undef STAT_MACROS_BROKEN */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define if struct stat contains a nanoseconds field */ #if defined(__USE_XOPEN2K8) || defined(__USE_MISC) # define ST_MTIM_NSEC st_mtim.tv_nsec # define ST_ATIM_NSEC st_atim.tv_nsec #else # define ST_MTIM_NSEC st_mtimensec # define ST_ATIM_NSEC st_atimensec #endif /* Define to 1 on System V Release 4. */ /* #undef SVR4 */ /* Define to 1 if you can safely include both and . */ #define TIME_WITH_SYS_TIME 1 /* Define to 1 for Encore UMAX. */ /* #undef UMAX */ /* Define to 1 for Encore UMAX 4.3 that has instead of . */ /* #undef UMAX4_3 */ /* Version number of package */ #define VERSION "4.2.1" /* Use platform specific coding */ /* #undef WINDOWS32 */ /* Define if using the dmalloc debugging malloc package */ /* #undef WITH_DMALLOC */ /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ #if defined(KBUILD_ARCH_X86) || defined(KBUILD_ARCH_AMD64) # define _FILE_OFFSET_BITS 64 #else /* #undef _FILE_OFFSET_BITS */ #endif /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `int' if doesn't define. */ /* #undef gid_t */ /* Define to `long int' if does not define. */ /* #undef off_t */ /* Define to `int' if does not define. */ /* #undef pid_t */ /* Define to `unsigned int' if does not define. */ /* #undef size_t */ /* Define to `int' if does not define. */ /* #undef ssize_t */ /* Define to `int' if doesn't define. */ /* #undef uid_t */ /* Define to the widest unsigned integer type if and do not define. */ /* #undef uintmax_t */ /* Define as `fork' if `vfork' does not work. */ /* #undef vfork */ #include "inlined_memchr.h" kbuild-3686/src/kmk/strcache2.c0000664000175000017500000011556615053010075016321 0ustar locutuslocutus/* $Id: strcache2.c 3140 2018-03-14 21:28:10Z bird $ */ /** @file * strcache2 - New string cache. */ /* * Copyright (c) 2008-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "makeint.h" #include "strcache2.h" #include #include "debug.h" #ifdef _MSC_VER typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; #else # include #endif #ifdef WINDOWS32 # include # include # include # define PARSE_IN_WORKER #endif #ifdef __OS2__ # include #endif #ifdef HAVE_PTHREAD # include #endif /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ /* The default size of a memory segment (1MB). */ #define STRCACHE2_SEG_SIZE (1024U*1024U) /* The default hash table shift (hash size give as a power of two). */ #define STRCACHE2_HASH_SHIFT 16 /** Does the modding / masking of a hash number into an index. */ #ifdef STRCACHE2_USE_MASK # define STRCACHE2_MOD_IT(cache, hash) ((hash) & (cache)->hash_mask) #else # define STRCACHE2_MOD_IT(cache, hash) ((hash) % (cache)->hash_div) #endif # if ( defined(__amd64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_X64) || defined(__amd64) \ || defined(__i386__) || defined(__x86__) || defined(__X86__) || defined(_M_IX86) || defined(__i386)) \ && !defined(GCC_ADDRESS_SANITIZER) # define strcache2_get_unaligned_16bits(ptr) ( *((const uint16_t *)(ptr))) # else /* (endian doesn't matter) */ # define strcache2_get_unaligned_16bits(ptr) ( (((const uint8_t *)(ptr))[0] << 8) \ | (((const uint8_t *)(ptr))[1]) ) # endif /******************************************************************************* * Global Variables * *******************************************************************************/ /* List of initialized string caches. */ static struct strcache2 *strcache_head; #ifndef STRCACHE2_USE_MASK /** Finds the closest primary number for power of two value (or something else * useful if not support). */ MY_INLINE unsigned int strcache2_find_prime(unsigned int shift) { switch (shift) { case 5: return 31; case 6: return 61; case 7: return 127; case 8: return 251; case 9: return 509; case 10: return 1021; case 11: return 2039; case 12: return 4093; case 13: return 8191; case 14: return 16381; case 15: return 32749; case 16: return 65521; case 17: return 131063; case 18: return 262139; case 19: return 524269; case 20: return 1048573; case 21: return 2097143; case 22: return 4194301; case 23: return 8388593; default: assert (0); return (1 << shift) - 1; } } #endif /* The following is a bit experiment. It produces longer chains, i.e. worse distribution of the strings in the table, however the actual make performances is better (> 2); while (head-- > 0) { hash += strcache2_get_unaligned_16bits (str); tmp = (strcache2_get_unaligned_16bits (str + 2) << 11) ^ hash; hash = (hash << 16) ^ tmp; str += 2 * sizeof (uint16_t); hash += hash >> 11; } /* tail BIG_HASH_TAIL bytes (minus the odd ones) */ str += (len - BIG_HASH_HEAD - BIG_HASH_TAIL) & ~3U; head = (BIG_HASH_TAIL >> 2); while (head-- > 0) { hash += strcache2_get_unaligned_16bits (str); tmp = (strcache2_get_unaligned_16bits (str + 2) << 11) ^ hash; hash = (hash << 16) ^ tmp; str += 2 * sizeof (uint16_t); hash += hash >> 11; } /* force "avalanching" of final 127 bits. */ hash ^= hash << 3; hash += hash >> 5; hash ^= hash << 4; hash += hash >> 17; hash ^= hash << 25; hash += hash >> 6; return hash; } #endif /* BIG_HASH_SIZE */ MY_INLINE unsigned int strcache2_case_sensitive_hash (const char *str, unsigned int len) { #if 1 /* Paul Hsieh hash SuperFast function: http://www.azillionmonkeys.com/qed/hash.html This performs very good and as a sligtly better distribution than STRING_N_HASH_1 on a typical kBuild run. It is also 37% faster than return_STRING_N_HASH_1 when running the two 100 times over typical kBuild strings that end up here (did a fprintf here and built kBuild). Compiler was 32-bit gcc 4.0.1, darwin, with -O2. FIXME: A path for well aligned data should be added to speed up execution on alignment sensitive systems. */ unsigned int rem; uint32_t hash; uint32_t tmp; assert (sizeof (uint8_t) == sizeof (char)); # ifdef BIG_HASH_SIZE /* long string? */ # if 0 /*BIG_HASH_SIZE > 128*/ if (MY_PREDICT_FALSE(len >= BIG_HASH_SIZE)) # else if (len >= BIG_HASH_SIZE) # endif return strcache2_case_sensitive_hash_big (str, len); # endif /* short string: main loop, walking on 2 x uint16_t */ hash = len; rem = len & 3; len >>= 2; while (len > 0) { hash += strcache2_get_unaligned_16bits (str); tmp = (strcache2_get_unaligned_16bits (str + 2) << 11) ^ hash; hash = (hash << 16) ^ tmp; str += 2 * sizeof (uint16_t); hash += hash >> 11; len--; } /* the remainder */ switch (rem) { case 3: hash += strcache2_get_unaligned_16bits (str); hash ^= hash << 16; hash ^= str[sizeof (uint16_t)] << 18; hash += hash >> 11; break; case 2: hash += strcache2_get_unaligned_16bits (str); hash ^= hash << 11; hash += hash >> 17; break; case 1: hash += *str; hash ^= hash << 10; hash += hash >> 1; break; } /* force "avalanching" of final 127 bits. */ hash ^= hash << 3; hash += hash >> 5; hash ^= hash << 4; hash += hash >> 17; hash ^= hash << 25; hash += hash >> 6; return hash; #elif 1 /* Note! This implementation is 18% faster than return_STRING_N_HASH_1 when running the two 100 times over typical kBuild strings that end up here (did a fprintf here and built kBuild). Compiler was 32-bit gcc 4.0.1, darwin, with -O2. */ unsigned int hash = 0; if (MY_PREDICT_TRUE(len >= 2)) { unsigned int ch0 = *str++; hash = 0; len--; while (len >= 2) { unsigned int ch1 = *str++; hash += ch0 << (ch1 & 0xf); ch0 = *str++; hash += ch1 << (ch0 & 0xf); len -= 2; } if (len == 1) { unsigned ch1 = *str; hash += ch0 << (ch1 & 0xf); hash += ch1; } else hash += ch0; } else if (len) { hash = *str; hash += hash << (hash & 0xf); } else hash = 0; return hash; #elif 1 # if 0 /* This is SDBM. This specific form/unroll was benchmarked to be 28% faster than return_STRING_N_HASH_1. (Now the weird thing is that putting the (ch) first in the assignment made it noticably slower.) However, it is noticably slower in practice, most likely because of more collisions. Hrmpf. */ # define UPDATE_HASH(ch) hash = (hash << 6) + (hash << 16) - hash + (ch) unsigned int hash = 0; # else /* This is DJB2. This specific form/unroll was benchmarked to be 27% fast than return_STRING_N_HASH_1. Ditto. */ # define UPDATE_HASH(ch) hash = (hash << 5) + hash + (ch) unsigned int hash = 5381; # endif while (len >= 4) { UPDATE_HASH (str[0]); UPDATE_HASH (str[1]); UPDATE_HASH (str[2]); UPDATE_HASH (str[3]); str += 4; len -= 4; } switch (len) { default: case 0: return hash; case 1: UPDATE_HASH (str[0]); return hash; case 2: UPDATE_HASH (str[0]); UPDATE_HASH (str[1]); return hash; case 3: UPDATE_HASH (str[0]); UPDATE_HASH (str[1]); UPDATE_HASH (str[2]); return hash; } #endif } MY_INLINE unsigned int strcache2_case_insensitive_hash (const char *str, unsigned int len) { unsigned int hash = 0; if (MY_PREDICT_TRUE(len >= 2)) { unsigned int ch0 = *str++; ch0 = tolower (ch0); hash = 0; len--; while (len >= 2) { unsigned int ch1 = *str++; ch1 = tolower (ch1); hash += ch0 << (ch1 & 0xf); ch0 = *str++; ch0 = tolower (ch0); hash += ch1 << (ch0 & 0xf); len -= 2; } if (len == 1) { unsigned ch1 = *str; ch1 = tolower (ch1); hash += ch0 << (ch1 & 0xf); hash += ch1; } else hash += ch0; } else if (len) { hash = *str; hash += hash << (hash & 0xf); } else hash = 0; return hash; } #if 0 MY_INLINE int strcache2_memcmp_inline_short (const char *xs, const char *ys, unsigned int length) { if (length <= 8) { /* short string compare - ~50% of the kBuild calls. */ assert ( !((size_t)ys & 3) ); if (!((size_t)xs & 3)) { /* aligned */ int result; switch (length) { default: /* memcmp for longer strings */ return memcmp (xs, ys, length); case 8: result = *(int32_t*)(xs + 4) - *(int32_t*)(ys + 4); result |= *(int32_t*)xs - *(int32_t*)ys; return result; case 7: result = xs[6] - ys[6]; result |= xs[5] - ys[5]; result |= xs[4] - ys[4]; result |= *(int32_t*)xs - *(int32_t*)ys; return result; case 6: result = xs[5] - ys[5]; result |= xs[4] - ys[4]; result |= *(int32_t*)xs - *(int32_t*)ys; return result; case 5: result = xs[4] - ys[4]; result |= *(int32_t*)xs - *(int32_t*)ys; return result; case 4: return *(int32_t*)xs - *(int32_t*)ys; case 3: result = xs[2] - ys[2]; result |= xs[1] - ys[1]; result |= xs[0] - ys[0]; return result; case 2: result = xs[1] - ys[1]; result |= xs[0] - ys[0]; return result; case 1: return *xs - *ys; case 0: return 0; } } else { /* unaligned */ int result = 0; switch (length) { case 8: result |= xs[7] - ys[7]; case 7: result |= xs[6] - ys[6]; case 6: result |= xs[5] - ys[5]; case 5: result |= xs[4] - ys[4]; case 4: result |= xs[3] - ys[3]; case 3: result |= xs[2] - ys[2]; case 2: result |= xs[1] - ys[1]; case 1: result |= xs[0] - ys[0]; case 0: return result; } } } /* memcmp for longer strings */ return memcmp (xs, ys, length); } #endif MY_INLINE int strcache2_memcmp_inlined (const char *xs, const char *ys, unsigned int length) { #ifndef ELECTRIC_HEAP assert ( !((size_t)ys & 3) ); #endif if (!((size_t)xs & 3)) { /* aligned */ int result; unsigned reminder = length & 7; length >>= 3; while (length-- > 0) { result = *(int32_t*)xs - *(int32_t*)ys; result |= *(int32_t*)(xs + 4) - *(int32_t*)(ys + 4); if (MY_PREDICT_FALSE(result)) return result; xs += 8; ys += 8; } switch (reminder) { case 7: result = *(int32_t*)xs - *(int32_t*)ys; result |= xs[6] - ys[6]; result |= xs[5] - ys[5]; result |= xs[4] - ys[4]; return result; case 6: result = *(int32_t*)xs - *(int32_t*)ys; result |= xs[5] - ys[5]; result |= xs[4] - ys[4]; return result; case 5: result = *(int32_t*)xs - *(int32_t*)ys; result |= xs[4] - ys[4]; return result; case 4: return *(int32_t*)xs - *(int32_t*)ys; case 3: result = xs[2] - ys[2]; result |= xs[1] - ys[1]; result |= xs[0] - ys[0]; return result; case 2: result = xs[1] - ys[1]; result |= xs[0] - ys[0]; return result; case 1: return *xs - *ys; default: case 0: return 0; } } else { /* unaligned */ int result; unsigned reminder = length & 7; length >>= 3; while (length-- > 0) { #if defined(__i386__) || defined(__x86_64__) result = ( ((int32_t)xs[3] << 24) | ((int32_t)xs[2] << 16) | ((int32_t)xs[1] << 8) | xs[0] ) - *(int32_t*)ys; result |= ( ((int32_t)xs[7] << 24) | ((int32_t)xs[6] << 16) | ((int32_t)xs[5] << 8) | xs[4] ) - *(int32_t*)(ys + 4); #else result = xs[3] - ys[3]; result |= xs[2] - ys[2]; result |= xs[1] - ys[1]; result |= xs[0] - ys[0]; result |= xs[7] - ys[7]; result |= xs[6] - ys[6]; result |= xs[5] - ys[5]; result |= xs[4] - ys[4]; #endif if (MY_PREDICT_FALSE(result)) return result; xs += 8; ys += 8; } result = 0; switch (reminder) { case 7: result |= xs[6] - ys[6]; /* fall thru */ case 6: result |= xs[5] - ys[5]; /* fall thru */ case 5: result |= xs[4] - ys[4]; /* fall thru */ case 4: result |= xs[3] - ys[3]; /* fall thru */ case 3: result |= xs[2] - ys[2]; /* fall thru */ case 2: result |= xs[1] - ys[1]; /* fall thru */ case 1: result |= xs[0] - ys[0]; /* fall thru */ return result; default: case 0: return 0; } } } MY_INLINE int strcache2_is_equal (struct strcache2 *cache, struct strcache2_entry const *entry, const char *str, unsigned int length, unsigned int hash) { assert (!cache->case_insensitive); /* the simple stuff first. */ if ( entry->hash != hash || entry->length != length) return 0; #if 0 return memcmp (str, entry + 1, length) == 0; #elif 1 return strcache2_memcmp_inlined (str, (const char *)(entry + 1), length) == 0; #else return strcache2_memcmp_inline_short (str, (const char *)(entry + 1), length) == 0; #endif } #if defined(HAVE_CASE_INSENSITIVE_FS) MY_INLINE int strcache2_is_iequal (struct strcache2 *cache, struct strcache2_entry const *entry, const char *str, unsigned int length, unsigned int hash) { assert (cache->case_insensitive); /* the simple stuff first. */ if ( entry->hash != hash || entry->length != length) return 0; # if defined(_MSC_VER) || defined(__OS2__) return _memicmp (entry + 1, str, length) == 0; # else return strncasecmp ((const char *)(entry + 1), str, length) == 0; # endif } #endif /* HAVE_CASE_INSENSITIVE_FS */ static void strcache2_rehash (struct strcache2 *cache) { unsigned int src = cache->hash_size; struct strcache2_entry **src_tab = cache->hash_tab; struct strcache2_entry **dst_tab; #ifndef STRCACHE2_USE_MASK unsigned int hash_shift; #endif /* Allocate a new hash table twice the size of the current. */ cache->hash_size <<= 1; #ifdef STRCACHE2_USE_MASK cache->hash_mask <<= 1; cache->hash_mask |= 1; #else for (hash_shift = 1; (1U << hash_shift) < cache->hash_size; hash_shift++) /* nothing */; cache->hash_div = strcache2_find_prime (hash_shift); #endif cache->rehash_count <<= 1; cache->hash_tab = dst_tab = (struct strcache2_entry **) xmalloc (cache->hash_size * sizeof (struct strcache2_entry *)); memset (dst_tab, '\0', cache->hash_size * sizeof (struct strcache2_entry *)); /* Copy the entries from the old to the new hash table. */ cache->collision_count = 0; while (src-- > 0) { struct strcache2_entry *entry = src_tab[src]; while (entry) { struct strcache2_entry *next = entry->next; unsigned int dst = STRCACHE2_MOD_IT (cache, entry->hash); if ((entry->next = dst_tab[dst]) != 0) cache->collision_count++; dst_tab[dst] = entry; entry = next; } } /* That's it, just free the old table and we're done. */ free (src_tab); } static struct strcache2_seg * strcache2_new_seg (struct strcache2 *cache, unsigned int minlen) { struct strcache2_seg *seg; size_t size; size_t off; size = cache->def_seg_size; if (size < (size_t)minlen + sizeof (struct strcache2_seg) + STRCACHE2_ENTRY_ALIGNMENT) { size = (size_t)minlen * 2; size = (size + 0xfff) & ~(size_t)0xfff; } seg = xmalloc (size); seg->start = (char *)(seg + 1); seg->size = size - sizeof (struct strcache2_seg); off = (size_t)seg->start & (STRCACHE2_ENTRY_ALIGNMENT - 1); if (off) { off = STRCACHE2_ENTRY_ALIGNMENT - off; seg->start += off; seg->size -= off; } assert (seg->size > minlen); seg->cursor = seg->start; seg->avail = seg->size; seg->next = cache->seg_head; cache->seg_head = seg; return seg; } /* Internal worker that enters a new string into the cache. */ static const char * strcache2_enter_string (struct strcache2 *cache, unsigned int idx, const char *str, unsigned int length, unsigned int hash) { struct strcache2_entry *entry; struct strcache2_seg *seg; unsigned int size; char *str_copy; /* Allocate space for the string. */ size = length + 1 + sizeof (struct strcache2_entry); size = (size + STRCACHE2_ENTRY_ALIGNMENT - 1) & ~(STRCACHE2_ENTRY_ALIGNMENT - 1U); seg = cache->seg_head; if (MY_PREDICT_FALSE(seg->avail < size)) { do seg = seg->next; while (seg && seg->avail < size); if (!seg) seg = strcache2_new_seg (cache, size); } entry = (struct strcache2_entry *) seg->cursor; assert (!((size_t)entry & (STRCACHE2_ENTRY_ALIGNMENT - 1))); seg->cursor += size; seg->avail -= size; /* Setup the entry, copy the string and insert it into the hash table. */ entry->user = NULL; entry->length = length; entry->hash = hash; str_copy = (char *) memcpy (entry + 1, str, length); str_copy[length] = '\0'; if ((entry->next = cache->hash_tab[idx]) != 0) cache->collision_count++; cache->hash_tab[idx] = entry; cache->count++; if (cache->count >= cache->rehash_count) strcache2_rehash (cache); return str_copy; } /* The public add string interface. */ const char * strcache2_add (struct strcache2 *cache, const char *str, unsigned int length) { struct strcache2_entry const *entry; unsigned int hash = strcache2_case_sensitive_hash (str, length); unsigned int idx; assert (!cache->case_insensitive); assert (!memchr (str, '\0', length)); MAKE_STATS (cache->lookup_count++); /* Lookup the entry in the hash table, hoping for an early match. If not found, enter the string at IDX. */ idx = STRCACHE2_MOD_IT (cache, hash); entry = cache->hash_tab[idx]; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_1st_count++); entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_2nd_count++); /* Loop the rest. */ for (;;) { entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_3rd_count++); } /* not reached */ } /* The public add string interface for prehashed strings. Use strcache2_hash_str to calculate the hash of a string. */ const char * strcache2_add_hashed (struct strcache2 *cache, const char *str, unsigned int length, unsigned int hash) { struct strcache2_entry const *entry; unsigned int idx; #ifndef NDEBUG unsigned correct_hash; assert (!cache->case_insensitive); assert (!memchr (str, '\0', length)); correct_hash = strcache2_case_sensitive_hash (str, length); MY_ASSERT_MSG (hash == correct_hash, ("%#x != %#x\n", hash, correct_hash)); #endif /* NDEBUG */ MAKE_STATS (cache->lookup_count++); /* Lookup the entry in the hash table, hoping for an early match. If not found, enter the string at IDX. */ idx = STRCACHE2_MOD_IT (cache, hash); entry = cache->hash_tab[idx]; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_1st_count++); entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_2nd_count++); /* Loop the rest. */ for (;;) { entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_3rd_count++); } /* not reached */ } /* The public lookup (case sensitive) string interface. */ const char * strcache2_lookup (struct strcache2 *cache, const char *str, unsigned int length) { struct strcache2_entry const *entry; unsigned int hash = strcache2_case_sensitive_hash (str, length); unsigned int idx; assert (!cache->case_insensitive); assert (!memchr (str, '\0', length)); MAKE_STATS (cache->lookup_count++); /* Lookup the entry in the hash table, hoping for an early match. */ idx = STRCACHE2_MOD_IT (cache, hash); entry = cache->hash_tab[idx]; if (!entry) return NULL; if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_1st_count++); entry = entry->next; if (!entry) return NULL; if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_2nd_count++); /* Loop the rest. */ for (;;) { entry = entry->next; if (!entry) return NULL; if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_3rd_count++); } /* not reached */ } #if defined(HAVE_CASE_INSENSITIVE_FS) /* The public add string interface for case insensitive strings. */ const char * strcache2_iadd (struct strcache2 *cache, const char *str, unsigned int length) { struct strcache2_entry const *entry; unsigned int hash = strcache2_case_insensitive_hash (str, length); unsigned int idx; assert (cache->case_insensitive); assert (!memchr (str, '\0', length)); MAKE_STATS (cache->lookup_count++); /* Lookup the entry in the hash table, hoping for an early match. If not found, enter the string at IDX. */ idx = STRCACHE2_MOD_IT (cache, hash); entry = cache->hash_tab[idx]; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_iequal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_1st_count++); entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_iequal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_2nd_count++); /* Loop the rest. */ for (;;) { entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_iequal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_3rd_count++); } /* not reached */ } /* The public add string interface for prehashed case insensitive strings. Use strcache2_hash_istr to calculate the hash of a string. */ const char * strcache2_iadd_hashed (struct strcache2 *cache, const char *str, unsigned int length, unsigned int hash) { struct strcache2_entry const *entry; unsigned int idx; #ifndef NDEBUG unsigned correct_hash; assert (cache->case_insensitive); assert (!memchr (str, '\0', length)); correct_hash = strcache2_case_insensitive_hash (str, length); MY_ASSERT_MSG (hash == correct_hash, ("%#x != %#x\n", hash, correct_hash)); #endif /* NDEBUG */ MAKE_STATS (cache->lookup_count++); /* Lookup the entry in the hash table, hoping for an early match. If not found, enter the string at IDX. */ idx = STRCACHE2_MOD_IT (cache, hash); entry = cache->hash_tab[idx]; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_iequal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_1st_count++); entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_iequal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_2nd_count++); /* Loop the rest. */ for (;;) { entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_iequal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_3rd_count++); } /* not reached */ } /* The public lookup (case insensitive) string interface. */ const char * strcache2_ilookup (struct strcache2 *cache, const char *str, unsigned int length) { struct strcache2_entry const *entry; unsigned int hash = strcache2_case_insensitive_hash (str, length); unsigned int idx; assert (cache->case_insensitive); assert (!memchr (str, '\0', length)); MAKE_STATS (cache->lookup_count++); /* Lookup the entry in the hash table, hoping for an early match. */ idx = STRCACHE2_MOD_IT (cache, hash); entry = cache->hash_tab[idx]; if (!entry) return NULL; if (strcache2_is_iequal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_1st_count++); entry = entry->next; if (!entry) return NULL; if (strcache2_is_iequal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_2nd_count++); /* Loop the rest. */ for (;;) { entry = entry->next; if (!entry) return NULL; if (strcache2_is_iequal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_3rd_count++); } /* not reached */ } #endif /* HAVE_CASE_INSENSITIVE_FS */ /* Is the given string cached? returns 1 if it is, 0 if it isn't. */ int strcache2_is_cached (struct strcache2 *cache, const char *str) { /* Check mandatory alignment first. */ if (!((size_t)str & (sizeof (void *) - 1))) { /* Check the segment list and consider the question answered if the string is within one of them. (Could check it more thoroughly...) */ struct strcache2_seg const *seg; for (seg = cache->seg_head; seg; seg = seg->next) if ((size_t)(str - seg->start) < seg->size) return 1; } return 0; } /* Verify the integrity of the specified string, returning 0 if OK. */ int strcache2_verify_entry (struct strcache2 *cache, const char *str) { struct strcache2_entry const *entry; unsigned int hash; unsigned int length; const char *end; entry = (struct strcache2_entry const *)str - 1; if ((size_t)entry & (STRCACHE2_ENTRY_ALIGNMENT - 1)) { fprintf (stderr, "strcache2[%s]: missaligned entry %p\nstring: %p=%s\n", cache->name, (void *)entry, (void *)str, str); return -1; } end = memchr (str, '\0', entry->length + 1); length = end - str; if (length != entry->length) { fprintf (stderr, "strcache2[%s]: corrupt entry %p, length: %u, expected %u;\nstring: %s\n", cache->name, (void *)entry, length, entry->length, str); return -1; } hash = cache->case_insensitive ? strcache2_case_insensitive_hash (str, entry->length) : strcache2_case_sensitive_hash (str, entry->length); if (hash != entry->hash) { fprintf (stderr, "strcache2[%s]: corrupt entry %p, hash: %x, expected %x;\nstring: %s\n", cache->name, (void *)entry, hash, entry->hash, str); return -1; } return 0; } /* Calculates the case sensitive hash values of the string. The first hash is returned, the other is put at HASH2P. */ unsigned int strcache2_hash_str (const char *str, unsigned int length, unsigned int *hash2p) { *hash2p = 1; return strcache2_case_sensitive_hash (str, length); } /* Calculates the case insensitive hash values of the string. The first hash is returned, the other is put at HASH2P. */ unsigned int strcache2_hash_istr (const char *str, unsigned int length, unsigned int *hash2p) { *hash2p = 1; return strcache2_case_insensitive_hash (str, length); } /* Initalizes a new cache. */ void strcache2_init (struct strcache2 *cache, const char *name, unsigned int size, unsigned int def_seg_size, int case_insensitive, int thread_safe) { unsigned hash_shift; assert (!thread_safe); /* calc the size as a power of two */ if (!size) hash_shift = STRCACHE2_HASH_SHIFT; else { assert (size <= (~0U / 2 + 1)); for (hash_shift = 8; (1U << hash_shift) < size; hash_shift++) /* nothing */; } /* adjust the default segment size */ if (!def_seg_size) def_seg_size = STRCACHE2_SEG_SIZE; else if (def_seg_size < sizeof (struct strcache2_seg) * 10) def_seg_size = sizeof (struct strcache2_seg) * 10; else if ((def_seg_size & 0xfff) < 0xf00) def_seg_size = ((def_seg_size + 0xfff) & ~0xfffU); /* init the structure. */ cache->case_insensitive = case_insensitive; #ifdef STRCACHE2_USE_MASK cache->hash_mask = (1U << hash_shift) - 1U; #else cache->hash_div = strcache2_find_prime(hash_shift); #endif cache->count = 0; cache->collision_count = 0; cache->lookup_count = 0; cache->collision_1st_count = 0; cache->collision_2nd_count = 0; cache->collision_3rd_count = 0; cache->rehash_count = (1U << hash_shift) / 4 * 3; /* rehash at 75% */ cache->init_size = 1U << hash_shift; cache->hash_size = 1U << hash_shift; cache->def_seg_size = def_seg_size; cache->lock = NULL; cache->name = name; /* allocate the hash table and first segment. */ cache->hash_tab = (struct strcache2_entry **) xmalloc (cache->init_size * sizeof (struct strcache2_entry *)); memset (cache->hash_tab, '\0', cache->init_size * sizeof (struct strcache2_entry *)); strcache2_new_seg (cache, 0); /* link it */ cache->next = strcache_head; strcache_head = cache; } /* Terminates a string cache, freeing all memory and other associated resources. */ void strcache2_term (struct strcache2 *cache) { /* unlink it */ if (strcache_head == cache) strcache_head = cache->next; else { struct strcache2 *prev = strcache_head; while (prev->next != cache) prev = prev->next; assert (prev); prev->next = cache->next; } /* free the memory segments */ do { void *free_it = cache->seg_head; cache->seg_head = cache->seg_head->next; free (free_it); } while (cache->seg_head); /* free the hash and clear the structure. */ free (cache->hash_tab); memset (cache, '\0', sizeof (struct strcache2)); } /* Print statistics a string cache. */ void strcache2_print_stats (struct strcache2 *cache, const char *prefix) { unsigned int seg_count = 0; unsigned long seg_total_bytes = 0; unsigned long seg_avg_bytes; unsigned long seg_avail_bytes = 0; unsigned long seg_max_bytes = 0; struct strcache2_seg *seg; unsigned int str_count = 0; unsigned long str_total_len = 0; unsigned int str_avg_len; unsigned int str_min_len = ~0U; unsigned int str_max_len = 0; unsigned int idx; unsigned int rehashes; unsigned int chain_depths[32]; printf (_("\n%s strcache2: %s\n"), prefix, cache->name); /* Segment statistics. */ for (seg = cache->seg_head; seg; seg = seg->next) { seg_count++; seg_total_bytes += seg->size; seg_avail_bytes += seg->avail; if (seg->size > seg_max_bytes) seg_max_bytes = seg->size; } seg_avg_bytes = seg_total_bytes / seg_count; printf (_("%s %u segments: total = %lu / max = %lu / avg = %lu / def = %u avail = %lu\n"), prefix, seg_count, seg_total_bytes, seg_max_bytes, seg_avg_bytes, cache->def_seg_size, seg_avail_bytes); /* String statistics. */ memset (chain_depths, '\0', sizeof (chain_depths)); idx = cache->hash_size; while (idx-- > 0) { struct strcache2_entry const *entry = cache->hash_tab[idx]; unsigned int depth = 0; for (; entry != 0; entry = entry->next, depth++) { unsigned int length = entry->length; str_total_len += length; if (length > str_max_len) str_max_len = length; if (length < str_min_len) str_min_len = length; str_count++; } chain_depths[depth >= 32 ? 31 : depth]++; } str_avg_len = cache->count ? str_total_len / cache->count : 0; printf (_("%s %u strings: total len = %lu / max = %u / avg = %u / min = %u\n"), prefix, cache->count, str_total_len, str_max_len, str_avg_len, str_min_len); if (str_count != cache->count) printf (_("%s string count mismatch! cache->count=%u, actual count is %u\n"), prefix, cache->count, str_count); /* Hash statistics. */ idx = cache->init_size; rehashes = 0; while (idx < cache->hash_size) { idx *= 2; rehashes++; } #ifdef STRCACHE2_USE_MASK printf (_("%s hash size = %u mask = %#x rehashed %u times"), prefix, cache->hash_size, cache->hash_mask, rehashes); #else printf (_("%s hash size = %u div = %#x rehashed %u times"), prefix, cache->hash_size, cache->hash_div, rehashes); #endif if (cache->lookup_count) printf (_("%s lookups = %lu\n" "%s hash collisions 1st = %lu (%u%%) 2nd = %lu (%u%%) 3rd = %lu (%u%%)"), prefix, cache->lookup_count, prefix, cache->collision_1st_count, (unsigned int)((100.0 * cache->collision_1st_count) / cache->lookup_count), cache->collision_2nd_count, (unsigned int)((100.0 * cache->collision_2nd_count) / cache->lookup_count), cache->collision_3rd_count, (unsigned int)((100.0 * cache->collision_3rd_count) / cache->lookup_count)); printf (_("\n%s hash insert collisions = %u (%u%%)\n"), prefix, cache->collision_count,(unsigned int)((100.0 * cache->collision_count) / cache->count)); printf (_("%s %5u (%u%%) empty hash table slots\n"), prefix, chain_depths[0], (unsigned int)((100.0 * chain_depths[0]) / cache->hash_size)); printf (_("%s %5u (%u%%) occupied hash table slots\n"), prefix, chain_depths[1], (unsigned int)((100.0 * chain_depths[1]) / cache->hash_size)); for (idx = 2; idx < 32; idx++) { unsigned strs_at_this_depth = chain_depths[idx]; unsigned i; for (i = idx + 1; i < 32; i++) strs_at_this_depth += chain_depths[i]; if (strs_at_this_depth) printf (_("%s %5u (%2u%%) with %u string%s chained on; %5u (%2u%%) strings at depth %u.\n"), prefix, chain_depths[idx], (unsigned int)((100.0 * chain_depths[idx]) / (cache->count - cache->collision_count)), idx - 1, idx == 2 ? " " : "s", strs_at_this_depth, (unsigned int)((100.0 * strs_at_this_depth) / cache->count), idx - 1); } } /* Print statistics for all string caches. */ void strcache2_print_stats_all (const char *prefix) { struct strcache2 *cur; for (cur = strcache_head; cur; cur = cur->next) strcache2_print_stats (cur, prefix); } kbuild-3686/src/kmk/doc/0000775000175000017500000000000015053010075015026 5ustar locutuslocutuskbuild-3686/src/kmk/doc/Makefile.am0000664000175000017500000000160415053010075017063 0ustar locutuslocutus# -*-Makefile-*-, or close enough # Copyright (C) 2000-2016 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) any later # version. # # GNU Make 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, see . TEXI2HTML = texi2html TEXI2HTML_FLAGS = -split_chapter info_TEXINFOS = make.texi make_TEXINFOS = fdl.texi make-stds.texi CLEANFILES = make*.html kbuild-3686/src/kmk/doc/.gitignore0000664000175000017500000000032515053010075017016 0ustar locutuslocutusmanual/ gendocs_template fdl.texi make-stds.texi stamp-vti version.texi make.info* make*.html make.aux make.cp make.cps make.dvi make.fn make.fns make.ky make.log make.pdf make.pg make.ps make.toc make.tp make.vr kbuild-3686/src/kmk/README.OS2.template0000664000175000017500000001477515053010075017373 0ustar locutuslocutusPort of GNU make to OS/2. Features of GNU make that do not work under OS/2: - remote job execution - dynamic load balancing Special features of the OS/2 version: Due to the fact that some people might want to use sh syntax in Makefiles while others might want to use OS/2's native shell cmd.exe, GNU make supports both shell types. The following list defines the order that is used to determine the shell: 1. The shell specified by the environment variable MAKESHELL. 2. The shell specified by the SHELL variable within a Makefile. Like Unix, SHELL is NOT taken from the environment. 3. The shell specified by the COMSPEC environment variable. 4. The shell specified by the OS2_SHELL environment variable. 5. If none of the above is defined /bin/sh is used as default. This happens e.g. in the make testsuite. Note: - Points 3 and 4 can be turned off at compile time by adding -DNO_CMD_DEFAULT to the CPPFLAGS. - DOS support is not tested for EMX and therefore might not work. - The UNIXROOT environment variable is supported to find /bin/sh if it is not on the current drive. COMPILATION OF GNU MAKE FOR OS/2: I. ***** SPECIAL OPTIONS ***** - At compile time you can turn off that cmd is used as default shell (but only /bin/sh). Simply set CPPFLAGS="-DNO_CMD_DEFAULT" and make will not use cmd unless you cause it to do so by setting MAKESHELL to cmd or by specifying SHELL=cmd in your Makefile. - At compile time you can set CPPFLAGS="-DNO_CHDIR2" to turn off that GNU make prints drive letters. This is necessary if you want to run the testsuite. II. ***** REQUIREMENTS FOR THE COMPILATION ***** A standard Unix like build environment: - sh compatible shell (ksh, bash, ash, but tested only with pdksh 5.2.14 release 2) If you use pdksh it is recommended to update to 5.2.14 release 2. Older versions may not work! You can get this version at http://www.math.ohio-state.edu/~ilya/software/os2/pdksh-5.2.14-bin-2.zip - GNU file utilities (make sure that install.exe from the file utilities is in front of your PATH before X:\OS2\INSTALL\INSTALL.EXE. I recommend also to change the filename to ginstall.exe instead of install.exe to avoid confusion with X:\OS2\INSTALL\INSTALL.EXE) - GNU shell utilities - GNU text utilities - gawk - grep - sed - GNU make 3.79.1 (special OS/2 patched version) or higher - perl 5.005 or higher - GNU texinfo (you can use 3.1 (gnuinfo.zip), but I recommend 4.0) If you want to recreate the configuration files (developers only!) you need also: GNU m4 1.4, autoconf 2.59, automake 1.9.6 (or compatible) III. ***** COMPILATION AND INSTALLATION ***** a) ** Developers only - Everyone else should skip this section ** To recreate the configuration files use: export EMXSHELL=ksh aclocal -I config automake autoconf autoheader b) Installation into x:/usr Note: Although it is possible to compile make using "./configure", "make", "make install" this is not recommended. In particular, you must ALWAYS use LDFLAGS="-Zstack 0x6000" because the default stack size is far to small and make will not work properly! Recommended environment variables and installation options: export ac_executable_extensions=".exe" export CPPFLAGS="-D__ST_MT_ERRNO__" export CFLAGS="-O2 -Zomf -Zmt" export LDFLAGS="-Zcrtdll -Zlinker /exepack:2 -Zlinker /pm:vio -Zstack 0x6000" export RANLIB="echo" ./configure --prefix=x:/usr --infodir=x:/usr/share/info --mandir=x:/usr/share/man --without-included-gettext make AR=emxomfar make install Note: If you use gcc 2.9.x I recommend to set also LIBS="-lgcc" Note: You can add -DNO_CMD_DEFAULT and -DNO_CHDIR2 to CPPFLAGS. See section I. for details. IV. ***** NLS support ***** GNU make has NLS (National Language Support), with the following caveats: a) It will only work with GNU gettext, and b) GNU gettext support is not included in the GNU make package. Therefore, if you wish to enable the internationalization features of GNU make you must install GNU gettext on your system before configuring GNU make. You can choose the languages to be installed. To install support for English, German and French only enter: export LINGUAS="en de fr" If you don't specify LINGUAS all languages are installed. If you don't want NLS support (English only) use the option --disable-nls for the configure script. Note if GNU gettext is not installed then NLS will not be enabled regardless of this flag. V. ***** Running the make test suite ***** To run the included make test suite you have to set CPPFLAGS="-D__ST_MT_ERRNO__ -DNO_CMD_DEFAULT -DNO_CHDIR2" before you compile make. This is due to some restrictions of the testsuite itself. -DNO_CMD_DEFAULT causes make to use /bin/sh as default shell in every case. Normally you could simply set MAKESHELL="/bin/sh" to do this but the testsuite ignores the environment. -DNO_CHDIR2 causes make not to use drive letters for directory names (i.e. _chdir2() and _getcwd2() are NOT used). The testsuite interpretes the whole output of make, especially statements like make[1]: Entering directory 'C:/somewhere/make-3.79.1/tests' where the testsuite does not expect the drive letter. This would be interpreted as an error even if there is none. To run the testsuite do the following: export CPPFLAGS="-D__ST_MT_ERRNO__ -DNO_CMD_DEFAULT -DNO_CHDIR2" export CFLAGS="-Zomf -O2 -Zmt" export LDFLAGS="-Zcrtdll -s -Zlinker /exepack:2 -Zlinker /pm:vio -Zstack 0x6000" export RANLIB="echo" ./configure --prefix=x:/usr --disable-nls make AR=emxomfar make check All tests should work fine with the exception of one of the "INCLUDE_DIRS" tests which will fail if your /usr/include directory is on a drive different from the make source tree. ------------------------------------------------------------------------------- Copyright (C) 2003-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . kbuild-3686/src/kmk/kbuildprf.c0000664000175000017500000000150515053010075016410 0ustar locutuslocutus#include #include #include #include __int64 prf_now(void) { return GetTickCount(); } #undef open int prf_open(const char *name, int of, int mask) { int fd; // int err; // __int64 t = prf_now(); fd = _open(name, of, mask); // err = errno; // t = prf_now() - t; // fprintf(stderr, "open(%s, %#x) -> %d/%d in %lu\n", name, of, fd, err, (long)t); // errno = err; return fd; } #undef close int prf_close(int fd) { int rc; rc = _close(fd); return rc; } #undef read int prf_read(int fd, void *buf, long cb) { int cbRead; cbRead = _read(fd, buf, cb); return cbRead; } #undef lseek long prf_lseek(int fd, long off, int whence) { long rc; rc = _lseek(fd, off, whence); return rc; } kbuild-3686/src/kmk/README.Amiga0000664000175000017500000000522415053010075016161 0ustar locutuslocutusShort: Port of GNU make with SAS/C (no ixemul.library required) Author: GNU, Amiga port by Aaron "Optimizer" Digulla Uploader: Aaron "Optimizer" Digulla (digulla@fh-konstanz.de) Type: dev/c This is a pure Amiga port of GNU make. It needs no extra libraries or anything. It has the following features (in addition to any features of GNU make): - Runs Amiga-Commands with SystemTags() (Execute) - Can run multi-line statements - Allows to use Device-Names in targets: c:make : make.o is ok. To distinguish between device-names and target : or ::, MAKE looks for spaces. If there are any around :, it's taken as a target delimiter, if there are none, it's taken as the name of a device. Note that "make:make.o" tries to create "make.o" on the device "make:". - Replaces @@ by a newline in any command line: if exists make @@\ delete make.bak quiet @@\ rename make make.bak @@\ endif @@\ $(CC) Link Make.o To make works. Note that the @@ must stand alone (i.e., "make@@\" is illegal). Also be careful that there is a space after the "\" (i.e., at the beginning of the next line). - Can be made resident to save space and time - Amiga specific wildcards can be used in $(wildcard ...) BUGS: - The line dummy.h : src/*.c tries to make dummy.h from "src/*.c" (i.e., no wildcard-expansion takes place). You have to use "$(wildcard src/*.c)" instead. COMPILING FROM SCRATCH ---------------------- To recompile, you need SAS/C 6.51. make itself is not necessary, there is an smakefile. 1. Copy config.ami to config.h 2. If you use make to compile, copy Makefile.ami to Makefile and glob/Makefile.ami to glob/Makefile. Copy make into the current directory. 3. Run smake/make INSTALLATION Copy make somewhere in your search path (e.g., sc:c or sc:bin). If you plan to use recursive makes, install make resident: Resident make Add ------------------------------------------------------------------------------- Copyright (C) 1995-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . kbuild-3686/src/kmk/misc.c0000664000175000017500000010003015053010075015352 0ustar locutuslocutus/* Miscellaneous generic support functions for GNU Make. Copyright (C) 1988-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include "makeint.h" #include "filedef.h" #include "dep.h" #include "debug.h" /* GNU make no longer supports pre-ANSI89 environments. */ #include #ifdef HAVE_FCNTL_H # include #else # include #endif #if defined (CONFIG_WITH_VALUE_LENGTH) || defined (CONFIG_WITH_ALLOC_CACHES) # include #endif #ifdef CONFIG_WITH_PRINT_STATS_SWITCH # ifdef __APPLE__ # include # endif # if defined(__GLIBC__) || defined(HAVE_MALLINFO) # include # endif #endif #if defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_PRINT_TIME_SWITCH) # ifdef WINDOWS32 # include # endif #endif /* All bcopy calls in this file can be replaced by memcpy and save a tick or two. */ #ifdef CONFIG_WITH_OPTIMIZATION_HACKS # undef bcopy # if defined(__GNUC__) && defined(CONFIG_WITH_OPTIMIZATION_HACKS) # define bcopy(src, dst, size) __builtin_memcpy ((dst), (src), (size)) # else # define bcopy(src, dst, size) memcpy ((dst), (src), (size)) # endif #endif /* Compare strings *S1 and *S2. Return negative if the first is less, positive if it is greater, zero if they are equal. */ int alpha_compare (const void *v1, const void *v2) { const char *s1 = *((char **)v1); const char *s2 = *((char **)v2); if (*s1 != *s2) return *s1 - *s2; return strcmp (s1, s2); } /* Discard each backslash-newline combination from LINE. Backslash-backslash-newline combinations become backslash-newlines. This is done by copying the text at LINE into itself. */ #ifndef CONFIG_WITH_VALUE_LENGTH void collapse_continuations (char *line) #else char * collapse_continuations (char *line, unsigned int linelen) #endif { char *in, *out, *p; #ifndef CONFIG_WITH_VALUE_LENGTH in = strchr (line, '\n'); if (in == 0) return; #else assert (strlen (line) == linelen); in = memchr (line, '\n', linelen); if (in == 0) return line + linelen; if (in == line || in[-1] != '\\') { do { unsigned int off_in = in - line; if (off_in == linelen) return in; in = memchr (in + 1, '\n', linelen - off_in - 1); if (in == 0) return line + linelen; } while (in[-1] != '\\'); } #endif out = in; while (out > line && out[-1] == '\\') --out; while (*in != '\0') { /* BS_WRITE gets the number of quoted backslashes at the end just before IN, and BACKSLASH gets nonzero if the next character is quoted. */ unsigned int backslash = 0; unsigned int bs_write = 0; for (p = in - 1; p >= line && *p == '\\'; --p) { if (backslash) ++bs_write; backslash = !backslash; /* It should be impossible to go back this far without exiting, but if we do, we can't get the right answer. */ if (in == out - 1) abort (); } /* Output the appropriate number of backslashes. */ while (bs_write-- > 0) *out++ = '\\'; /* Skip the newline. */ ++in; if (backslash) { /* Backslash/newline handling: In traditional GNU make all trailing whitespace, consecutive backslash/newlines, and any leading non-newline whitespace on the next line is reduced to a single space. In POSIX, each backslash/newline and is replaced by a space. */ while (ISBLANK (*in)) ++in; if (! posix_pedantic) while (out > line && ISBLANK (out[-1])) --out; *out++ = ' '; } else /* If the newline isn't quoted, put it in the output. */ *out++ = '\n'; /* Now copy the following line to the output. Stop when we find backslashes followed by a newline. */ while (*in != '\0') if (*in == '\\') { p = in + 1; while (*p == '\\') ++p; if (*p == '\n') { in = p; break; } while (in < p) *out++ = *in++; } else *out++ = *in++; } *out = '\0'; #ifdef CONFIG_WITH_VALUE_LENGTH assert (strchr (line, '\0') == out); return out; #endif } /* Print N spaces (used in debug for target-depth). */ void print_spaces (unsigned int n) { while (n-- > 0) putchar (' '); } /* Return a string whose contents concatenate the NUM strings provided This string lives in static, re-used memory. */ const char * concat (unsigned int num, ...) { static unsigned int rlen = 0; static char *result = NULL; unsigned int ri = 0; va_list args; va_start (args, num); while (num-- > 0) { const char *s = va_arg (args, const char *); unsigned int l = xstrlen (s); if (l == 0) continue; if (ri + l > rlen) { rlen = ((rlen ? rlen : 60) + l) * 2; result = xrealloc (result, rlen); } memcpy (result + ri, s, l); ri += l; } va_end (args); /* Get some more memory if we don't have enough space for the terminating '\0'. */ if (ri == rlen) { rlen = (rlen ? rlen : 60) * 2; result = xrealloc (result, rlen); } result[ri] = '\0'; return result; } #ifndef HAVE_STRERROR #undef strerror char * strerror (int errnum) { extern int errno, sys_nerr; #ifndef __DECC extern char *sys_errlist[]; #endif static char buf[] = "Unknown error 12345678901234567890"; if (errno < sys_nerr) return sys_errlist[errnum]; sprintf (buf, _("Unknown error %d"), errnum); return buf; } #endif /* Like malloc but get fatal error if memory is exhausted. */ /* Don't bother if we're using dmalloc; it provides these for us. */ #if !defined(HAVE_DMALLOC_H) && !defined(ELECTRIC_HEAP) /* bird */ #undef xmalloc #undef xcalloc #undef xrealloc #undef xstrdup void * xmalloc (unsigned int size) { /* Make sure we don't allocate 0, for pre-ISO implementations. */ void *result = malloc (size ? size : 1); if (result == 0) OUT_OF_MEM(); #ifdef CONFIG_WITH_MAKE_STATS make_stats_allocations++; if (make_expensive_statistics) make_stats_allocated += SIZE_OF_HEAP_BLOCK (result); else make_stats_allocated += size; #endif return result; } void * xcalloc (unsigned int size) { /* Make sure we don't allocate 0, for pre-ISO implementations. */ void *result = calloc (size ? size : 1, 1); if (result == 0) OUT_OF_MEM(); #ifdef CONFIG_WITH_MAKE_STATS make_stats_allocations++; if (make_expensive_statistics) make_stats_allocated += SIZE_OF_HEAP_BLOCK (result); else make_stats_allocated += size; #endif return result; } void * xrealloc (void *ptr, unsigned int size) { void *result; #ifdef CONFIG_WITH_MAKE_STATS if (make_expensive_statistics && ptr != NULL) make_stats_allocated -= SIZE_OF_HEAP_BLOCK (ptr); if (ptr) make_stats_reallocations++; else make_stats_allocations++; #endif /* Some older implementations of realloc() don't conform to ISO. */ if (! size) size = 1; result = ptr ? realloc (ptr, size) : malloc (size); if (result == 0) OUT_OF_MEM(); #ifdef CONFIG_WITH_MAKE_STATS if (make_expensive_statistics) make_stats_allocated += SIZE_OF_HEAP_BLOCK (result); else make_stats_allocated += size; #endif return result; } char * xstrdup (const char *ptr) { char *result; #ifdef HAVE_STRDUP result = strdup (ptr); #else result = malloc (strlen (ptr) + 1); #endif if (result == 0) OUT_OF_MEM(); #ifdef CONFIG_WITH_MAKE_STATS make_stats_allocations++; if (make_expensive_statistics) make_stats_allocated += SIZE_OF_HEAP_BLOCK (result); else make_stats_allocated += strlen (ptr) + 1; #endif #ifdef HAVE_STRDUP return result; #else return strcpy (result, ptr); #endif } #endif /* HAVE_DMALLOC_H */ char * xstrndup (const char *str, unsigned int length) { char *result; #if defined(HAVE_STRNDUP) && !defined(KMK) result = strndup (str, length); if (result == 0) OUT_OF_MEM(); #else result = xmalloc (length + 1); if (length > 0) strncpy (result, str, length); result[length] = '\0'; #endif return result; } #ifndef CONFIG_WITH_OPTIMIZATION_HACKS /* This is really a reimplemntation of memchr, only slower. It's been replaced by a macro in the header file. */ /* Limited INDEX: Search through the string STRING, which ends at LIMIT, for the character C. Returns a pointer to the first occurrence, or nil if none is found. Like INDEX except that the string searched ends where specified instead of at the first null. */ char * lindex (const char *s, const char *limit, int c) { while (s < limit) if (*s++ == c) return (char *)(s - 1); return 0; } #endif /* CONFIG_WITH_OPTIMIZATION_HACKS */ /* Return the address of the first whitespace or null in the string S. */ char * end_of_token (const char *s) { #if 0 /* @todo def KMK */ for (;;) { unsigned char ch0, ch1, ch2, ch3; ch0 = *s; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch0))) return (char *)s; ch1 = s[1]; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch1))) return (char *)s + 1; ch2 = s[2]; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch2))) return (char *)s + 2; ch3 = s[3]; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch3))) return (char *)s + 3; s += 4; } #else END_OF_TOKEN (s); return (char *)s; #endif } /* Return the address of the first nonwhitespace or null in the string S. */ char * next_token (const char *s) { #if 0 /* @todo def KMK */ for (;;) { unsigned char ch0, ch1, ch2, ch3; ch0 = *s; if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch0))) return (char *)s; ch1 = s[1]; if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch1))) return (char *)s + 1; ch2 = s[2]; if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch2))) return (char *)s + 2; ch3 = s[3]; if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch3))) return (char *)s + 3; s += 4; } #else /* !KMK */ NEXT_TOKEN (s); return (char *)s; #endif /* !KMK */ } /* Find the next token in PTR; return the address of it, and store the length of the token into *LENGTHPTR if LENGTHPTR is not nil. Set *PTR to the end of the token, so this function can be called repeatedly in a loop. */ char * find_next_token (const char **ptr, unsigned int *lengthptr) { #ifdef KMK const char *p = *ptr; const char *e; /* skip blanks */ # if 0 /* a moderate version */ for (;; p++) { unsigned char ch = *p; if (!MY_IS_BLANK(ch)) { if (!ch) return NULL; break; } } # else /* (too) big unroll */ for (;; p += 4) { unsigned char ch0, ch1, ch2, ch3; ch0 = *p; if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch0))) { if (!ch0) return NULL; break; } ch1 = p[1]; if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch1))) { if (!ch1) return NULL; p += 1; break; } ch2 = p[2]; if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch2))) { if (!ch2) return NULL; p += 2; break; } ch3 = p[3]; if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch3))) { if (!ch3) return NULL; p += 3; break; } } # endif /* skip ahead until EOS or blanks. */ # if 0 /* a moderate version */ for (e = p + 1; ; e++) { unsigned char ch = *e; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch))) break; } # else /* (too) big unroll */ for (e = p + 1; ; e += 4) { unsigned char ch0, ch1, ch2, ch3; ch0 = *e; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch0))) break; ch1 = e[1]; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch1))) { e += 1; break; } ch2 = e[2]; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch2))) { e += 2; break; } ch3 = e[3]; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch3))) { e += 3; break; } } # endif *ptr = e; if (lengthptr != 0) *lengthptr = e - p; return (char *)p; #else const char *p = next_token (*ptr); if (*p == '\0') return 0; *ptr = end_of_token (p); if (lengthptr != 0) *lengthptr = *ptr - p; return (char *)p; #endif } #ifdef KMK /* Finds the ends of the variable expansion starting at S, stopping at EOS if not found before. */ static char *find_end_of_variable_expansion (const char *s, char const *eos) { char const openparen = s[1]; char const closeparen = openparen == '(' ? ')' : '}'; int levels = 0; assert (s[0] == '$'); assert (s[1] == '(' || s[1] == '{'); s += 2; while (s != eos) { unsigned char ch = *s; if (ch != '\0') { if (ch != closeparen) { if (ch != openparen) { /* likely */ } else levels++; } else if (levels <= 1) break; else levels--; } else break; s++; } return (char *)s; } /* Same as find_next_token with two exception: - The string ends at EOS or '\0'. - We keep track of $() and ${}, allowing functions to be used. */ char * find_next_token_eos (const char **ptr, const char *eos, unsigned int *lengthptr) { const char *p = *ptr; const char *e; /* skip blanks */ while (p != eos) { unsigned char const ch = *p; unsigned int const map = stopchar_map[ch] & (MAP_NUL | MAP_BLANK); if (map & MAP_BLANK) p++; else if (!(map & MAP_NUL)) break; else return NULL; } if (p == eos) return NULL; /* skip ahead until EOS or blanks. */ e = p; while (e != eos) { unsigned char const ch = *e; unsigned int const map = stopchar_map[ch] & (MAP_NUL | MAP_BLANK | MAP_VARIABLE); if (!map) e++; /* likely */ /* Dollar can be escaped by duplication ($$) and when not, they need to be skipped over. */ else if (map & MAP_VARIABLE) { e++; if (&e[1] != eos) { unsigned ch2 = *e; if (ch2 == ch) e++; /* escaped */ else if (ch == '(' || ch == '}') e = find_end_of_variable_expansion (e - 1, eos); } else break; } else break; /* MAP_NUL or MAP_BLANK */ } *ptr = e; if (lengthptr != 0) *lengthptr = e - p; return (char *)p; } /* Same as find_next_token_eos but takes GNU make quoting into account, but without doing any unquoting like find_char_unquote & parse_file_seq. */ char * find_next_file_token (const char **ptr, const char *eos, unsigned int *lengthptr) { const char *p = *ptr; const char *e; /* skip blanks */ while (p != eos) { unsigned char const ch = *p; unsigned int const map = stopchar_map[ch] & (MAP_NUL | MAP_BLANK); if (map & MAP_BLANK) p++; else if (!(map & MAP_NUL)) break; else return NULL; } if (p == eos) return NULL; /* skip ahead until EOS or blanks. */ e = p; while (e != eos) { unsigned char const ch = *e; unsigned int const map = stopchar_map[ch] & (MAP_NUL | MAP_BLANK | MAP_VARIABLE); if (!map) e++; /* likely */ /* Dollar can be escaped by duplication ($$) and when not, they need to be skipped over. */ else if (map & MAP_VARIABLE) { e++; if (&e[1] != eos) { unsigned ch2 = *e; if (ch2 == ch) e++; /* escaped */ else if (ch == '(' || ch == '}') e = find_end_of_variable_expansion (e - 1, eos); } else break; } else if (map & MAP_NUL) break; /* A blank can be escaped using a backslash. */ else if (e[-1] != '\\') break; else { int slashes = 1; while (&e[-slashes] != p && e[-slashes - 1] == '\\') slashes++; if (slashes & 1) e++; else break; } } *ptr = e; if (lengthptr != 0) *lengthptr = e - p; return (char *)p; } #endif /* KMK */ /* Copy a chain of 'struct dep'. For 2nd expansion deps, dup the name. */ struct dep * copy_dep_chain (const struct dep *d) { struct dep *firstnew = 0; struct dep *lastnew = 0; while (d != 0) { #ifndef CONFIG_WITH_ALLOC_CACHES struct dep *c = xmalloc (sizeof (struct dep)); #else struct dep *c = alloccache_alloc(&dep_cache); #endif memcpy (c, d, sizeof (struct dep)); /** @todo KMK: Check if we need this duplication! */ if (c->need_2nd_expansion) c->name = xstrdup (c->name); c->next = 0; if (firstnew == 0) firstnew = lastnew = c; else lastnew = lastnew->next = c; d = d->next; } return firstnew; } /* Free a chain of struct nameseq. For struct dep chains use free_dep_chain. */ void free_ns_chain (struct nameseq *ns) { while (ns != 0) { struct nameseq *t = ns; ns = ns->next; #ifndef CONFIG_WITH_ALLOC_CACHES free_ns (t); #else alloccache_free (&nameseq_cache, t); #endif } } #ifdef CONFIG_WITH_ALLOC_CACHES void free_dep_chain (struct dep *d) { while (d != 0) { struct dep *tofree = d; d = d->next; alloccache_free (&dep_cache, tofree); } } void free_goal_chain (struct goaldep *g) { while (g != 0) { struct goaldep *tofree = g; g = g->next; alloccache_free (&dep_cache, tofree); } } #endif /* CONFIG_WITH_ALLOC_CACHES */ #if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI /* If we don't have strcasecmp() (from POSIX), or anything that can substitute for it, define our own version. */ int strcasecmp (const char *s1, const char *s2) { while (1) { int c1 = (int) *(s1++); int c2 = (int) *(s2++); if (isalpha (c1)) c1 = tolower (c1); if (isalpha (c2)) c2 = tolower (c2); if (c1 != '\0' && c1 == c2) continue; return (c1 - c2); } } #endif #if !HAVE_STRNCASECMP && !HAVE_STRNICMP && !HAVE_STRNCMPI /* If we don't have strncasecmp() (from POSIX), or anything that can substitute for it, define our own version. */ int strncasecmp (const char *s1, const char *s2, int n) { while (n-- > 0) { int c1 = (int) *(s1++); int c2 = (int) *(s2++); if (isalpha (c1)) c1 = tolower (c1); if (isalpha (c2)) c2 = tolower (c2); if (c1 != '\0' && c1 == c2) continue; return (c1 - c2); } return 0; } #endif #ifdef GETLOADAVG_PRIVILEGED #ifdef POSIX /* Hopefully if a system says it's POSIX.1 and has the setuid and setgid functions, they work as POSIX.1 says. Some systems (Alpha OSF/1 1.2, for example) which claim to be POSIX.1 also have the BSD setreuid and setregid functions, but they don't work as in BSD and only the POSIX.1 way works. */ #undef HAVE_SETREUID #undef HAVE_SETREGID #else /* Not POSIX. */ /* Some POSIX.1 systems have the seteuid and setegid functions. In a POSIX-like system, they are the best thing to use. However, some non-POSIX systems have them too but they do not work in the POSIX style and we must use setreuid and setregid instead. */ #undef HAVE_SETEUID #undef HAVE_SETEGID #endif /* POSIX. */ #ifndef HAVE_UNISTD_H extern int getuid (), getgid (), geteuid (), getegid (); extern int setuid (), setgid (); #ifdef HAVE_SETEUID extern int seteuid (); #else #ifdef HAVE_SETREUID extern int setreuid (); #endif /* Have setreuid. */ #endif /* Have seteuid. */ #ifdef HAVE_SETEGID extern int setegid (); #else #ifdef HAVE_SETREGID extern int setregid (); #endif /* Have setregid. */ #endif /* Have setegid. */ #endif /* No . */ /* Keep track of the user and group IDs for user- and make- access. */ static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1; #define access_inited (user_uid != -1) static enum { make, user } current_access; /* Under -d, write a message describing the current IDs. */ static void log_access (const char *flavor) { if (! ISDB (DB_JOBS)) return; /* All the other debugging messages go to stdout, but we write this one to stderr because it might be run in a child fork whose stdout is piped. */ fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"), flavor, (unsigned long) geteuid (), (unsigned long) getuid (), (unsigned long) getegid (), (unsigned long) getgid ()); fflush (stderr); } static void init_access (void) { #ifndef VMS user_uid = getuid (); user_gid = getgid (); make_uid = geteuid (); make_gid = getegid (); /* Do these ever fail? */ if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1) pfatal_with_name ("get{e}[gu]id"); log_access (_("Initialized access")); current_access = make; #endif } #endif /* GETLOADAVG_PRIVILEGED */ /* Give the process appropriate permissions for access to user data (i.e., to stat files, or to spawn a child process). */ void user_access (void) { #ifdef GETLOADAVG_PRIVILEGED if (!access_inited) init_access (); if (current_access == user) return; /* We are in "make access" mode. This means that the effective user and group IDs are those of make (if it was installed setuid or setgid). We now want to set the effective user and group IDs to the real IDs, which are the IDs of the process that exec'd make. */ #ifdef HAVE_SETEUID /* Modern systems have the seteuid/setegid calls which set only the effective IDs, which is ideal. */ if (seteuid (user_uid) < 0) pfatal_with_name ("user_access: seteuid"); #else /* Not HAVE_SETEUID. */ #ifndef HAVE_SETREUID /* System V has only the setuid/setgid calls to set user/group IDs. There is an effective ID, which can be set by setuid/setgid. It can be set (unless you are root) only to either what it already is (returned by geteuid/getegid, now in make_uid/make_gid), the real ID (return by getuid/getgid, now in user_uid/user_gid), or the saved set ID (what the effective ID was before this set-ID executable (make) was exec'd). */ if (setuid (user_uid) < 0) pfatal_with_name ("user_access: setuid"); #else /* HAVE_SETREUID. */ /* In 4BSD, the setreuid/setregid calls set both the real and effective IDs. They may be set to themselves or each other. So you have two alternatives at any one time. If you use setuid/setgid, the effective will be set to the real, leaving only one alternative. Using setreuid/setregid, however, you can toggle between your two alternatives by swapping the values in a single setreuid or setregid call. */ if (setreuid (make_uid, user_uid) < 0) pfatal_with_name ("user_access: setreuid"); #endif /* Not HAVE_SETREUID. */ #endif /* HAVE_SETEUID. */ #ifdef HAVE_SETEGID if (setegid (user_gid) < 0) pfatal_with_name ("user_access: setegid"); #else #ifndef HAVE_SETREGID if (setgid (user_gid) < 0) pfatal_with_name ("user_access: setgid"); #else if (setregid (make_gid, user_gid) < 0) pfatal_with_name ("user_access: setregid"); #endif #endif current_access = user; log_access (_("User access")); #endif /* GETLOADAVG_PRIVILEGED */ } /* Give the process appropriate permissions for access to make data (i.e., the load average). */ void make_access (void) { #ifdef GETLOADAVG_PRIVILEGED if (!access_inited) init_access (); if (current_access == make) return; /* See comments in user_access, above. */ #ifdef HAVE_SETEUID if (seteuid (make_uid) < 0) pfatal_with_name ("make_access: seteuid"); #else #ifndef HAVE_SETREUID if (setuid (make_uid) < 0) pfatal_with_name ("make_access: setuid"); #else if (setreuid (user_uid, make_uid) < 0) pfatal_with_name ("make_access: setreuid"); #endif #endif #ifdef HAVE_SETEGID if (setegid (make_gid) < 0) pfatal_with_name ("make_access: setegid"); #else #ifndef HAVE_SETREGID if (setgid (make_gid) < 0) pfatal_with_name ("make_access: setgid"); #else if (setregid (user_gid, make_gid) < 0) pfatal_with_name ("make_access: setregid"); #endif #endif current_access = make; log_access (_("Make access")); #endif /* GETLOADAVG_PRIVILEGED */ } /* Give the process appropriate permissions for a child process. This is like user_access, but you can't get back to make_access. */ void child_access (void) { #ifdef GETLOADAVG_PRIVILEGED if (!access_inited) abort (); /* Set both the real and effective UID and GID to the user's. They cannot be changed back to make's. */ #ifndef HAVE_SETREUID if (setuid (user_uid) < 0) pfatal_with_name ("child_access: setuid"); #else if (setreuid (user_uid, user_uid) < 0) pfatal_with_name ("child_access: setreuid"); #endif #ifndef HAVE_SETREGID if (setgid (user_gid) < 0) pfatal_with_name ("child_access: setgid"); #else if (setregid (user_gid, user_gid) < 0) pfatal_with_name ("child_access: setregid"); #endif log_access (_("Child access")); #endif /* GETLOADAVG_PRIVILEGED */ } #ifdef NEED_GET_PATH_MAX unsigned int get_path_max (void) { static unsigned int value; if (value == 0) { long int x = pathconf ("/", _PC_PATH_MAX); if (x > 0) value = x; else return MAXPATHLEN; } return value; } #endif #ifdef CONFIG_WITH_PRINT_STATS_SWITCH /* Print heap statistics if supported by the platform. */ void print_heap_stats (void) { /* Darwin / Mac OS X */ # ifdef __APPLE__ malloc_statistics_t s; malloc_zone_statistics (NULL, &s); printf (_("\n# CRT Heap: %u bytes in use, in %u blocks, avg %u bytes/block\n"), (unsigned)s.size_in_use, (unsigned)s.blocks_in_use, s.blocks_in_use ? (unsigned)(s.size_in_use / s.blocks_in_use) : 0); printf (_("# %u bytes max in use (high water mark)\n"), (unsigned)s.max_size_in_use); printf (_("# %u bytes reserved, %u bytes free (estimate)\n"), (unsigned)s.size_allocated, (unsigned)(s.size_allocated - s.size_in_use)); # endif /* __APPLE__ */ /* MSC / Windows */ # ifdef _MSC_VER unsigned int blocks_used = 0; unsigned int bytes_used = 0; unsigned int blocks_avail = 0; unsigned int bytes_avail = 0; _HEAPINFO hinfo; memset (&hinfo, '\0', sizeof (hinfo)); while (_heapwalk(&hinfo) == _HEAPOK) { if (hinfo._useflag == _USEDENTRY) { blocks_used++; bytes_used += hinfo._size; } else { blocks_avail++; bytes_avail += hinfo._size; } } printf (_("\n# CRT Heap: %u bytes in use, in %u blocks, avg %u bytes/block\n"), bytes_used, blocks_used, blocks_used ? bytes_used / blocks_used : 0); printf (_("# %u bytes avail, in %u blocks, avg %u bytes/block\n"), bytes_avail, blocks_avail, blocks_avail ? bytes_avail / blocks_avail : 0); # endif /* _MSC_VER */ /* Darwin Libc sources indicates that something like this may be found in GLIBC, however, it's not in any current one... */ # if 0 /* ??? */ struct mstats m; m = mstats(); printf (_("\n# CRT Heap: %zu blocks / %zu bytes in use, %zu blocks / %zu bytes free\n"), m.chunks_used, m.bytes_used, m.chunks_free, m.bytes_free); printf (_("# %zu bytes reserved\n"), m.bytes_total); # endif /* ??? */ /* XVID2/XPG mallinfo (displayed per GLIBC documentation). */ # if defined(__GLIBC__) || defined(HAVE_MALLINFO) struct mallinfo m; m = mallinfo(); printf (_("\n# CRT Heap: %d bytes in use, %d bytes free\n"), m.uordblks, m.fordblks); printf (_("# # free chunks=%d, # fastbin blocks=%d\n"), m.ordblks, m.smblks); printf (_("# # mapped regions=%d, space in mapped regions=%d\n"), m.hblks, m.hblkhd); printf (_("# non-mapped space allocated from system=%d\n"), m.arena); printf (_("# maximum total allocated space=%d\n"), m.usmblks); printf (_("# top-most releasable space=%d\n"), m.keepcost); # endif /* __GLIBC__ || HAVE_MALLINFO */ # ifdef CONFIG_WITH_MAKE_STATS printf(_("# %lu malloc calls, %lu realloc calls\n"), make_stats_allocations, make_stats_reallocations); printf(_("# %lu MBs alloc sum, not counting freed, add pinch of salt\n"), /* XXX: better wording */ make_stats_allocated / (1024*1024)); # endif /* XXX: windows */ } #endif /* CONFIG_WITH_PRINT_STATS_SWITCH */ #if defined(CONFIG_WITH_PRINT_TIME_SWITCH) || defined(CONFIG_WITH_KMK_BUILTIN_STATS) /* Get a nanosecond timestamp, from a monotonic time source if possible. Returns -1 after calling error() on failure. */ big_int nano_timestamp (void) { big_int ts; #if defined (WINDOWS32) static int s_state = -1; static LARGE_INTEGER s_freq; if (s_state == -1) s_state = QueryPerformanceFrequency (&s_freq); if (s_state) { LARGE_INTEGER pc; if (!QueryPerformanceCounter (&pc)) { s_state = 0; return nano_timestamp (); } ts = (big_int)((long double)pc.QuadPart / (long double)s_freq.QuadPart * 1000000000); } else { /* fall back to low resolution system time. */ LARGE_INTEGER bigint; FILETIME ft = {0,0}; GetSystemTimeAsFileTime (&ft); bigint.u.LowPart = ft.dwLowDateTime; bigint.u.HighPart = ft.dwLowDateTime; ts = bigint.QuadPart * 100; } #elif HAVE_GETTIMEOFDAY /* FIXME: Linux and others have the realtime clock_* api, detect and use it. */ struct timeval tv; if (!gettimeofday (&tv, NULL)) ts = (big_int)tv.tv_sec * 1000000000 + tv.tv_usec * 1000; else { O (error, NILF, _("gettimeofday failed")); ts = -1; } #else # error "PORTME" #endif return ts; } /* Formats the elapsed time (nano seconds) in the manner easiest to read, with millisecond percision for larger numbers. */ int format_elapsed_nano (char *buf, size_t size, big_int ts) { unsigned sz; if (ts < 1000) sz = sprintf (buf, "%uns", (unsigned)ts); else if (ts < 100000) sz = sprintf (buf, "%u.%03uus", (unsigned)(ts / 1000), (unsigned)(ts % 1000)); else { ts /= 1000; if (ts < 1000) sz = sprintf (buf, "%uus", (unsigned)ts); else if (ts < 100000) sz = sprintf (buf, "%u.%03ums", (unsigned)(ts / 1000), (unsigned)(ts % 1000)); else { ts /= 1000; if (ts < BIG_INT_C(60000)) sz = sprintf (buf, "%u.%03us", (unsigned)(ts / 1000), (unsigned)(ts % 1000)); else sz = sprintf (buf, "%um%u.%03us", (unsigned)( ts / BIG_INT_C(60000)), (unsigned)((ts % BIG_INT_C(60000)) / 1000), (unsigned)((ts % BIG_INT_C(60000)) % 1000)); } } if (sz >= size) ONN (fatal, NILF, _("format_elapsed_nano buffer overflow: %u written, %lu buffer"), sz, (unsigned long)size); return sz; } #endif /* CONFIG_WITH_PRINT_TIME_SWITCH || defined(CONFIG_WITH_KMK_BUILTIN_STATS) */ kbuild-3686/src/kmk/kdepdb.c0000664000175000017500000007570115053010075015670 0ustar locutuslocutus/* $Id: incdep.c 2283 2009-02-24 04:54:00Z bird $ */ /** @file * kdepdb - Dependency database. */ /* * Copyright (c) 2009-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "makeint.h" #include "../lib/k/kDefs.h" #include "../lib/k/kTypes.h" #include #include #include "dep.h" #include "filedef.h" #include "job.h" #include "commands.h" #include "variable.h" #include "rule.h" #include "debug.h" #include "strcache2.h" #ifdef HAVE_FCNTL_H # include #else # include #endif #if K_OS == K_WINDOWS # include #else # include # include #endif /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ /** @def KDEPDB_ASSERT_SIZE * Check the size of an on-disk type. * * @param Type The type which size it being checked. * @param Size The size it should have. */ #ifdef __GNUC__ # define KDEPDB_ASSERT_SIZE(Type, Size) \ extern int kDepDbAssertSize[1] __attribute__((unused)), \ kDepDbAssertSize[sizeof(Type) == (Size)] __attribute__((unused)) #else # define KDEPDB_ASSERT_SIZE(Type, Size) \ typedef int kDepDbAssertSize[sizeof(Type) == (Size)] #endif KDEPDB_ASSERT_SIZE(KU8, 1); KDEPDB_ASSERT_SIZE(KU16, 2); KDEPDB_ASSERT_SIZE(KU32, 4); KDEPDB_ASSERT_SIZE(KU64, 8); /******************************************************************************* * Structures and Typedefs * *******************************************************************************/ /** * File header. * * @remarks All on-disk formats are in little-endian format. */ typedef struct KDEPDBHDR { /** The file magic. */ KU8 szMagic[8]; /** The major file format version. */ KU8 uVerMajor; /** The minor file format version. */ KU8 uVerMinor; /** Reserved \#2. */ KU16 uReserved2; /** Reserved \#1. */ KU32 uReserved1; /** The internal name of this file. */ KU8 szName[16]; } KDEPDBHDR; KDEPDB_ASSERT_SIZE(KDEPDBHDR, 32); /** The file header magic value. */ #define KDEPDBHDR_MAGIC "kDepDb\0" /** The current major file format version number. */ #define KDEPDBHDR_VERSION_MAJOR 0 /** The current minor file format version number. * Numbers above 240 indicate unsupported development variants. */ #define KDEPDBHDR_VERSION_MINOR 240 /** * Hash table file. * * The hash table is recreated in a new file when we have to grow it. */ typedef struct KDEPDBHASH { /** The file header. */ KDEPDBHDR Hdr; /** The number of hash table entries. */ KU32 cEntries; /** The number of hash table entries with content. */ KU32 cUsedEntries; /** The number of collisions on insert. */ KU32 cCollisions; /** Reserved member \#5. */ KU32 uReserved5; /** Reserved member \#4. */ KU32 uReserved4; /** Reserved member \#3. */ KU32 uReserved3; /** Reserved member \#2. */ KU32 uReserved2; /** Reserved member \#1. */ KU32 uReserved1; /** The hash table. */ KU32 auEntries[32]; } KDEPDBHASH; KDEPDB_ASSERT_SIZE(KDEPDBHASH, 32+32+4*32); /** The item value indicating that it is unused. */ #define KDEPDBHASH_UNUSED KU32_C(0xffffffff) /** The item indicating that it hash been deleted. */ #define KDEPDBHASH_DELETED KU32_C(0xfffffffe) /** The first special item value. */ #define KDEPDBHASH_END KU32_C(0xfffffff0) /** * A string table string entry. * * This should be a multiple of 32 bytes. */ typedef struct KDEPDBSTRING { /** The hash number for the string. */ KU32 uHash; /** The string length, excluding the zero terminator. */ KU32 cchString; /** The string. */ KU8 szString[24]; } KDEPDBSTRING; KDEPDB_ASSERT_SIZE(KDEPDBSTRING, 32); /** * String table file. * * The file is insertion only and will grow forever. */ typedef struct KDEPDBSTRTAB { /** The file header. */ KDEPDBHDR Hdr; /** The end of the valid string table indexes. */ KU32 iStringEnd; /** Reserved member \#7. */ KU32 uReserved7; /** Reserved member \#6. */ KU32 uReserved6; /** Reserved member \#5. */ KU32 uReserved5; /** Reserved member \#4. */ KU32 uReserved4; /** Reserved member \#3. */ KU32 uReserved3; /** Reserved member \#2. */ KU32 uReserved2; /** Reserved member \#1. */ KU32 uReserved1; /** The string table. */ KDEPDBSTRING aStrings[1]; } KDEPDBSTRTAB; KDEPDB_ASSERT_SIZE(KDEPDBSTRTAB, 32+32+32); /** The end of the valid string table indexes (exclusive). */ #define KDEPDBG_STRTAB_IDX_END KU32_C(0x80000000) /** The string was not found. */ #define KDEPDBG_STRTAB_IDX_NOT_FOUND KU32_C(0xfffffffd) /** Error during string table operation. */ #define KDEPDBG_STRTAB_IDX_ERROR KU32_C(0xfffffffe) /** Generic invalid string table index. */ #define KDEPDBG_STRTAB_IDX_INVALID KU32_C(0xffffffff) /** * Directory entry. */ typedef struct KDEPDBDIRENTRY { /** The string table index of the entry name. * Unused entries are set to KDEPDBG_STRTAB_IDX_INVALID. */ KU32 iName; /** The actual data stream size. * Unused entries are set to KU32_MAX. */ KU32 cbData; /** The number of blocks allocated for this stream. * Unused entries are set to KU32_MAX. */ KU32 cBlocks; /** The start block number. * The stream is a contiguous sequence of blocks. This optimizes and * simplifies reading the stream at the expense of operations extending it. * * In unused entries, this serves as the free chain pointer with KU32_MAX as * nil value. */ KU32 iStartBlock; } KDEPDBDIRENTRY; KDEPDB_ASSERT_SIZE(KDEPDBDIRENTRY, 16); /** * Directory file. */ typedef struct KDEPDBDIR { /** The file header. */ KDEPDBHDR Hdr; /** The number of entries. */ KU32 cEntries; /** The head of the free chain. (Index into aEntries.) */ KU32 iFreeHead; /** Reserved member \#6. */ KU32 uReserved6; /** Reserved member \#5. */ KU32 uReserved5; /** Reserved member \#4. */ KU32 uReserved4; /** Reserved member \#3. */ KU32 uReserved3; /** Reserved member \#2. */ KU32 uReserved2; /** Reserved member \#1. */ KU32 uReserved1; /** Directory entries. */ KDEPDBDIRENTRY aEntries[2]; } KDEPDBDIR; KDEPDB_ASSERT_SIZE(KDEPDBDIR, 32+32+32); /** * A block allocation bitmap. * * This can track 2^(12+8) = 2^20 = 1M blocks. */ typedef struct KDEPDBDATABITMAP { /** Bitmap where each bit is a block. * 0 indicates unused blocks and 1 indicates used ones. */ KU8 bm[4096]; } KDEPDBDATABITMAP; KDEPDB_ASSERT_SIZE(KDEPDBDATABITMAP, 4096); /** * Data file. * * The block numbering starts with this structure as block 0. */ typedef struct KDEPDBDATA { /** The file header. */ KDEPDBHDR Hdr; /** The size of a block. */ KU32 cbBlock; /** Reserved member \#7. */ KU32 uReserved7; /** Reserved member \#6. */ KU32 uReserved6; /** Reserved member \#5. */ KU32 uReserved5; /** Reserved member \#4. */ KU32 uReserved4; /** Reserved member \#3. */ KU32 uReserved3; /** Reserved member \#2. */ KU32 uReserved2; /** Reserved member \#1. */ KU32 uReserved1; /** Block numbers for the allocation bitmaps. */ KU32 aiBitmaps[4096]; } KDEPDBDATA; /** The end of the valid block indexes (exclusive). */ #define KDEPDB_BLOCK_IDX_END KU32_C(0xfffffff0) /** The index of an unallocated bitmap block. */ #define KDEPDB_BLOCK_IDX_UNALLOCATED KU32_C(0xffffffff) /** * Stream storing dependencies. * * The stream name gives the output file name, so all that we need is the list * of files it depends on. These are serialized as a list of string table * indexes. */ typedef struct KDEPDBDEPSTREAM { /** String table indexes for the dependencies. */ KU32 aiDeps[1]; } KDEPDBDEPSTREAM; /** * A file handle structure. */ typedef struct KDEPDBFH { #if K_OS == K_OS_WINDOWS /** The file handle. */ HANDLE hFile; /** The mapping object handle. */ HANDLE hMapObj; #else /** The file handle. */ int fd; #endif /** The current file size. */ KU32 cb; } KDEPDBFH; /** * Internal control structure for a string table. */ typedef struct KDEPDBINTSTRTAB { /** The hash file. */ KDEPDBHASH *pHash; /** The handle of the hash file. */ KDEPDBFH hHash; /** The string table file. */ KDEPDBSTRTAB *pStrTab; /** The handle of the string table file. */ KDEPDBFH hStrTab; /** The end of the allocated string table indexes (i.e. when to grow the * file). */ KU32 iStringAlloced; } KDEPDBINTSTRTAB; /** * Internal control structure for a data set. * * This governs the directory file, the directory hash file and the data file. */ typedef struct KDEPDBINTDATASET { /** The hash file. */ KDEPDBHASH pHash; /** The size of the hash file. */ KU32 cbHash; /** The size of the directory file. */ KU32 cbDir; /** The mapping of the directory file. */ KDEPDBHASH pDir; /** The data file. */ KDEPDBDATA pData; /** The size of the data file. */ KU32 cbData; /** The handle of the hash file. */ KDEPDBFH hHash; /** The handle of the directory file. */ KDEPDBFH hDir; /** The handle of the data file. */ KDEPDBFH hData; } KDEPDBINTDATASET; /** * The database instance. * * To simplifiy things the database uses 8 files for storing the different kinds * of data. This greatly reduces the complexity compared to a single file * solution. */ typedef struct KDEPDB { /** The string table. */ KDEPDBINTSTRTAB StrTab; /** The variable data set. */ KDEPDBINTDATASET DepSet; /** The command data set. */ KDEPDBINTDATASET CmdSet; } KDEPDB; /******************************************************************************* * Internal Functions * *******************************************************************************/ static void *kDepDbAlloc(KSIZE cb); static void kDepDbFree(void *pv); static void kDepDbFHInit(KDEPDBFH *pFH); static int kDepDbFHUpdateSize(KDEPDBFH *pFH); static int kDepDbFHOpen(KDEPDBFH *pFH, const char *pszFilename, KBOOL fCreate, KBOOL *pfNew); static int kDepDbFHClose(KDEPDBFH *pFH); static int kDepDbFHWriteAt(KDEPDBFH *pFH, KU32 off, void const *pvBuf, KSIZE cbBuf); static int kDepDbFHMap(KDEPDBFH *pFH, void **ppvMap); static int kDepDbFHUnmap(KDEPDBFH *pFH, void **ppvMap); static int kDepDbFHGrow(KDEPDBFH *pFH, KSIZE cbNew, void **ppvMap); static KU32 kDepDbHashString(const char *pszString, size_t cchString); /** xmalloc wrapper. */ static void *kDepDbAlloc(KSIZE cb) { return xmalloc(cb); } /** free wrapper. */ static void kDepDbFree(void *pv) { if (pv) free(pv); } /** * Initializes the file handle structure so closing it without first opening it * will work smoothly. * * @param pFH The file handle structure. */ static void kDepDbFHInit(KDEPDBFH *pFH) { #if K_OS == K_OS_WINDOWS pFH->hFile = INVALID_HANDLE_VALUE; pFH->hMapObj = INVALID_HANDLE_VALUE; #else pFH->fd = -1; #endif pFH->cb = 0; } /** * Updates the file size. * * @returns 0 on success. Some non-zero native error code on failure. * @param pFH The file handle structure. */ static int kDepDbFHUpdateSize(KDEPDBFH *pFH) { #if K_OS == K_OS_WINDOWS DWORD rc; DWORD dwHigh; DWORD dwLow; SetLastError(0); dwLow = GetFileSize(File, &High); rc = GetLastError(); if (rc) { pFH->cb = 0; return (int)rc; } if (High) pFH->cb = KU32_MAX; else pFH->cb = dwLow; #else off_t cb; cb = lseek(pFH->fd, 0, SEEK_END); if (cb == -1) { pFH->cb = 0; return errno; } pFH->cb = cb; if ((off_t)pFH->cb != cb) pFH->cb = KU32_MAX; #endif return 0; } /** * Opens an existing file or creates a new one. * * @returns 0 on success. Some non-zero native error code on failure. * * @param pFH The file handle structure. * @param pszFilename The name of the file. * @param fCreate Whether we should create the file or not. * @param pfCreated Where to return whether we created it or not. */ static int kDepDbFHOpen(KDEPDBFH *pFH, const char *pszFilename, KBOOL fCreate, KBOOL *pfCreated) { int rc; #if K_OS == K_OS_WINDOWS SECURITY_ATTRIBUTES SecAttr; SecAttr.bInheritHandle = FALSE; SecAttr.lpSecurityDescriptor = NULL; SecAttr.nLength = 0; pFH->cb = 0; SetLastError(0); pFH->hFile = CreateFile(pszFilename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, &SecAttr, fCreate ? OPEN_ALWAYS : OPEN_EXISTING, 0, NULL); if (pFH->hFile == INVALID_HANDLE_VALUE) return GetLastError(); *pfCreated = GetLastError() == 0; #else int fFlags = O_RDWR; # ifdef O_BINARY fFlags |= O_BINARY; # endif pFH->cb = 0; pFH->fd = open(pszFilename, fFlags, 0); if (pFH->fd >= 0) *pfCreated = K_FALSE; else if (!fCreate) return errno; else { pFH->fd = open(pszFilename, fFlags | O_EXCL | O_CREAT, 0666); if (pFH->fd < 0) return errno; *pfCreated = K_TRUE; } fcntl(pFH->fd, F_SETFD, FD_CLOEXEC); #endif /* update the size */ rc = kDepDbFHUpdateSize(pFH); if (rc) kDepDbFHClose(pFH); return rc; } /** * Closes an open file. * * @returns 0 on success. Some non-zero native error code on failure. * * @param pFH The file handle structure. */ static int kDepDbFHClose(KDEPDBFH *pFH) { #if K_OS == K_OS_WINDOWS if (pFH->hFile != INVALID_HANDLE_VALUE) { if (!CloseHandle(pFH->hFile)) return GetLastError(); pFH->hFile = INVALID_HANDLE_VALUE; } #else if (pFH->fd >= 0) { if (close(pFH->fd) != 0) return errno; pFH->fd = -1; } #endif pFH->cb = 0; return 0; } /** * Writes to a file. * * @returns 0 on success. Some non-zero native error code on failure. * * @param pFH The file handle structure. * @param off The offset into the file to start writing at. * @param pvBuf What to write. * @param cbBuf How much to write. */ static int kDepDbFHWriteAt(KDEPDBFH *pFH, KU32 off, void const *pvBuf, KSIZE cbBuf) { #if K_OS == K_OS_WINDOWS ULONG cbWritten; if (SetFilePointer(pFH->hFile, off, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER) return GetLastError(); if (!WriteFile(pFH->hFile, pvBuf, cbBuf, &cbWritten, NULL)) return GetLastError(); if (cbWritten != cbBuf) return -1; #else ssize_t cbWritten; if (lseek(pFH->fd, off, SEEK_SET) == -1) return errno; errno = 0; cbWritten = write(pFH->fd, pvBuf, cbBuf); if ((size_t)cbWritten != cbBuf) return errno ? errno : EIO; #endif return kDepDbFHUpdateSize(pFH); } /** * Creates a memory mapping of the file. * * @returns 0 on success. Some non-zero native error code on failure. * * @param pFH The file handle structure. * @param ppvMap Where to return the map address. */ static int kDepDbFHMap(KDEPDBFH *pFH, void **ppvMap) { #if K_OS == K_OS_WINDOWS *ppvMap = NULL; return -1; #else *ppvMap = mmap(NULL, pFH->cb, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, pFH->fd, 0); if (*ppvMap == (void *)-1) { *ppvMap = NULL; return errno; } #endif return 0; } /** * Flushes and destroys a memory of the file. * * @returns 0 on success. Some non-zero native error code on failure. * * @param pFH The file handle structure. * @param ppvMap The pointer to the mapping pointer. This will be set to * NULL on success. */ static int kDepDbFHUnmap(KDEPDBFH *pFH, void **ppvMap) { #if K_OS == K_OS_WINDOWS return -1; #else if (msync(*ppvMap, pFH->cb, MS_SYNC) == -1) return errno; if (munmap(*ppvMap, pFH->cb) == -1) return errno; *ppvMap = NULL; #endif return 0; } /** * Grows the memory mapping of the file. * * The content of the new space is undefined. * * @returns 0 on success. Some non-zero native error code on failure. * * @param pFH The file handle structure. * @param cbNew The new mapping size. * @param ppvMap The pointer to the mapping pointer. This may change and * may be set to NULL on failure. */ static int kDepDbFHGrow(KDEPDBFH *pFH, KSIZE cbNew, void **ppvMap) { #if K_OS == K_OS_WINDOWS return -1; #else if ((KU32)cbNew != cbNew) return ERANGE; if (cbNew <= pFH->cb) return 0; if (munmap(*ppvMap, pFH->cb) == -1) return errno; *ppvMap = NULL; pFH->cb = cbNew; return kDepDbFHMap(pFH, ppvMap); #endif } /** Macro for reading an potentially unaligned 16-bit word from a string. */ # if K_ARCH == K_ARCH_AMD64 \ || K_ARCH == K_ARCH_X86_32 \ || K_ARCH == K_ARCH_X86_16 # define kDepDbHashString_get_unaligned_16bits(ptr) ( *((const KU16 *)(ptr)) ) # elif K_ENDIAN == K_ENDIAN_LITTLE # define kDepDbHashString_get_unaligned_16bits(ptr) ( (((const KU8 *)(ptr))[0]) \ | (((const KU8 *)(ptr))[1] << 8) ) # else # define kDepDbHashString_get_unaligned_16bits(ptr) ( (((const KU8 *)(ptr))[0] << 8) \ | (((const KU8 *)(ptr))[1]) ) # endif /** * Hash a string. * * @returns Hash value. * * @param pszString The string to hash. * @param cchString How much to hash. */ static KU32 kDepDbHashString(const char *pszString, size_t cchString) { /* * Paul Hsieh hash SuperFast function: * http://www.azillionmonkeys.com/qed/hash.html */ /** @todo A path for well aligned data should be added to speed up execution on * alignment sensitive systems. */ unsigned int uRem; KU32 uHash; KU32 uTmp; assert(sizeof(KU8) == sizeof(char)); /* main loop, walking on 2 x KU16 */ uHash = cchString; uRem = cchString & 3; cchString >>= 2; while (cchString > 0) { uHash += kDepDbHashString_get_unaligned_16bits(pszString); uTmp = (kDepDbHashString_get_unaligned_16bits(pszString + 2) << 11) ^ uHash; uHash = (uHash << 16) ^ uTmp; pszString += 2 * sizeof(KU16); uHash += uHash >> 11; cchString--; } /* the remainder */ switch (uRem) { case 3: uHash += kDepDbHashString_get_unaligned_16bits(pszString); uHash ^= uHash << 16; uHash ^= pszString[sizeof(KU16)] << 18; uHash += uHash >> 11; break; case 2: uHash += kDepDbHashString_get_unaligned_16bits(pszString); uHash ^= uHash << 11; uHash += uHash >> 17; break; case 1: uHash += *pszString; uHash ^= uHash << 10; uHash += uHash >> 1; break; } /* force "avalanching" of final 127 bits. */ uHash ^= uHash << 3; uHash += uHash >> 5; uHash ^= uHash << 4; uHash += uHash >> 17; uHash ^= uHash << 25; uHash += uHash >> 6; return uHash; } /*** * Looks up a string in the string table. * * @returns The string table index. * @retval KDEPDBG_STRTAB_IDX_NOT_FOUND is not found. * @retval KDEPDBG_STRTAB_IDX_ERROR on internal inconsistency. * * @param pStrTab The string table. * @param pszString The string. * @param cchStringIn The string length. * @param uHash The hash of the string. */ static KU32 kDepDbStrTabLookupHashed(KDEPDBINTSTRTAB const *pStrTab, const char *pszString, size_t cchStringIn, KU32 uHash) { KU32 const cchString = (KU32)cchStringIn; KDEPDBHASH const *pHash = pStrTab->pHash; KDEPDBSTRING const *paStrings = &pStrTab->pStrTab->aStrings[0]; KU32 const iStringEnd = K_LE2H_U32(pStrTab->pStrTab->iStringEnd); KU32 iHash; /* sanity */ if (cchString != cchStringIn) return KDEPDBG_STRTAB_IDX_NOT_FOUND; /* * Hash lookup of the string. */ iHash = uHash % pHash->cEntries; for (;;) { KU32 iString = K_LE2H_U32(pHash->auEntries[iHash]); if (iString < iStringEnd) { KDEPDBSTRING const *pString = &paStrings[iString]; if ( K_LE2H_U32(pString->uHash) == uHash && K_LE2H_U32(pString->cchString) == cchString && !memcmp(pString->szString, pszString, cchString)) return iString; } else if (iString == KDEPDBHASH_UNUSED) return KDEPDBG_STRTAB_IDX_NOT_FOUND; else if (iString != KDEPDBHASH_DELETED) return KDEPDBG_STRTAB_IDX_ERROR; /* advance */ iHash = (iHash + 1) % pHash->cEntries; } } /** * Doubles the hash table size and rehashes it. * * @returns 0 on success, -1 on failure. * @param pStrTab The string table. * @todo Rebuild from string table, we'll be accessing it anyways. */ static int kDepDbStrTabReHash(KDEPDBINTSTRTAB *pStrTab) { KDEPDBSTRING const *paStrings = &pStrTab->pStrTab->aStrings[0]; KU32 const iStringEnd = K_LE2H_U32(pStrTab->pStrTab->iStringEnd); KDEPDBHASH *pHash = pStrTab->pHash; KDEPDBHASH HashHdr = *pHash; KU32 *pauNew; KU32 cEntriesNew; KU32 i; /* * Calc the size of the new hash table. */ if (pHash->cEntries >= KU32_C(0x80000000)) return -1; cEntriesNew = 1024; while (cEntriesNew <= pHash->cEntries) cEntriesNew <<= 1; /* * Allocate and initialize an empty hash table in memory. */ pauNew = kDepDbAlloc(cEntriesNew * sizeof(KU32)); if (!pauNew) return -1; i = cEntriesNew; while (i-- > 0) pauNew[i] = KDEPDBHASH_UNUSED; /* * Popuplate the new table. */ HashHdr.cEntries = K_LE2H_U32(cEntriesNew); HashHdr.cCollisions = 0; HashHdr.cUsedEntries = 0; i = pHash->cEntries; while (i-- > 0) { KU32 iString = K_LE2H_U32(pHash->auEntries[i]); if (iString < iStringEnd) { KU32 iHash = (paStrings[iString].uHash % cEntriesNew); if (pauNew[iHash] != K_H2LE_U32(KDEPDBHASH_UNUSED)) { do { iHash = (iHash + 1) % cEntriesNew; HashHdr.cCollisions++; } while (pauNew[iHash] != K_H2LE_U32(KDEPDBHASH_UNUSED)); } pauNew[iHash] = iString; HashHdr.cUsedEntries++; } else if ( iString != KDEPDBHASH_UNUSED && iString != KDEPDBHASH_DELETED) { kDepDbFree(pauNew); return -1; } } HashHdr.cCollisions = K_H2LE_U32(HashHdr.cCollisions); HashHdr.cUsedEntries = K_H2LE_U32(HashHdr.cUsedEntries); /* * Unmap the hash, write the new hash table and map it again. */ if (!kDepDbFHUnmap(&pStrTab->hHash, (void **)&pStrTab->pHash)) { if ( !kDepDbFHWriteAt(&pStrTab->hHash, 0, &HashHdr, K_OFFSETOF(KDEPDBHASH, auEntries)) && !kDepDbFHWriteAt(&pStrTab->hHash, K_OFFSETOF(KDEPDBHASH, auEntries), pauNew, sizeof(pauNew[0]) * cEntriesNew)) { kDepDbFree(pauNew); pauNew = NULL; if (!kDepDbFHMap(&pStrTab->hHash, (void **)&pStrTab->pHash)) return 0; } else kDepDbFHWriteAt(&pStrTab->hHash, 0, "\0\0\0\0", 4); /* file is screwed, trash the magic. */ } kDepDbFree(pauNew); return -1; } /** * Add a string to the string table. * * If already in the table, the index of the existing entry is returned. * * @returns String index on success, * @retval KDEPDBG_STRTAB_IDX_ERROR on I/O and inconsistency errors. * * @param pStrTab The string table. * @param pszString The string to add. * @param cchStringIn The length of the string. * @param uHash The hash of the string. */ static KU32 kDepDbStrTabAddHashed(KDEPDBINTSTRTAB *pStrTab, const char *pszString, size_t cchStringIn, KU32 uHash) { KU32 const cchString = (KU32)cchStringIn; KDEPDBHASH *pHash = pStrTab->pHash; KDEPDBSTRING *paStrings = &pStrTab->pStrTab->aStrings[0]; KU32 const iStringEnd = K_LE2H_U32(pStrTab->pStrTab->iStringEnd); KU32 iInsertAt = KDEPDBHASH_UNUSED; KU32 cCollisions = 0; KU32 iHash; KU32 iString; KU32 cEntries; KDEPDBSTRING *pNewString; /* sanity */ if (cchString != cchStringIn) return KDEPDBG_STRTAB_IDX_NOT_FOUND; /* * Hash lookup of the string, finding either an existing copy or where to * insert the new string at in the hash table. */ iHash = uHash % pHash->cEntries; for (;;) { iString = K_LE2H_U32(pHash->auEntries[iHash]); if (iString < iStringEnd) { KDEPDBSTRING const *pString = &paStrings[iString]; if ( K_LE2H_U32(pString->uHash) == uHash && K_LE2H_U32(pString->cchString) == cchString && !memcmp(pString->szString, pszString, cchString)) return iString; } else { if (iInsertAt == KDEPDBHASH_UNUSED) iInsertAt = iHash; if (iString == KDEPDBHASH_UNUSED) break; if (iString != KDEPDBHASH_DELETED) return KDEPDBG_STRTAB_IDX_ERROR; } /* advance */ cCollisions++; iHash = (iHash + 1) % pHash->cEntries; } /* * Add string to the string table. * The string table file is grown in 256KB increments and ensuring at least 64KB unused new space. */ cEntries = cchString + 1 <= sizeof(paStrings[0].szString) ? 1 : (cchString + 1 - sizeof(paStrings[0].szString) + sizeof(KDEPDBSTRING) - 1) / sizeof(KDEPDBSTRING); if (iStringEnd + cEntries > pStrTab->iStringAlloced) { KSIZE cbNewSize = K_ALIGN_Z((iStringEnd + cEntries) * sizeof(KDEPDBSTRING) + 64*1024, 256*1024); KU32 iStringAlloced = (pStrTab->hStrTab.cb - K_OFFSETOF(KDEPDBSTRTAB, aStrings)) / sizeof(KDEPDBSTRING); if ( iStringAlloced <= pStrTab->iStringAlloced || iStringAlloced >= KDEPDBG_STRTAB_IDX_END || iStringAlloced >= KDEPDBHASH_END) return KDEPDBG_STRTAB_IDX_ERROR; if (kDepDbFHGrow(&pStrTab->hStrTab, cbNewSize, (void **)&pStrTab->pStrTab) != 0) return KDEPDBG_STRTAB_IDX_ERROR; pStrTab->iStringAlloced = iStringAlloced; paStrings = &pStrTab->pStrTab->aStrings[0]; } pNewString = &paStrings[iStringEnd]; pNewString->uHash = K_H2LE_U32(uHash); pNewString->cchString = K_H2LE_U32(cchString); memcpy(&pNewString->szString, pszString, cchString); pNewString->szString[cchString] = '\0'; pStrTab->pStrTab->iStringEnd = K_H2LE_U32(iStringEnd + cEntries); /* * Insert hash table entry, rehash it if necessary. */ pHash->auEntries[iInsertAt] = K_H2LE_U32(iStringEnd); pHash->cUsedEntries = K_H2LE_U32(K_LE2H_U32(pHash->cUsedEntries) + 1); pHash->cCollisions = K_H2LE_U32(K_LE2H_U32(pHash->cCollisions) + cCollisions); if ( K_LE2H_U32(pHash->cUsedEntries) > K_LE2H_U32(pHash->cEntries) / 3 * 2 && kDepDbStrTabReHash(pStrTab) != 0) return KDEPDBG_STRTAB_IDX_ERROR; return iStringEnd; } /** Wrapper for kDepDbStrTabLookupHashed. */ static KU32 kDepDbStrTabLookupN(KDEPDBINTSTRTAB const *pStrTab, const char *pszString, size_t cchString) { return kDepDbStrTabLookupHashed(pStrTab, pszString, cchString, kDepDbHashString(pszString, cchString)); } /** Wrapper for kDepDbStrTabAddHashed. */ static KU32 kDepDbStrTabAddN(KDEPDBINTSTRTAB *pStrTab, const char *pszString, size_t cchString) { return kDepDbStrTabAddHashed(pStrTab, pszString, cchString, kDepDbHashString(pszString, cchString)); } /** Wrapper for kDepDbStrTabLookupHashed. */ static KU32 kDepDbStrTabLookup(KDEPDBINTSTRTAB const *pStrTab, const char *pszString) { return kDepDbStrTabLookupN(pStrTab, pszString, strlen(pszString)); } /** Wrapper for kDepDbStrTabAddHashed. */ static KU32 kDepDbStrTabAdd(KDEPDBINTSTRTAB *pStrTab, const char *pszString) { return kDepDbStrTabAddN(pStrTab, pszString, strlen(pszString)); } /** * Opens the string table files, creating them if necessary. */ static int kDepDbStrTabInit(KDEPDBINTSTRTAB *pStrTab, const char *pszFilenameBase) { size_t cchFilenameBase = strlen(pszFilenameBase); char szPath[4096]; int rc; KBOOL fNew; /* Basic member init, so kDepDbStrTabTerm always works. */ pStrTab->pHash = NULL; kDepDbFHInit(&pStrTab->hHash); pStrTab->pStrTab = NULL; kDepDbFHInit(&pStrTab->hStrTab); pStrTab->iStringAlloced = 0; /* check the length. */ if (cchFilenameBase + sizeof(".strtab.hash") > sizeof(szPath)) return -1; /* * Open the string table first. */ memcpy(szPath, pszFilenameBase, cchFilenameBase); memcpy(&szPath[cchFilenameBase], ".strtab", sizeof(".strtab")); rc = kDepDbFHOpen(&pStrTab->hStrTab, szPath, K_TRUE, &fNew); return -1; } kbuild-3686/src/kmk/guile.c0000664000175000017500000000764715053010075015550 0ustar locutuslocutus/* GNU Guile interface for GNU Make. Copyright (C) 2011-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include "makeint.h" #ifdef HAVE_GUILE #include "gnumake.h" #include "debug.h" #include "filedef.h" #include "dep.h" #include "variable.h" #include /* Pre-2.0 versions of Guile don't have a typedef for gsubr function types. */ #if SCM_MAJOR_VERSION < 2 # define GSUBR_TYPE SCM (*) () /* Guile 1.x doesn't really support i18n. */ # define EVAL_STRING(_s) scm_c_eval_string (_s) #else # define GSUBR_TYPE scm_t_subr # define EVAL_STRING(_s) scm_eval_string (scm_from_utf8_string (_s)) #endif static SCM make_mod = SCM_EOL; static SCM obj_to_str = SCM_EOL; /* Convert an SCM object into a string. */ static char * cvt_scm_to_str (SCM obj) { return scm_to_locale_string (scm_call_1 (obj_to_str, obj)); } /* Perform the GNU make expansion function. */ static SCM guile_expand_wrapper (SCM obj) { char *str = cvt_scm_to_str (obj); SCM ret; char *res; DB (DB_BASIC, (_("guile: Expanding '%s'\n"), str)); res = gmk_expand (str); ret = scm_from_locale_string (res); free (str); free (res); return ret; } /* Perform the GNU make eval function. */ static SCM guile_eval_wrapper (SCM obj) { char *str = cvt_scm_to_str (obj); DB (DB_BASIC, (_("guile: Evaluating '%s'\n"), str)); gmk_eval (str, 0); return SCM_BOOL_F; } /* Invoked by scm_c_define_module(), in the context of the GNU make module. */ static void guile_define_module (void *data UNUSED) { /* Ingest the predefined Guile module for GNU make. */ #include "gmk-default.h" /* Register a subr for GNU make's eval capability. */ scm_c_define_gsubr ("gmk-expand", 1, 0, 0, (GSUBR_TYPE) guile_expand_wrapper); /* Register a subr for GNU make's eval capability. */ scm_c_define_gsubr ("gmk-eval", 1, 0, 0, (GSUBR_TYPE) guile_eval_wrapper); /* Define the rest of the module. */ scm_c_eval_string (GUILE_module_defn); } /* Initialize the GNU make Guile module. */ static void * guile_init (void *arg UNUSED) { /* Define the module. */ make_mod = scm_c_define_module ("gnu make", guile_define_module, NULL); /* Get a reference to the object-to-string translator, for later. */ obj_to_str = scm_variable_ref (scm_c_module_lookup (make_mod, "obj-to-str")); /* Import the GNU make module exports into the generic space. */ scm_c_eval_string ("(use-modules (gnu make))"); return NULL; } static void * internal_guile_eval (void *arg) { return cvt_scm_to_str (EVAL_STRING (arg)); } /* This is the function registered with make */ static char * func_guile (const char *funcname UNUSED, unsigned int argc UNUSED, char **argv) { static int init = 0; if (! init) { /* Initialize the Guile interpreter. */ scm_with_guile (guile_init, NULL); init = 1; } if (argv[0] && argv[0][0] != '\0') return scm_with_guile (internal_guile_eval, argv[0]); return NULL; } /* ----- Public interface ----- */ /* We could send the flocp to define_new_function(), but since guile is "kind of" built-in, that didn't seem so useful. */ int guile_gmake_setup (const floc *flocp UNUSED) { /* Create a make function "guile". */ gmk_add_function ("guile", func_guile, 0, 1, GMK_FUNC_DEFAULT); return 1; } #else int guile_gmake_setup (const floc *flocp UNUSED) { return 1; } #endif kbuild-3686/src/kmk/TODO.private0000664000175000017500000001276515053010075016435 0ustar locutuslocutus -*-Indented-Text-*- GNU Make TODO List ------------------ This list comes both from the authors and from users of GNU make. They are listed in no particular order! Also, I don't guarantee that all of them will be ultimately deemed "good ideas" and implemented. These are just the ones that, at first blush, seem to have some merit (and that I can remember). However, if you see something here you really, really want, speak up. All other things being equal, I will tend to implement things that seem to maximize user satisfaction. If you want to implement some of them yourself, barring the ones I've marked below, have at it! Please contact me first to let me know you're working on it, and give me some info about the design--and, critically, information about any user-visible syntax change, etc. The Top Item ------------ If you know perl (or want to learn DejaGNU or similar), the number one priority on my list of things I don't have time to do right now is fixing up the GNU make test suite. Most importantly it needs to be made "parallelizable", so more than one regression can run at the same time (essentially, make the "work" directory local). Also, the CWD during the test should be in the work directory or, better, a test-specific temporary directory so each test gets a new directory; right now sometimes tests leak files into the main directory which causes subsequent tests to fail (some tests may need to be tweaked). Beyond that, any cleanup done to make writing, reading, or handling tests simpler would be great! Please feel free to make whatever changes you like to the current tests, given some high-level goals, and that you'll port the current tests to whatever you do :). The Rest of the List -------------------- 1) Option to check more than timestamps to determine if targets have changed. This is also a very big one. It's _close_ to my plate :), and I have very definite ideas about how I would like it done. Please pick something else unless you must have this feature. If you try it, please work _extremely_ closely with me on it. 1a) Possibly a special case of this is the .KEEP_STATE feature of Sun's make. Some great folks at W U. in Canada did an implementation of this for a class project. Their approach is reasonable and workable, but doesn't really fit into my ideas for #2. Maybe that's OK. I have paperwork for their work so if you want to do this one talk to me to get what they've already done. [K R Praveen ] 2) Currently you can use "%.foo %.bar : %.baz" to mean that one invocation of the rule builds both targets. GNU make needs a way to do that for explicit rules, too. I heard a rumor that some versions of make all you to say "a.foo + a.bar : a.baz" to do this (i.e., a "+" means one invocation builds both). Don't know if this is the best syntax or not... what if you say "a.foo + a.bar a.bam : a.baz"; what does that mean? 3) Multi-token pattern rule matching (allow %1/%2.c : %1/obj/%2.o, etc., or something like that). Maybe using regex? 4) Provide a .TARGETS variable, containing the names of the targets defined in the makefile. Actually, I now think a $(targets ...) function, at least, might be better than a MAKETARGETS variable. The argument would be types of targets to list: "phony" is the most useful one. I suppose "default" might also be useful. Maybe some others; check the bitfields to see what might be handy. 5) Some sort of operating-system independent way of handling paths would be outstanding, so makefiles can be written for UNIX, VMS, DOS, MS-Windows, Amiga, etc. with a minimum of specialization. Or, perhaps related/instead of, some sort of meta-quoting syntax so make can deal with filenames containing spaces, colons, etc. I dunno, maybe something like $[...]? This may well not be worth doing until #1 is done. 6) Right now the .PRECIOUS, .INTERMEDIATE, and .SECONDARY pseudo-targets have different capabilities. For example, .PRECIOUS can take a "%", the others can't. Etc. These should all work the same, insofar as that makes sense. 7) Improved debugging/logging/etc. capabilities. Part of this is done: I introduced a number of debugging enhancements. Tim Magill is (I think) looking into options to control output more selectively. One thing I want to do in debugging is add a flag to allow debugging of variables as they're expanded (!). This would be incredibly verbose, but could be invaluable when nothing else seems to work and you just can't figure it out. The way variables are expanded now means this isn't 100% trivial, but it probably won't be hard. ------------------------------------------------------------------------------- Copyright (C) 1997-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . kbuild-3686/src/kmk/hash.c0000664000175000017500000003252515053010075015357 0ustar locutuslocutus/* hash.c -- hash table maintenance Copyright (C) 1995, 1999, 2002, 2010 Free Software Foundation, Inc. Written by Greg McGary GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include "makeint.h" #include "hash.h" #ifdef CONFIG_WITH_STRCACHE2 # include #endif #define CALLOC(t, n) ((t *) xcalloc (sizeof (t) * (n))) #define MALLOC(t, n) ((t *) xmalloc (sizeof (t) * (n))) #define REALLOC(o, t, n) ((t *) xrealloc ((o), sizeof (t) * (n))) #define CLONE(o, t, n) ((t *) memcpy (MALLOC (t, (n)), (o), sizeof (t) * (n))) static void hash_rehash __P((struct hash_table* ht)); static unsigned long round_up_2 __P((unsigned long rough)); /* Implement double hashing with open addressing. The table size is always a power of two. The secondary ('increment') hash function is forced to return an odd-value, in order to be relatively prime to the table size. This guarantees that the increment can potentially hit every slot in the table during collision resolution. */ void *hash_deleted_item = &hash_deleted_item; /* Force the table size to be a power of two, possibly rounding up the given size. */ void hash_init (struct hash_table *ht, unsigned long size, hash_func_t hash_1, hash_func_t hash_2, hash_cmp_func_t hash_cmp) { ht->ht_size = round_up_2 (size); ht->ht_empty_slots = ht->ht_size; ht->ht_vec = (void**) CALLOC (struct token *, ht->ht_size); if (ht->ht_vec == 0) { fprintf (stderr, _("can't allocate %lu bytes for hash table: memory exhausted"), ht->ht_size * (unsigned long) sizeof (struct token *)); exit (MAKE_TROUBLE); } ht->ht_capacity = ht->ht_size - (ht->ht_size / 16); /* 93.75% loading factor */ ht->ht_fill = 0; ht->ht_collisions = 0; ht->ht_lookups = 0; ht->ht_rehashes = 0; ht->ht_hash_1 = hash_1; ht->ht_hash_2 = hash_2; ht->ht_compare = hash_cmp; #ifdef CONFIG_WITH_STRCACHE2 ht->ht_strcache = 0; ht->ht_off_string = 0; #endif } #ifdef CONFIG_WITH_STRCACHE2 /* Same as hash_init, except that no callbacks are needed since all keys - including the ones being searched for - are from a string cache. This means that any give string will only have one pointer value and that the hash and length can be retrived very cheaply, thus permitting some nice optimizations. STRCACHE points to the string cache, while OFF_STRING gives the offset of the string pointer in the item structures the hash table entries points to. */ void hash_init_strcached (struct hash_table *ht, unsigned long size, struct strcache2 *strcache, unsigned int off_string) { hash_init (ht, size, 0, 0, 0); ht->ht_strcache = strcache; ht->ht_off_string = off_string; } #endif /* CONFIG_WITH_STRCACHE2 */ /* Load an array of items into 'ht'. */ void hash_load (struct hash_table *ht, void *item_table, unsigned long cardinality, unsigned long size) { char *items = (char *) item_table; #ifndef CONFIG_WITH_STRCACHE2 while (cardinality--) { hash_insert (ht, items); items += size; } #else /* CONFIG_WITH_STRCACHE2 */ if (ht->ht_strcache) while (cardinality--) { hash_insert_strcached (ht, items); items += size; } else while (cardinality--) { hash_insert (ht, items); items += size; } #endif /* CONFIG_WITH_STRCACHE2 */ } /* Returns the address of the table slot matching 'key'. If 'key' is not found, return the address of an empty slot suitable for inserting 'key'. The caller is responsible for incrementing ht_fill on insertion. */ void ** hash_find_slot (struct hash_table *ht, const void *key) { void **slot; void **deleted_slot = 0; unsigned int hash_2 = 0; unsigned int hash_1 = (*ht->ht_hash_1) (key); #ifdef CONFIG_WITH_STRCACHE2 assert (ht->ht_strcache == 0); #endif MAKE_STATS (ht->ht_lookups++); MAKE_STATS_3 (make_stats_ht_lookups++); for (;;) { hash_1 &= (ht->ht_size - 1); slot = &ht->ht_vec[hash_1]; if (*slot == 0) return (deleted_slot ? deleted_slot : slot); if (*slot == hash_deleted_item) { if (deleted_slot == 0) deleted_slot = slot; } else { if (key == *slot) return slot; if ((*ht->ht_compare) (key, *slot) == 0) return slot; MAKE_STATS (ht->ht_collisions++); MAKE_STATS_3 (make_stats_ht_collisions++); } if (!hash_2) hash_2 = (*ht->ht_hash_2) (key) | 1; hash_1 += hash_2; } } #ifdef CONFIG_WITH_STRCACHE2 /* hash_find_slot version for tables created with hash_init_strcached. */ void ** hash_find_slot_strcached (struct hash_table *ht, const void *key) { void **slot; void **deleted_slot = 0; const char *str1 = *(const char **)((const char *)key + ht->ht_off_string); const char *str2; unsigned int hash_1 = strcache2_calc_ptr_hash (ht->ht_strcache, str1); unsigned int hash_2; #ifdef CONFIG_WITH_STRCACHE2 assert (ht->ht_strcache != 0); #endif MAKE_STATS (ht->ht_lookups++); MAKE_STATS_3 (make_stats_ht_lookups++); /* first iteration unrolled. */ hash_1 &= (ht->ht_size - 1); slot = &ht->ht_vec[hash_1]; if (*slot == 0) return slot; if (*slot != hash_deleted_item) { str2 = *(const char **)((const char *)(*slot) + ht->ht_off_string); if (str1 == str2) return slot; MAKE_STATS (ht->ht_collisions++); MAKE_STATS_3 (make_stats_ht_collisions++); } else deleted_slot = slot; /* the rest of the loop. */ hash_2 = strcache2_get_hash (ht->ht_strcache, str1) | 1; hash_1 += hash_2; for (;;) { hash_1 &= (ht->ht_size - 1); slot = &ht->ht_vec[hash_1]; if (*slot == 0) return (deleted_slot ? deleted_slot : slot); if (*slot == hash_deleted_item) { if (deleted_slot == 0) deleted_slot = slot; } else { str2 = *(const char **)((const char *)(*slot) + ht->ht_off_string); if (str1 == str2) return slot; MAKE_STATS (ht->ht_collisions++); MAKE_STATS_3 (make_stats_ht_collisions++); } hash_1 += hash_2; } } #endif /* CONFIG_WITH_STRCACHE2 */ void * hash_find_item (struct hash_table *ht, const void *key) { void **slot = hash_find_slot (ht, key); return ((HASH_VACANT (*slot)) ? 0 : *slot); } #ifdef CONFIG_WITH_STRCACHE2 void * hash_find_item_strcached (struct hash_table *ht, const void *key) { void **slot = hash_find_slot_strcached (ht, key); return ((HASH_VACANT (*slot)) ? 0 : *slot); } #endif /* CONFIG_WITH_STRCACHE2 */ void * hash_insert (struct hash_table *ht, const void *item) { void **slot = hash_find_slot (ht, item); const void *old_item = *slot; hash_insert_at (ht, item, slot); return (void *)((HASH_VACANT (old_item)) ? 0 : old_item); } #ifdef CONFIG_WITH_STRCACHE2 void * hash_insert_strcached (struct hash_table *ht, const void *item) { void **slot = hash_find_slot_strcached (ht, item); const void *old_item = slot ? *slot : 0; hash_insert_at (ht, item, slot); return (void *)((HASH_VACANT (old_item)) ? 0 : old_item); } #endif /* CONFIG_WITH_STRCACHE2 */ void * hash_insert_at (struct hash_table *ht, const void *item, const void *slot) { const void *old_item = *(void **) slot; if (HASH_VACANT (old_item)) { ht->ht_fill++; if (old_item == 0) ht->ht_empty_slots--; old_item = item; } *(void const **) slot = item; if (ht->ht_empty_slots < ht->ht_size - ht->ht_capacity) { hash_rehash (ht); #ifdef CONFIG_WITH_STRCACHE2 if (ht->ht_strcache) return (void *)hash_find_slot_strcached (ht, item); #endif /* CONFIG_WITH_STRCACHE2 */ return (void *) hash_find_slot (ht, item); } else return (void *) slot; } void * hash_delete (struct hash_table *ht, const void *item) { void **slot = hash_find_slot (ht, item); return hash_delete_at (ht, slot); } #ifdef CONFIG_WITH_STRCACHE2 void * hash_delete_strcached (struct hash_table *ht, const void *item) { void **slot = hash_find_slot_strcached (ht, item); return hash_delete_at (ht, slot); } #endif /* CONFIG_WITH_STRCACHE2 */ void * hash_delete_at (struct hash_table *ht, const void *slot) { void *item = *(void **) slot; if (!HASH_VACANT (item)) { *(void const **) slot = hash_deleted_item; ht->ht_fill--; return item; } else return 0; } void hash_free_items (struct hash_table *ht) { void **vec = ht->ht_vec; void **end = &vec[ht->ht_size]; for (; vec < end; vec++) { void *item = *vec; if (!HASH_VACANT (item)) free (item); *vec = 0; } ht->ht_fill = 0; ht->ht_empty_slots = ht->ht_size; } #ifdef CONFIG_WITH_ALLOC_CACHES void hash_free_items_cached (struct hash_table *ht, struct alloccache *cache) { void **vec = ht->ht_vec; void **end = &vec[ht->ht_size]; for (; vec < end; vec++) { void *item = *vec; if (!HASH_VACANT (item)) alloccache_free (cache, item); *vec = 0; } ht->ht_fill = 0; ht->ht_empty_slots = ht->ht_size; } #endif /* CONFIG_WITH_ALLOC_CACHES */ void hash_delete_items (struct hash_table *ht) { void **vec = ht->ht_vec; void **end = &vec[ht->ht_size]; for (; vec < end; vec++) *vec = 0; ht->ht_fill = 0; ht->ht_collisions = 0; ht->ht_lookups = 0; ht->ht_rehashes = 0; ht->ht_empty_slots = ht->ht_size; } void hash_free (struct hash_table *ht, int free_items) { if (free_items) hash_free_items (ht); else { ht->ht_fill = 0; ht->ht_empty_slots = ht->ht_size; } free (ht->ht_vec); ht->ht_vec = 0; ht->ht_capacity = 0; } #ifdef CONFIG_WITH_ALLOC_CACHES void hash_free_cached (struct hash_table *ht, int free_items, struct alloccache *cache) { if (free_items) hash_free_items_cached (ht, cache); else { ht->ht_fill = 0; ht->ht_empty_slots = ht->ht_size; } free (ht->ht_vec); ht->ht_vec = 0; ht->ht_capacity = 0; } #endif /* CONFIG_WITH_ALLOC_CACHES */ void hash_map (struct hash_table *ht, hash_map_func_t map) { void **slot; void **end = &ht->ht_vec[ht->ht_size]; for (slot = ht->ht_vec; slot < end; slot++) { if (!HASH_VACANT (*slot)) (*map) (*slot); } } void hash_map_arg (struct hash_table *ht, hash_map_arg_func_t map, void *arg) { void **slot; void **end = &ht->ht_vec[ht->ht_size]; for (slot = ht->ht_vec; slot < end; slot++) { if (!HASH_VACANT (*slot)) (*map) (*slot, arg); } } /* Double the size of the hash table in the event of overflow... */ static void hash_rehash (struct hash_table *ht) { unsigned long old_ht_size = ht->ht_size; void **old_vec = ht->ht_vec; void **ovp; if (ht->ht_fill >= ht->ht_capacity) { ht->ht_size *= 2; ht->ht_capacity = ht->ht_size - (ht->ht_size >> 4); } ht->ht_rehashes++; ht->ht_vec = (void **) CALLOC (struct token *, ht->ht_size); #ifndef CONFIG_WITH_STRCACHE2 for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++) { if (! HASH_VACANT (*ovp)) { void **slot = hash_find_slot (ht, *ovp); *slot = *ovp; } } #else /* CONFIG_WITH_STRCACHE2 */ if (ht->ht_strcache) for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++) { if (! HASH_VACANT (*ovp)) { void **slot = hash_find_slot_strcached (ht, *ovp); *slot = *ovp; } } else for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++) { if (! HASH_VACANT (*ovp)) { void **slot = hash_find_slot (ht, *ovp); *slot = *ovp; } } #endif /* CONFIG_WITH_STRCACHE2 */ ht->ht_empty_slots = ht->ht_size - ht->ht_fill; free (old_vec); } void hash_print_stats (struct hash_table *ht, FILE *out_FILE) { /* GKM FIXME: honor NO_FLOAT */ fprintf (out_FILE, _("Load=%ld/%ld=%.0f%%, "), ht->ht_fill, ht->ht_size, 100.0 * (double) ht->ht_fill / (double) ht->ht_size); fprintf (out_FILE, _("Rehash=%d, "), ht->ht_rehashes); MAKE_STATS( fprintf (out_FILE, _("Collisions=%ld/%ld=%.0f%%"), ht->ht_collisions, ht->ht_lookups, (ht->ht_lookups ? (100.0 * (double) ht->ht_collisions / (double) ht->ht_lookups) : 0)); ); } /* Dump all items into a NULL-terminated vector. Use the user-supplied vector, or malloc one. */ void ** hash_dump (struct hash_table *ht, void **vector_0, qsort_cmp_t compare) { void **vector; void **slot; void **end = &ht->ht_vec[ht->ht_size]; if (vector_0 == 0) vector_0 = MALLOC (void *, ht->ht_fill + 1); vector = vector_0; for (slot = ht->ht_vec; slot < end; slot++) if (!HASH_VACANT (*slot)) *vector++ = *slot; *vector = 0; if (compare) qsort (vector_0, ht->ht_fill, sizeof (void *), compare); return vector_0; } /* Round a given number up to the nearest power of 2. */ static unsigned long round_up_2 (unsigned long n) { n |= (n >> 1); n |= (n >> 2); n |= (n >> 4); n |= (n >> 8); n |= (n >> 16); #if !defined(HAVE_LIMITS_H) || ULONG_MAX > 4294967295 /* We only need this on systems where unsigned long is >32 bits. */ n |= (n >> 32); #endif return n + 1; } kbuild-3686/src/kmk/remake.c0000664000175000017500000020614415053010075015700 0ustar locutuslocutus/* Basic dependency engine for GNU Make. Copyright (C) 1988-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include "makeint.h" #include "filedef.h" #include "job.h" #include "commands.h" #include "dep.h" #include "variable.h" #include "debug.h" #include #ifdef HAVE_FCNTL_H #include #else #include #endif #ifdef VMS #include #endif #ifdef WINDOWS32 #include #endif /* The test for circular dependencies is based on the 'updating' bit in 'struct file'. However, double colon targets have separate 'struct file's; make sure we always use the base of the double colon chain. */ #define start_updating(_f) (((_f)->double_colon ? (_f)->double_colon : (_f))\ ->updating = 1) #define finish_updating(_f) (((_f)->double_colon ? (_f)->double_colon : (_f))\ ->updating = 0) #define is_updating(_f) (((_f)->double_colon ? (_f)->double_colon : (_f))\ ->updating) /* Incremented when a command is started (under -n, when one would be). */ unsigned int commands_started = 0; /* Set to the goal dependency. Mostly needed for remaking makefiles. */ static struct goaldep *goal_list; static struct dep *goal_dep; /* Current value for pruning the scan of the goal chain. All files start with considered == 0. */ static unsigned int considered = 0; static enum update_status update_file (struct file *file, unsigned int depth); static enum update_status update_file_1 (struct file *file, unsigned int depth); static enum update_status check_dep (struct file *file, unsigned int depth, FILE_TIMESTAMP this_mtime, int *must_make); static enum update_status touch_file (struct file *file); static void remake_file (struct file *file); static FILE_TIMESTAMP name_mtime (const char *name); static const char *library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr); #ifdef CONFIG_WITH_DOT_MUST_MAKE static int call_must_make_target_var (struct file *file, unsigned int depth); #endif #ifdef CONFIG_WITH_DOT_IS_CHANGED static int call_is_changed_target_var (struct file *file); #endif /* Remake all the goals in the 'struct dep' chain GOALS. Return -1 if nothing was done, 0 if all goals were updated successfully, or 1 if a goal failed. If rebuilding_makefiles is nonzero, these goals are makefiles, so -t, -q, and -n should be disabled for them unless they were also command-line targets, and we should only make one goal at a time and return as soon as one goal whose 'changed' member is nonzero is successfully made. */ enum update_status update_goal_chain (struct goaldep *goaldeps) { int t = touch_flag, q = question_flag, n = just_print_flag; enum update_status status = us_none; /* Duplicate the chain so we can remove things from it. */ struct dep *goals = copy_dep_chain ((struct dep *)goaldeps); goal_list = rebuilding_makefiles ? goaldeps : NULL; #define MTIME(file) (rebuilding_makefiles ? file_mtime_no_search (file) \ : file_mtime (file)) /* Start a fresh batch of consideration. */ ++considered; /* Update all the goals until they are all finished. */ while (goals != 0) { register struct dep *g, *lastgoal; /* Start jobs that are waiting for the load to go down. */ start_waiting_jobs (); /* Wait for a child to die. */ reap_children (1, 0); lastgoal = 0; g = goals; while (g != 0) { /* Iterate over all double-colon entries for this file. */ struct file *file; int stop = 0, any_not_updated = 0; goal_dep = g; for (file = g->file->double_colon ? g->file->double_colon : g->file; file != NULL; file = file->prev) { unsigned int ocommands_started; enum update_status fail; file->dontcare = ANY_SET (g->flags, RM_DONTCARE); check_renamed (file); if (rebuilding_makefiles) { if (file->cmd_target) { touch_flag = t; question_flag = q; just_print_flag = n; } else touch_flag = question_flag = just_print_flag = 0; } /* Save the old value of 'commands_started' so we can compare later. It will be incremented when any commands are actually run. */ ocommands_started = commands_started; fail = update_file (file, rebuilding_makefiles ? 1 : 0); check_renamed (file); /* Set the goal's 'changed' flag if any commands were started by calling update_file above. We check this flag below to decide when to give an "up to date" diagnostic. */ if (commands_started > ocommands_started) g->changed = 1; stop = 0; if ((fail || file->updated) && status < us_question) { /* We updated this goal. Update STATUS and decide whether to stop. */ if (file->update_status) { /* Updating failed, or -q triggered. The STATUS value tells our caller which. */ status = file->update_status; /* If -q just triggered, stop immediately. It doesn't matter how much more we run, since we already know the answer to return. */ stop = (question_flag && !keep_going_flag && !rebuilding_makefiles); } else { FILE_TIMESTAMP mtime = MTIME (file); check_renamed (file); if (file->updated && g->changed && mtime != file->mtime_before_update) { /* Updating was done. If this is a makefile and just_print_flag or question_flag is set (meaning -n or -q was given and this file was specified as a command-line target), don't change STATUS. If STATUS is changed, we will get re-exec'd, and enter an infinite loop. */ if (!rebuilding_makefiles || (!just_print_flag && !question_flag)) status = us_success; if (rebuilding_makefiles && file->dontcare) /* This is a default makefile; stop remaking. */ stop = 1; } } } /* Keep track if any double-colon entry is not finished. When they are all finished, the goal is finished. */ any_not_updated |= !file->updated; file->dontcare = 0; if (stop) break; } /* Reset FILE since it is null at the end of the loop. */ file = g->file; if (stop || !any_not_updated) { /* If we have found nothing whatever to do for the goal, print a message saying nothing needs doing. */ if (!rebuilding_makefiles /* If the update_status is success, we updated successfully or not at all. G->changed will have been set above if any commands were actually started for this goal. */ && file->update_status == us_success && !g->changed /* Never give a message under -s or -q. */ && !silent_flag && !question_flag) OS (message, 1, ((file->phony || file->cmds == 0) ? _("Nothing to be done for '%s'.") : _("'%s' is up to date.")), file->name); /* This goal is finished. Remove it from the chain. */ if (lastgoal == 0) goals = g->next; else lastgoal->next = g->next; /* Free the storage. */ #ifndef CONFIG_WITH_ALLOC_CACHES free (g); #else free_dep (g); #endif g = lastgoal == 0 ? goals : lastgoal->next; if (stop) break; } else { lastgoal = g; g = g->next; } } /* If we reached the end of the dependency graph update CONSIDERED for the next pass. */ if (g == 0) ++considered; } if (rebuilding_makefiles) { touch_flag = t; question_flag = q; just_print_flag = n; } return status; } /* If we're rebuilding an included makefile that failed, and we care about errors, show an error message the first time. */ void show_goal_error (void) { struct goaldep *goal; if ((goal_dep->flags & (RM_INCLUDED|RM_DONTCARE)) != RM_INCLUDED) return; for (goal = goal_list; goal; goal = goal->next) if (goal_dep->file == goal->file) { if (goal->error) { OSS (error, &goal->floc, "%s: %s", goal->file->name, strerror ((int)goal->error)); goal->error = 0; } return; } } /* If FILE is not up to date, execute the commands for it. Return 0 if successful, non-0 if unsuccessful; but with some flag settings, just call 'exit' if unsuccessful. DEPTH is the depth in recursions of this function. We increment it during the consideration of our dependencies, then decrement it again after finding out whether this file is out of date. If there are multiple double-colon entries for FILE, each is considered in turn. */ static enum update_status update_file (struct file *file, unsigned int depth) { enum update_status status = us_success; struct file *f; f = file->double_colon ? file->double_colon : file; /* Prune the dependency graph: if we've already been here on _this_ pass through the dependency graph, we don't have to go any further. We won't reap_children until we start the next pass, so no state change is possible below here until then. */ if (f->considered == considered) { /* Check for the case where a target has been tried and failed but the diagnostics haven't been issued. If we need the diagnostics then we will have to continue. */ if (!(f->updated && f->update_status > us_none && !f->dontcare && f->no_diag)) { DBF (DB_VERBOSE, _("Pruning file '%s'.\n")); return f->command_state == cs_finished ? f->update_status : us_success; } } /* This loop runs until we start commands for a double colon rule, or until the chain is exhausted. */ for (; f != 0; f = f->prev) { enum update_status new; f->considered = considered; new = update_file_1 (f, depth); check_renamed (f); /* Clean up any alloca() used during the update. */ alloca (0); /* If we got an error, don't bother with double_colon etc. */ if (new && !keep_going_flag) return new; if (f->command_state == cs_running || f->command_state == cs_deps_running) /* Don't run other :: rules for this target until this rule is finished. */ return us_success; if (new > status) status = new; } /* Process the remaining rules in the double colon chain so they're marked considered. Start their prerequisites, too. */ if (file->double_colon) for (; f != 0 ; f = f->prev) { struct dep *d; f->considered = considered; for (d = f->deps; d != 0; d = d->next) { enum update_status new = update_file (d->file, depth + 1); if (new > status) status = new; } } return status; } /* Show a message stating the target failed to build. */ static void complain (struct file *file) { /* If this file has no_diag set then it means we tried to update it before in the dontcare mode and failed. The target that actually failed is not necessarily this file but could be one of its direct or indirect dependencies. So traverse this file's dependencies and find the one that actually caused the failure. */ struct dep *d; for (d = file->deps; d != 0; d = d->next) { if (d->file->updated && d->file->update_status > us_none && file->no_diag) { complain (d->file); break; } } if (d == 0) { show_goal_error (); /* Didn't find any dependencies to complain about. */ #ifdef KMK /* jokes */ if (!keep_going_flag && file->parent == 0) { const char *msg_joke = 0; extern struct dep *goals; /* classics */ if (!strcmp (file->name, "fire") || !strcmp (file->name, "Fire")) msg_joke = "No matches.\n"; else if (!strcmp (file->name, "love") || !strcmp (file->name, "Love") || !strcmp (file->name, "peace") || !strcmp (file->name, "Peace")) msg_joke = "Not war.\n"; else if (!strcmp (file->name, "war")) msg_joke = "Don't know how to make war.\n"; /* http://xkcd.com/149/ - GNU Make bug #23273. */ else if (( !strcmp (file->name, "me") && goals != 0 && !strcmp (dep_name(goals), "me") && goals->next != 0 && !strcmp (dep_name(goals->next), "a") && goals->next->next != 0) || !strncmp (file->name, "me a ", 5)) msg_joke = # ifdef HAVE_UNISTD_H getuid () == 0 ? "Okay.\n" : # endif "What? Make it yourself!\n"; if (msg_joke) { fputs (msg_joke, stderr); die (2); } } #endif /* KMK */ if (file->parent) { size_t l = strlen (file->name) + strlen (file->parent->name) + 4; const char *m = _("%sNo rule to make target '%s', needed by '%s'%s"); if (!keep_going_flag) fatal (NILF, l, m, "", file->name, file->parent->name, ""); error (NILF, l, m, "*** ", file->name, file->parent->name, "."); } else { size_t l = strlen (file->name) + 4; const char *m = _("%sNo rule to make target '%s'%s"); if (!keep_going_flag) fatal (NILF, l, m, "", file->name, ""); error (NILF, l, m, "*** ", file->name, "."); } file->no_diag = 0; } } /* Consider a single 'struct file' and update it as appropriate. Return 0 on success, or non-0 on failure. */ static enum update_status update_file_1 (struct file *file, unsigned int depth) { enum update_status dep_status = us_success; FILE_TIMESTAMP this_mtime; int noexist, must_make, deps_changed; struct file *ofile; struct dep *d, *ad; struct dep amake; int running = 0; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET struct file *org_file; struct file *req_file; struct file *f2, *f3; /* Secondary target expansion leaves renamed files around, skip any rename files to simplify multi target handling. */ check_renamed(file); /* Remember the request file and find the primary multi target file. Always work on the primary file in a multi target recipe. */ req_file = file; org_file = file; if (file->multi_head != NULL) { if (file->multi_head == file) DBS (DB_VERBOSE, (_("Considering target file '%s' (multi head).\n"), file->name)); else { org_file = file = file->multi_head; DBS (DB_VERBOSE, (_("Considering target file '%s' -> multi head '%s'.\n"), req_file->name, file->name)); assert (file->multi_head == file); } } else #endif /* CONFIG_WITH_EXPLICIT_MULTITARGET */ DBF (DB_VERBOSE, _("Considering target file '%s'.\n")); if (file->updated) { if (file->update_status > us_none) { DBF (DB_VERBOSE, _("Recently tried and failed to update file '%s'.\n")); /* If the file we tried to make is marked no_diag then no message was printed about it when it failed during the makefile rebuild. If we're trying to build it again in the normal rebuild, print a message now. */ if (file->no_diag && !file->dontcare) complain (file); return file->update_status; } DBF (DB_VERBOSE, _("File '%s' was considered already.\n")); return 0; } switch (file->command_state) { case cs_not_started: case cs_deps_running: break; case cs_running: DBF (DB_VERBOSE, _("Still updating file '%s'.\n")); return 0; case cs_finished: DBF (DB_VERBOSE, _("Finished updating file '%s'.\n")); return file->update_status; default: abort (); } /* Determine whether the diagnostics will be issued should this update fail. */ file->no_diag = file->dontcare; ++depth; /* Notice recursive update of the same file. */ start_updating (file); /* We might change file if we find a different one via vpath; remember this one to turn off updating. */ ofile = file; /* Looking at the file's modtime beforehand allows the possibility that its name may be changed by a VPATH search, and thus it may not need an implicit rule. If this were not done, the file might get implicit commands that apply to its initial name, only to have that name replaced with another found by VPATH search. For multi target files check the other files and use the time of the oldest / non-existing file. */ #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET this_mtime = file_mtime (file); check_renamed (file); f3 = file; for (f2 = file->multi_next; f2 != NULL && this_mtime != NONEXISTENT_MTIME; f2 = f2->multi_next) if (!f2->multi_maybe) { FILE_TIMESTAMP second_mtime = file_mtime (f2); if (second_mtime < this_mtime) { this_mtime = second_mtime; f3 = f2; } } /** @todo this isn't sufficient, need to introduce a truly optional type and * make |+ ignore mtime. let's hope that doesn't break too much... */ /* If the requested file doesn't exist, always do a remake in the hope that it is recreated even if it's "maybe" target. */ else if (f2 == req_file && file_mtime (f2) == NONEXISTENT_MTIME) { this_mtime = NONEXISTENT_MTIME; f3 = f2; break; } check_renamed (f3); noexist = this_mtime == NONEXISTENT_MTIME; if (noexist) DBS (DB_BASIC, (_("File '%s' does not exist.\n"), f3->name)); #else /* !CONFIG_WITH_EXPLICIT_MULTITARGET */ this_mtime = file_mtime (file); check_renamed (file); noexist = this_mtime == NONEXISTENT_MTIME; if (noexist) DBF (DB_BASIC, _("File '%s' does not exist.\n")); #endif /* !CONFIG_WITH_EXPLICIT_MULTITARGET */ else if (ORDINARY_MTIME_MIN <= this_mtime && this_mtime <= ORDINARY_MTIME_MAX && file->low_resolution_time) { /* Avoid spurious rebuilds due to low resolution time stamps. */ int ns = FILE_TIMESTAMP_NS (this_mtime); if (ns != 0) OS (error, NILF, _("*** Warning: .LOW_RESOLUTION_TIME file '%s' has a high resolution time stamp"), file->name); this_mtime += FILE_TIMESTAMPS_PER_S - 1 - ns; } must_make = noexist; /* If file was specified as a target with no commands, come up with some default commands. */ if (!file->phony && file->cmds == 0 && !file->tried_implicit) { if (try_implicit_rule (file, depth)) DBF (DB_IMPLICIT, _("Found an implicit rule for '%s'.\n")); else DBF (DB_IMPLICIT, _("No implicit rule found for '%s'.\n")); file->tried_implicit = 1; } if (file->cmds == 0 && !file->is_target && default_file != 0 && default_file->cmds != 0) { DBF (DB_IMPLICIT, _("Using default recipe for '%s'.\n")); file->cmds = default_file->cmds; } /* Update all non-intermediate files we depend on, if necessary, and see whether any of them is more recent than this file. We need to walk our deps, AND the deps of any also_make targets to ensure everything happens in the correct order. bird: For explicit multitarget rules we must iterate all the output files to get the correct picture. The special .MUST_MAKE target variable call is also done from this context. */ #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET assert (file == org_file); for (f2 = file; f2; file = f2 = f2->multi_next) { #endif amake.file = file; amake.next = file->also_make; ad = &amake; while (ad) { struct dep *lastd = 0; /* Find the deps we're scanning */ d = ad->file->deps; ad = ad->next; while (d) { enum update_status new; FILE_TIMESTAMP mtime; int maybe_make; int dontcare = 0; check_renamed (d->file); mtime = file_mtime (d->file); check_renamed (d->file); if (is_updating (d->file)) { #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET /* silently ignore the order-only dep hack. */ if (file->multi_maybe && d->file == org_file) { lastd = d; d = d->next; continue; } #endif OSS (error, NILF, _("Circular %s <- %s dependency dropped."), file->name, d->file->name); /* We cannot free D here because our the caller will still have a reference to it when we were called recursively via check_dep below. */ if (lastd == 0) file->deps = d->next; else lastd->next = d->next; d = d->next; continue; } d->file->parent = file; maybe_make = must_make; /* Inherit dontcare flag from our parent. */ if (rebuilding_makefiles) { dontcare = d->file->dontcare; d->file->dontcare = file->dontcare; } new = check_dep (d->file, depth, this_mtime, &maybe_make); if (new > dep_status) dep_status = new; /* Restore original dontcare flag. */ if (rebuilding_makefiles) d->file->dontcare = dontcare; if (! d->ignore_mtime) must_make = maybe_make; check_renamed (d->file); { register struct file *f = d->file; if (f->double_colon) f = f->double_colon; do { running |= (f->command_state == cs_running || f->command_state == cs_deps_running); f = f->prev; } while (f != 0); } if (dep_status && !keep_going_flag) break; if (!running) /* The prereq is considered changed if the timestamp has changed while it was built, OR it doesn't exist. */ d->changed = ((file_mtime (d->file) != mtime) || (mtime == NONEXISTENT_MTIME)); lastd = d; d = d->next; } } #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET if (dep_status != 0 && !keep_going_flag) break; } file = org_file; #endif #ifdef CONFIG_WITH_DOT_MUST_MAKE /* Check with the .MUST_MAKE target variable if it's not already decided to make the file. */ # ifdef CONFIG_WITH_EXPLICIT_MULTITARGET if (!must_make) for (f2 = org_file; f2 && !must_make; f2 = f2->multi_next) must_make = call_must_make_target_var (f2, depth); # else if (!must_make) must_make = call_must_make_target_var (file, depth); # endif #endif /* CONFIG_WITH_DOT_MUST_MAKE */ /* Now we know whether this target needs updating. If it does, update all the intermediate files we depend on. */ if (must_make || always_make_flag) { #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET for (file = f2 = org_file; f2; file = f2 = f2->multi_next) #endif for (d = file->deps; d != 0; d = d->next) if (d->file->intermediate) { enum update_status new; int dontcare = 0; FILE_TIMESTAMP mtime = file_mtime (d->file); check_renamed (d->file); d->file->parent = file; /* Inherit dontcare flag from our parent. */ if (rebuilding_makefiles) { dontcare = d->file->dontcare; d->file->dontcare = file->dontcare; } /* We may have already considered this file, when we didn't know we'd need to update it. Force update_file() to consider it and not prune it. */ d->file->considered = 0; new = update_file (d->file, depth); if (new > dep_status) dep_status = new; /* Restore original dontcare flag. */ if (rebuilding_makefiles) d->file->dontcare = dontcare; check_renamed (d->file); { register struct file *f = d->file; if (f->double_colon) f = f->double_colon; do { running |= (f->command_state == cs_running || f->command_state == cs_deps_running); f = f->prev; } while (f != 0); } if (dep_status && !keep_going_flag) break; if (!running) d->changed = ((file->phony && file->cmds != 0) || file_mtime (d->file) != mtime); } #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET file = org_file; #endif } finish_updating (file); finish_updating (ofile); DBF (DB_VERBOSE, _("Finished prerequisites of target file '%s'.\n")); if (running) { set_command_state (file, cs_deps_running); --depth; DBF (DB_VERBOSE, _("The prerequisites of '%s' are being made.\n")); return 0; } /* If any dependency failed, give up now. */ if (dep_status) { /* I'm not sure if we can't just assign dep_status... */ file->update_status = dep_status == us_none ? us_failed : dep_status; notice_finished_file (file); --depth; DBF (DB_VERBOSE, _("Giving up on target file '%s'.\n")); if (depth == 0 && keep_going_flag && !just_print_flag && !question_flag) OS (error, NILF, _("Target '%s' not remade because of errors."), file->name); return dep_status; } if (file->command_state == cs_deps_running) /* The commands for some deps were running on the last iteration, but they have finished now. Reset the command_state to not_started to simplify later bookkeeping. It is important that we do this only when the prior state was cs_deps_running, because that prior state was definitely propagated to FILE's also_make's by set_command_state (called above), but in another state an also_make may have independently changed to finished state, and we would confuse that file's bookkeeping (updated, but not_started is bogus state). */ set_command_state (file, cs_not_started); /* Now record which prerequisites are more recent than this file, so we can define $?. */ deps_changed = 0; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET for (file = f2 = org_file; f2; file = f2 = f2->multi_next) #endif for (d = file->deps; d != 0; d = d->next) { FILE_TIMESTAMP d_mtime = file_mtime (d->file); #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET if (d->file == file && file->multi_maybe) continue; #endif check_renamed (d->file); if (! d->ignore_mtime) { #if 1 /* %%% In version 4, remove this code completely to implement not remaking deps if their deps are newer than their parents. */ if (d_mtime == NONEXISTENT_MTIME && !d->file->intermediate) /* We must remake if this dep does not exist and is not intermediate. */ must_make = 1; #endif /* Set DEPS_CHANGED if this dep actually changed. */ deps_changed |= d->changed; } /* Set D->changed if either this dep actually changed, or its dependent, FILE, is older or does not exist. */ d->changed |= noexist || d_mtime > this_mtime; if (!noexist && ISDB (DB_BASIC|DB_VERBOSE)) { const char *fmt = 0; if (d->ignore_mtime) { if (ISDB (DB_VERBOSE)) fmt = _("Prerequisite '%s' is order-only for target '%s'.\n"); } else if (d_mtime == NONEXISTENT_MTIME) { if (ISDB (DB_BASIC)) fmt = _("Prerequisite '%s' of target '%s' does not exist.\n"); } else if (d->changed) { if (ISDB (DB_BASIC)) fmt = _("Prerequisite '%s' is newer than target '%s'.\n"); } else if (ISDB (DB_VERBOSE)) fmt = _("Prerequisite '%s' is older than target '%s'.\n"); if (fmt) { print_spaces (depth); printf (fmt, dep_name (d), file->name); fflush (stdout); } } } #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET file = org_file; #endif /* Here depth returns to the value it had when we were called. */ depth--; if (file->double_colon && file->deps == 0) { must_make = 1; DBF (DB_BASIC, _("Target '%s' is double-colon and has no prerequisites.\n")); } else if (!noexist && file->is_target && !deps_changed && file->cmds == 0 && !always_make_flag) { must_make = 0; DBF (DB_VERBOSE, _("No recipe for '%s' and no prerequisites actually changed.\n")); } else if (!must_make && file->cmds != 0 && always_make_flag) { must_make = 1; DBF (DB_VERBOSE, _("Making '%s' due to always-make flag.\n")); } if (!must_make) { if (ISDB (DB_VERBOSE)) { print_spaces (depth); printf (_("No need to remake target '%s'"), file->name); if (!streq (file->name, file->hname)) printf (_("; using VPATH name '%s'"), file->hname); puts ("."); fflush (stdout); } notice_finished_file (file); /* Since we don't need to remake the file, convert it to use the VPATH filename if we found one. hfile will be either the local name if no VPATH or the VPATH name if one was found. */ while (file) { file->name = file->hname; file = file->prev; } return 0; } DBF (DB_BASIC, _("Must remake target '%s'.\n")); /* It needs to be remade. If it's VPATH and not reset via GPATH, toss the VPATH. */ if (!streq (file->name, file->hname)) { DB (DB_BASIC, (_(" Ignoring VPATH name '%s'.\n"), file->hname)); file->ignore_vpath = 1; } /* Now, take appropriate actions to remake the file. */ remake_file (file); if (file->command_state != cs_finished) { DBF (DB_VERBOSE, _("Recipe of '%s' is being run.\n")); return 0; } switch (file->update_status) { case us_failed: DBF (DB_BASIC, _("Failed to remake target file '%s'.\n")); break; case us_success: DBF (DB_BASIC, _("Successfully remade target file '%s'.\n")); break; case us_question: DBF (DB_BASIC, _("Target file '%s' needs to be remade under -q.\n")); break; case us_none: break; } file->updated = 1; return file->update_status; } #ifdef CONFIG_WITH_DOT_MUST_MAKE /* Consider the .MUST_MAKE target variable if present. Returns 1 if must remake, 0 if not. The deal is that .MUST_MAKE returns non-zero if it thinks the target needs updating. We have to initialize file variables (for the sake of pattern vars) and set the most important file variables before calling (expanding) the .MUST_MAKE variable. The file variables keeping the dependency lists, $+, $^, $? and $| are not available at this point because $? depends on things happening after we've decided to make the file. So, to keep things simple all 4 of them are undefined in this call. */ static int call_must_make_target_var (struct file *file, unsigned int depth) { struct variable *var; unsigned char ch; const char *str; if (file->variables) { var = lookup_variable_in_set (".MUST_MAKE", sizeof (".MUST_MAKE") - 1, file->variables->set); if (var) { initialize_file_variables (file, 0); set_file_variables (file, 1 /* called early, no dep lists please */); str = variable_expand_for_file_2 (NULL, var->value, var->value_length, file, NULL); /* Stripped string should be non-zero. */ ch = *str; while (ISSPACE (ch)) ch = *++str; if (ch != '\0') { if (ISDB (DB_BASIC)) { print_spaces (depth); printf (_(".MUST_MAKE returned `%s' for target `%s'.\n"), str, file->name); } return 1; } } } return 0; } #endif /* CONFIG_WITH_DOT_MUST_MAKE */ #ifdef CONFIG_WITH_DOT_IS_CHANGED /* Consider the .IS_CHANGED target variable if present. Returns 1 if the file should be considered modified, 0 if not. The calling context and restrictions are the same as for .MUST_MAKE. Make uses the information from this 'function' for determining whether to make a file which lists this as a prerequisite. So, this is the feature you use to check MD5 sums, file sizes, time stamps and the like with data from a previous run. FIXME: Would be nice to know which file is currently being considered. FIXME: Is currently not invoked for intermediate files. */ static int call_is_changed_target_var (struct file *file) { struct variable *var; unsigned char ch; const char *str; if (file->variables) { var = lookup_variable_in_set (".IS_CHANGED", sizeof (".IS_CHANGED") - 1, file->variables->set); if (var) { initialize_file_variables (file, 0); set_file_variables (file, 1 /* called early, no dep lists please */); str = variable_expand_for_file_2 (NULL, var->value, var->value_length, file, NULL); /* stripped string should be non-zero. */ do ch = *str++; while (ISSPACE (ch)); return (ch != '\0'); } } return 0; } #endif /* CONFIG_WITH_DOT_IS_CHANGED */ /* Set FILE's 'updated' flag and re-check its mtime and the mtime's of all files listed in its 'also_make' member. Under -t, this function also touches FILE. On return, FILE->update_status will no longer be us_none if it was. */ void notice_finished_file (struct file *file) { #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET struct file *f2; #endif struct dep *d; int ran = file->command_state == cs_running; int touched = 0; DB (DB_JOBS, (_("notice_finished_file - entering: file=%p `%s' update_status=%d command_state=%d\n"), /* bird */ (void *) file, file->name, file->update_status, file->command_state)); file->command_state = cs_finished; file->updated = 1; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET if (file->multi_head) { assert (file == file->multi_head); for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next) { f2->command_state = cs_finished; f2->updated = 1; } } #endif #ifdef CONFIG_WITH_EXTENDED_NOTPARALLEL /* update not_parallel if the file was flagged for that. */ if ( ran && (file->command_flags & (COMMANDS_NOTPARALLEL | COMMANDS_NO_COMMANDS)) == COMMANDS_NOTPARALLEL) { DB (DB_KMK, (_("not_parallel %d -> %d (file=%p `%s') [notice_finished_file]\n"), not_parallel, not_parallel - 1, (void *) file, file->name)); assert(not_parallel >= 1); --not_parallel; } #endif if (touch_flag /* The update status will be: us_success if 0 or more commands (+ or ${MAKE}) were run and won; us_none if this target was not remade; >us_none if some commands were run and lost. We touch the target if it has commands which either were not run or won when they ran (i.e. status is 0). */ && file->update_status == us_success) { if (file->cmds != 0 && file->cmds->any_recurse) { /* If all the command lines were recursive, we don't want to do the touching. */ unsigned int i; for (i = 0; i < file->cmds->ncommand_lines; ++i) if (!(file->cmds->lines_flags[i] & COMMANDS_RECURSE)) goto have_nonrecursing; } else { have_nonrecursing: if (file->phony) #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET { file->update_status = us_success; if (file->multi_head) for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next) f2->update_status = us_success; } #else file->update_status = us_success; #endif /* According to POSIX, -t doesn't affect targets with no cmds. */ else if (file->cmds != 0) { /* Should set file's modification date and do nothing else. */ file->update_status = touch_file (file); #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET if (file->multi_head) for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next) { /* figure out this, touch if it exist ignore otherwise? */ } #endif /* Pretend we ran a real touch command, to suppress the "'foo' is up to date" message. */ commands_started++; /* Request for the timestamp to be updated (and distributed to the double-colon entries). Simply setting ran=1 would almost have done the trick, but messes up with the also_make updating logic below. */ touched = 1; } } } if (file->mtime_before_update == UNKNOWN_MTIME) file->mtime_before_update = file->last_mtime; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET if (file->multi_head) for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next) if (f2->mtime_before_update == UNKNOWN_MTIME) f2->mtime_before_update = f2->last_mtime; #endif if ((ran && !file->phony) || touched) { int i = 0; /* If -n, -t, or -q and all the commands are recursive, we ran them so really check the target's mtime again. Otherwise, assume the target would have been updated. */ if ((question_flag || just_print_flag || touch_flag) && file->cmds) { for (i = file->cmds->ncommand_lines; i > 0; --i) if (! (file->cmds->lines_flags[i-1] & COMMANDS_RECURSE)) break; } /* If there were no commands at all, it's always new. */ else if (file->is_target && file->cmds == 0) i = 1; file->last_mtime = i == 0 ? UNKNOWN_MTIME : NEW_MTIME; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET if (file->multi_head) for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next) file->last_mtime = i == 0 ? UNKNOWN_MTIME : NEW_MTIME; /*??*/ #endif } if (file->double_colon) { /* If this is a double colon rule and it is the last one to be updated, propagate the change of modification time to all the double-colon entries for this file. We do it on the last update because it is important to handle individual entries as separate rules with separate timestamps while they are treated as targets and then as one rule with the unified timestamp when they are considered as a prerequisite of some target. */ struct file *f; FILE_TIMESTAMP max_mtime = file->last_mtime; /* Check that all rules were updated and at the same time find the max timestamp. We assume UNKNOWN_MTIME is newer then any other value. */ for (f = file->double_colon; f != 0 && f->updated; f = f->prev) if (max_mtime != UNKNOWN_MTIME && (f->last_mtime == UNKNOWN_MTIME || f->last_mtime > max_mtime)) max_mtime = f->last_mtime; if (f == 0) for (f = file->double_colon; f != 0; f = f->prev) f->last_mtime = max_mtime; } if (ran && file->update_status != us_none) #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET { #endif /* We actually tried to update FILE, which has updated its also_make's as well (if it worked). If it didn't work, it wouldn't work again for them. So mark them as updated with the same status. */ for (d = file->also_make; d != 0; d = d->next) { d->file->command_state = cs_finished; d->file->updated = 1; d->file->update_status = file->update_status; if (ran && !d->file->phony) /* Fetch the new modification time. We do this instead of just invalidating the cached time so that a vpath_search can happen. Otherwise, it would never be done because the target is already updated. */ f_mtime (d->file, 0); } #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET /* Same as above but for explicit multi target rules. */ if (file->multi_head) for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next) { f2->update_status = file->update_status; if (!f2->phony) f_mtime (f2, 0); } } #endif else if (file->update_status == us_none) #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET { /* Nothing was done for FILE, but it needed nothing done. So mark it now as "succeeded". */ file->update_status = 0; if (file->multi_head) for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next) f2->update_status = 0; } #else /* Nothing was done for FILE, but it needed nothing done. So mark it now as "succeeded". */ file->update_status = us_success; #endif #ifdef CONFIG_WITH_MEMORY_OPTIMIZATIONS /* We're done with this command, so free the memory held by the chopped command lines. Saves heap for the compilers & linkers. */ if (file->cmds && file->cmds->command_lines) free_chopped_commands (file->cmds); #endif } /* Check whether another file (whose mtime is THIS_MTIME) needs updating on account of a dependency which is file FILE. If it does, store 1 in *MUST_MAKE_PTR. In the process, update any non-intermediate files that FILE depends on (including FILE itself). Return nonzero if any updating failed. */ static enum update_status check_dep (struct file *file, unsigned int depth, FILE_TIMESTAMP this_mtime, int *must_make_ptr) { struct file *ofile; struct dep *d; enum update_status dep_status = us_success; ++depth; start_updating (file); /* We might change file if we find a different one via vpath; remember this one to turn off updating. */ ofile = file; if (file->phony || !file->intermediate) { /* If this is a non-intermediate file, update it and record whether it is newer than THIS_MTIME. */ FILE_TIMESTAMP mtime; dep_status = update_file (file, depth); check_renamed (file); mtime = file_mtime (file); check_renamed (file); if (mtime == NONEXISTENT_MTIME || mtime > this_mtime) *must_make_ptr = 1; #ifdef CONFIG_WITH_DOT_IS_CHANGED else if ( *must_make_ptr == 0 && call_is_changed_target_var (file)) *must_make_ptr = 1; #endif /* CONFIG_WITH_DOT_IS_CHANGED */ } else { /* FILE is an intermediate file. */ FILE_TIMESTAMP mtime; if (!file->phony && file->cmds == 0 && !file->tried_implicit) { if (try_implicit_rule (file, depth)) DBF (DB_IMPLICIT, _("Found an implicit rule for '%s'.\n")); else DBF (DB_IMPLICIT, _("No implicit rule found for '%s'.\n")); file->tried_implicit = 1; } if (file->cmds == 0 && !file->is_target && default_file != 0 && default_file->cmds != 0) { DBF (DB_IMPLICIT, _("Using default commands for '%s'.\n")); file->cmds = default_file->cmds; } check_renamed (file); mtime = file_mtime (file); check_renamed (file); if (mtime != NONEXISTENT_MTIME && mtime > this_mtime) /* If the intermediate file actually exists and is newer, then we should remake from it. */ *must_make_ptr = 1; else { /* Otherwise, update all non-intermediate files we depend on, if necessary, and see whether any of them is more recent than the file on whose behalf we are checking. */ struct dep *ld; int deps_running = 0; /* If this target is not running, set it's state so that we check it fresh. It could be it was checked as part of an order-only prerequisite and so wasn't rebuilt then, but should be now. */ if (file->command_state != cs_running) { /* If the target was waiting for a dependency it has to be reconsidered, as that dependency might have finished. */ if (file->command_state == cs_deps_running) file->considered = 0; set_command_state (file, cs_not_started); } ld = 0; d = file->deps; while (d != 0) { enum update_status new; int maybe_make; if (is_updating (d->file)) { OSS (error, NILF, _("Circular %s <- %s dependency dropped."), file->name, d->file->name); if (ld == 0) { file->deps = d->next; free_dep (d); d = file->deps; } else { ld->next = d->next; free_dep (d); d = ld->next; } continue; } d->file->parent = file; maybe_make = *must_make_ptr; new = check_dep (d->file, depth, this_mtime, &maybe_make); if (new > dep_status) dep_status = new; if (! d->ignore_mtime) *must_make_ptr = maybe_make; check_renamed (d->file); if (dep_status && !keep_going_flag) break; if (d->file->command_state == cs_running || d->file->command_state == cs_deps_running) deps_running = 1; ld = d; d = d->next; } if (deps_running) /* Record that some of FILE's deps are still being made. This tells the upper levels to wait on processing it until the commands are finished. */ set_command_state (file, cs_deps_running); } } finish_updating (file); finish_updating (ofile); return dep_status; } /* Touch FILE. Return us_success if successful, us_failed if not. */ #define TOUCH_ERROR(call) do{ perror_with_name ((call), file->name); \ return us_failed; }while(0) static enum update_status touch_file (struct file *file) { if (!silent_flag) OS (message, 0, "touch %s", file->name); /* Print-only (-n) takes precedence over touch (-t). */ if (just_print_flag) return us_success; #ifndef NO_ARCHIVES if (ar_name (file->name)) return ar_touch (file->name) ? us_failed : us_success; else #endif { int fd; EINTRLOOP (fd, open (file->name, O_RDWR | O_CREAT, 0666)); if (fd < 0) TOUCH_ERROR ("touch: open: "); else { struct stat statbuf; char buf = 'x'; int e; EINTRLOOP (e, fstat (fd, &statbuf)); if (e < 0) TOUCH_ERROR ("touch: fstat: "); /* Rewrite character 0 same as it already is. */ EINTRLOOP (e, read (fd, &buf, 1)); if (e < 0) TOUCH_ERROR ("touch: read: "); { off_t o; EINTRLOOP (o, lseek (fd, 0L, 0)); if (o < 0L) TOUCH_ERROR ("touch: lseek: "); } EINTRLOOP (e, write (fd, &buf, 1)); if (e < 0) TOUCH_ERROR ("touch: write: "); /* If file length was 0, we just changed it, so change it back. */ if (statbuf.st_size == 0) { (void) close (fd); EINTRLOOP (fd, open (file->name, O_RDWR | O_TRUNC, 0666)); if (fd < 0) TOUCH_ERROR ("touch: open: "); } (void) close (fd); } } return us_success; } /* Having checked and updated the dependencies of FILE, do whatever is appropriate to remake FILE itself. Return the status from executing FILE's commands. */ static void remake_file (struct file *file) { #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET assert(file->multi_head == NULL || file->multi_head == file); #endif if (file->cmds == 0) { if (file->phony) /* Phony target. Pretend it succeeded. */ file->update_status = us_success; else if (file->is_target) /* This is a nonexistent target file we cannot make. Pretend it was successfully remade. */ file->update_status = us_success; else { /* This is a dependency file we cannot remake. Fail. */ if (!rebuilding_makefiles || !file->dontcare) complain (file); file->update_status = us_failed; } } else { chop_commands (file->cmds); /* The normal case: start some commands. */ if (!touch_flag || file->cmds->any_recurse) { execute_file_commands (file); return; } /* This tells notice_finished_file it is ok to touch the file. */ file->update_status = us_success; } /* This does the touching under -t. */ notice_finished_file (file); } /* Return the mtime of a file, given a 'struct file'. Caches the time in the struct file to avoid excess stat calls. If the file is not found, and SEARCH is nonzero, VPATH searching and replacement is done. If that fails, a library (-lLIBNAME) is tried and the library's actual name (/lib/libLIBNAME.a, etc.) is substituted into FILE. */ FILE_TIMESTAMP f_mtime (struct file *file, int search) { FILE_TIMESTAMP mtime; int propagate_timestamp; /* File's mtime is not known; must get it from the system. */ #ifndef NO_ARCHIVES if (ar_name (file->name)) { /* This file is an archive-member reference. */ char *arname, *memname; struct file *arfile; time_t member_date; /* Find the archive's name. */ ar_parse_name (file->name, &arname, &memname); /* Find the modification time of the archive itself. Also allow for its name to be changed via VPATH search. */ arfile = lookup_file (arname); if (arfile == 0) arfile = enter_file (strcache_add (arname)); mtime = f_mtime (arfile, search); check_renamed (arfile); if (search && strcmp (arfile->hname, arname)) { /* The archive's name has changed. Change the archive-member reference accordingly. */ char *name; unsigned int arlen, memlen; arlen = strlen (arfile->hname); memlen = strlen (memname); name = alloca (arlen + 1 + memlen + 2); memcpy (name, arfile->hname, arlen); name[arlen] = '('; memcpy (name + arlen + 1, memname, memlen); name[arlen + 1 + memlen] = ')'; name[arlen + 1 + memlen + 1] = '\0'; /* If the archive was found with GPATH, make the change permanent; otherwise defer it until later. */ if (arfile->name == arfile->hname) rename_file (file, strcache_add (name)); else rehash_file (file, strcache_add (name)); check_renamed (file); } free (arname); file->low_resolution_time = 1; if (mtime == NONEXISTENT_MTIME) /* The archive doesn't exist, so its members don't exist either. */ return NONEXISTENT_MTIME; member_date = ar_member_date (file->hname); mtime = (member_date == (time_t) -1 ? NONEXISTENT_MTIME : file_timestamp_cons (file->hname, member_date, 0)); } else #endif { mtime = name_mtime (file->name); if (mtime == NONEXISTENT_MTIME && search && !file->ignore_vpath) { /* If name_mtime failed, search VPATH. */ const char *name = vpath_search (file->name, &mtime, NULL, NULL); if (name /* Last resort, is it a library (-lxxx)? */ || (file->name[0] == '-' && file->name[1] == 'l' && (name = library_search (file->name, &mtime)) != 0)) { int name_len; if (mtime != UNKNOWN_MTIME) /* vpath_search and library_search store UNKNOWN_MTIME if they didn't need to do a stat call for their work. */ file->last_mtime = mtime; /* If we found it in VPATH, see if it's in GPATH too; if so, change the name right now; if not, defer until after the dependencies are updated. */ #ifndef VMS name_len = strlen (name) - strlen (file->name) - 1; #else name_len = strlen (name) - strlen (file->name); if (name[name_len - 1] == '/') name_len--; #endif if (gpath_search (name, name_len)) { rename_file (file, name); check_renamed (file); return file_mtime (file); } rehash_file (file, name); check_renamed (file); /* If the result of a vpath search is -o or -W, preserve it. Otherwise, find the mtime of the resulting file. */ if (mtime != OLD_MTIME && mtime != NEW_MTIME) mtime = name_mtime (name); } } } /* Files can have bogus timestamps that nothing newly made will be "newer" than. Updating their dependents could just result in loops. So notify the user of the anomaly with a warning. We only need to do this once, for now. */ if (!clock_skew_detected && mtime != NONEXISTENT_MTIME && mtime != NEW_MTIME && !file->updated) { static FILE_TIMESTAMP adjusted_now; FILE_TIMESTAMP adjusted_mtime = mtime; #if defined(WINDOWS32) || defined(__MSDOS__) /* Experimentation has shown that FAT filesystems can set file times up to 3 seconds into the future! Play it safe. */ #define FAT_ADJ_OFFSET (FILE_TIMESTAMP) 3 FILE_TIMESTAMP adjustment = FAT_ADJ_OFFSET << FILE_TIMESTAMP_LO_BITS; if (ORDINARY_MTIME_MIN + adjustment <= adjusted_mtime) adjusted_mtime -= adjustment; #elif defined(__EMX__) /* FAT filesystems round time to the nearest even second! Allow for any file (NTFS or FAT) to perhaps suffer from this brain damage. */ FILE_TIMESTAMP adjustment = (((FILE_TIMESTAMP_S (adjusted_mtime) & 1) == 0 && FILE_TIMESTAMP_NS (adjusted_mtime) == 0) ? (FILE_TIMESTAMP) 1 << FILE_TIMESTAMP_LO_BITS : 0); #endif /* If the file's time appears to be in the future, update our concept of the present and try once more. */ if (adjusted_now < adjusted_mtime) { int resolution; FILE_TIMESTAMP now = file_timestamp_now (&resolution); adjusted_now = now + (resolution - 1); if (adjusted_now < adjusted_mtime) { #ifdef NO_FLOAT OS (error, NILF, _("Warning: File '%s' has modification time in the future"), file->name); #else double from_now = (FILE_TIMESTAMP_S (mtime) - FILE_TIMESTAMP_S (now) + ((FILE_TIMESTAMP_NS (mtime) - FILE_TIMESTAMP_NS (now)) / 1e9)); char from_now_string[100]; if (from_now >= 99 && from_now <= ULONG_MAX) sprintf (from_now_string, "%lu", (unsigned long) from_now); else sprintf (from_now_string, "%.2g", from_now); OSS (error, NILF, _("Warning: File '%s' has modification time %s s in the future"), file->name, from_now_string); #endif clock_skew_detected = 1; } } } /* Store the mtime into all the entries for this file for which it is safe to do so: avoid propagating timestamps to double-colon rules that haven't been examined so they're run or not based on the pre-update timestamp. */ if (file->double_colon) file = file->double_colon; propagate_timestamp = file->updated; do { /* If this file is not implicit but it is intermediate then it was made so by the .INTERMEDIATE target. If this file has never been built by us but was found now, it existed before make started. So, turn off the intermediate bit so make doesn't delete it, since it didn't create it. */ if (mtime != NONEXISTENT_MTIME && file->command_state == cs_not_started && !file->tried_implicit && file->intermediate) file->intermediate = 0; if (file->updated == propagate_timestamp) file->last_mtime = mtime; file = file->prev; } while (file != 0); return mtime; } /* Return the mtime of the file or archive-member reference NAME. */ /* First, we check with stat(). If the file does not exist, then we return NONEXISTENT_MTIME. If it does, and the symlink check flag is set, then examine each indirection of the symlink and find the newest mtime. This causes one duplicate stat() when -L is being used, but the code is much cleaner. */ static FILE_TIMESTAMP name_mtime (const char *name) { FILE_TIMESTAMP mtime; struct stat st; int e; #if defined(KMK) && defined(KBUILD_OS_WINDOWS) extern int stat_only_mtime(const char *pszPath, struct stat *pStat); e = stat_only_mtime (name, &st); #else EINTRLOOP (e, stat (name, &st)); #endif if (e == 0) mtime = FILE_TIMESTAMP_STAT_MODTIME (name, st); else if (errno == ENOENT || errno == ENOTDIR) mtime = NONEXISTENT_MTIME; else { perror_with_name ("stat: ", name); return NONEXISTENT_MTIME; } /* If we get here we either found it, or it doesn't exist. If it doesn't exist see if we can use a symlink mtime instead. */ #ifdef MAKE_SYMLINKS #ifndef S_ISLNK # define S_ISLNK(_m) (((_m)&S_IFMT)==S_IFLNK) #endif if (check_symlink_flag) { PATH_VAR (lpath); /* Check each symbolic link segment (if any). Find the latest mtime amongst all of them (and the target file of course). Note that we have already successfully dereferenced all the links above. So, if we run into any error trying to lstat(), or readlink(), or whatever, something bizarre-o happened. Just give up and use whatever mtime we've already computed at that point. */ strcpy (lpath, name); while (1) { FILE_TIMESTAMP ltime; PATH_VAR (lbuf); long llen; char *p; EINTRLOOP (e, lstat (lpath, &st)); if (e) { /* Just take what we have so far. */ if (errno != ENOENT && errno != ENOTDIR) perror_with_name ("lstat: ", lpath); break; } /* If this is not a symlink, we're done (we started with the real file's mtime so we don't need to test it again). */ if (!S_ISLNK (st.st_mode)) break; /* If this mtime is newer than what we had, keep the new one. */ ltime = FILE_TIMESTAMP_STAT_MODTIME (lpath, st); if (ltime > mtime) mtime = ltime; /* Set up to check the file pointed to by this link. */ EINTRLOOP (llen, readlink (lpath, lbuf, GET_PATH_MAX)); if (llen < 0) { /* Eh? Just take what we have. */ perror_with_name ("readlink: ", lpath); break; } lbuf[llen] = '\0'; /* If the target is fully-qualified or the source is just a filename, then the new path is the target. Otherwise it's the source directory plus the target. */ if (lbuf[0] == '/' || (p = strrchr (lpath, '/')) == NULL) strcpy (lpath, lbuf); else if ((p - lpath) + llen + 2 > GET_PATH_MAX) /* Eh? Path too long! Again, just go with what we have. */ break; else /* Create the next step in the symlink chain. */ strcpy (p+1, lbuf); } } #endif return mtime; } /* Search for a library file specified as -lLIBNAME, searching for a suitable library file in the system library directories and the VPATH directories. */ static const char * library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr) { static const char *dirs[] = { #ifdef KMK ".", #else /* !KMK */ #ifndef _AMIGA "/lib", "/usr/lib", #endif #if defined(WINDOWS32) && !defined(LIBDIR) /* * This is completely up to the user at product install time. Just define * a placeholder. */ #define LIBDIR "." #endif # ifdef LIBDIR /* bird */ LIBDIR, /* Defined by configuration. */ # else /* bird */ ".", /* bird */ # endif /* bird */ #endif /* !KMK */ 0 }; const char *file = 0; char *libpatterns; FILE_TIMESTAMP mtime; /* Loop variables for the libpatterns value. */ char *p; const char *p2; unsigned int len; unsigned int liblen; /* Information about the earliest (in the vpath sequence) match. */ unsigned int best_vpath = 0, best_path = 0; const char **dp; libpatterns = xstrdup (variable_expand ("$(.LIBPATTERNS)")); /* Skip the '-l'. */ lib += 2; liblen = strlen (lib); /* Loop through all the patterns in .LIBPATTERNS, and search on each one. To implement the linker-compatible behavior we have to search through all entries in .LIBPATTERNS and choose the "earliest" one. */ p2 = libpatterns; while ((p = find_next_token (&p2, &len)) != 0) { static char *buf = NULL; static unsigned int buflen = 0; static int libdir_maxlen = -1; static unsigned int std_dirs = 0; char *libbuf = variable_expand (""); const size_t libbuf_offset = libbuf - variable_buffer; /* bird */ /* Expand the pattern using LIB as a replacement. */ { char c = p[len]; char *p3, *p4; p[len] = '\0'; p3 = find_percent (p); if (!p3) { /* Give a warning if there is no pattern. */ OS (error, NILF, _(".LIBPATTERNS element '%s' is not a pattern"), p); p[len] = c; continue; } p4 = variable_buffer_output (libbuf, p, p3-p); p4 = variable_buffer_output (p4, lib, liblen); p4 = variable_buffer_output (p4, p3+1, len - (p3-p)); p[len] = c; libbuf = variable_buffer + libbuf_offset; /* bird - variable_buffer may have been reallocated. UPSTREAM */ } /* Look first for 'libNAME.a' in the current directory. */ mtime = name_mtime (libbuf); if (mtime != NONEXISTENT_MTIME) { if (mtime_ptr != 0) *mtime_ptr = mtime; file = strcache_add (libbuf); /* This by definition will have the best index, so stop now. */ break; } /* Now try VPATH search on that. */ { unsigned int vpath_index, path_index; const char* f = vpath_search (libbuf, mtime_ptr ? &mtime : NULL, &vpath_index, &path_index); if (f) { /* If we have a better match, record it. */ if (file == 0 || vpath_index < best_vpath || (vpath_index == best_vpath && path_index < best_path)) { file = f; best_vpath = vpath_index; best_path = path_index; if (mtime_ptr != 0) *mtime_ptr = mtime; } } } /* Now try the standard set of directories. */ if (!buflen) { for (dp = dirs; *dp != 0; ++dp) { int l = strlen (*dp); if (l > libdir_maxlen) libdir_maxlen = l; std_dirs++; } buflen = strlen (libbuf); buf = xmalloc (libdir_maxlen + buflen + 2); } else if (buflen < strlen (libbuf)) { buflen = strlen (libbuf); buf = xrealloc (buf, libdir_maxlen + buflen + 2); } { /* Use the last std_dirs index for standard directories. This was it will always be greater than the VPATH index. */ unsigned int vpath_index = ~((unsigned int)0) - std_dirs; for (dp = dirs; *dp != 0; ++dp) { sprintf (buf, "%s/%s", *dp, libbuf); mtime = name_mtime (buf); if (mtime != NONEXISTENT_MTIME) { if (file == 0 || vpath_index < best_vpath) { file = strcache_add (buf); best_vpath = vpath_index; if (mtime_ptr != 0) *mtime_ptr = mtime; } } vpath_index++; } } } free (libpatterns); return file; } kbuild-3686/src/kmk/testcase-which.kmk0000664000175000017500000000011615053010076017677 0ustar locutuslocutus all: @echo which kmk: $(which kmk) @echo which kmk: $(which kmk kmk kmk ) kbuild-3686/src/kmk/testcase-stack.kmk0000664000175000017500000000545715053010075017716 0ustar locutuslocutus# $Id: testcase-stack.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild - testcase for the functions. # # # Copyright (c) 2007-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild 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 3 of the License, or # (at your option) any later version. # # kBuild 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 kBuild. If not, see # # DEPTH = ../.. include $(PATH_KBUILD)/header.kmk ifneq ($(not 1),) $(error The 'not' function is missing) endif ifneq ($(eq 1,1),1) $(error The 'eq' function is missing) endif ASSERT1 = $(if $(not $(eq $(STACK1),$(1))),$(error failure: STACK1:='$(STACK1)' expected='$(1)')) $(call stack-push,STACK1,1) $(call ASSERT,1) $(call stack-push,STACK1,2) $(call ASSERT,1 2) $(call stack-push,STACK1,3) $(call ASSERT,1 2 3) $(call stack-push,STACK1,4) $(call ASSERT,1 2 3 4) $(call stack-push,STACK1,5) $(call ASSERT,1 2 3 4 5) $(call stack-popv,STACK1) $(call ASSERT,1 2 3 4) $(call stack-push,STACK1,5) $(call ASSERT,1 2 3 4 5) $(call stack-popv,STACK1) $(call ASSERT,1 2 3 4) $(call stack-popv,STACK1) $(call ASSERT,1 2 3) $(call stack-push,STACK1,4) $(call ASSERT,1 2 3 4) $(call stack-push,STACK1,5) $(call ASSERT,1 2 3 4 5) top := $(call stack-top,STACK1) $(if $(not $(eq $(top),5)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='5')) $(call ASSERT,1 2 3 4 5) top := $(call stack-pop,STACK1) $(if $(not $(eq $(top),5)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='5')) $(call ASSERT,1 2 3 4) top := $(call stack-pop,STACK1) $(if $(not $(eq $(top),4)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='4')) $(call ASSERT,1 2 3) top := $(call stack-pop,STACK1) $(if $(not $(eq $(top),3)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='3')) $(call ASSERT,1 2) top := $(call stack-pop,STACK1) $(if $(not $(eq $(top),2)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='2')) $(call ASSERT,1) top := $(call stack-top,STACK1) $(if $(not $(eq $(top),1)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='1')) $(call ASSERT,1) top := $(call stack-pop,STACK1) $(if $(not $(eq $(top),1)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='1')) $(call ASSERT,) top := $(call stack-pop,STACK1) $(if $(not $(eq $(top),)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='')) $(call ASSERT,) all_recursive: $(ECHO) The stack works.$(STACK1) kbuild-3686/src/kmk/NMakefile.template0000664000175000017500000001017215053010075017652 0ustar locutuslocutus# -*-Makefile-*- to build GNU make with nmake # # NOTE: If you have no 'make' program at all to process this makefile, # run 'build_w32.bat' instead. # # Copyright (C) 1996-2016 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) any later # version. # # GNU Make 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, see . LINK = link CC = cl MAKE = nmake OUTDIR=. MAKEFILE=NMakefile SUBPROC_MAKEFILE=NMakefile CFLAGS_any = /nologo /MT /W4 /GX /Zi /YX /I . /I glob /I w32/include /D WIN32 /D WINDOWS32 /D _CONSOLE /D HAVE_CONFIG_H CFLAGS_debug = $(CFLAGS_any) /Od /D DEBUG /D _DEBUG /FR.\WinDebug/ /Fp.\WinDebug/make.pch /Fo.\WinDebug/ /Fd.\WinDebug/make.pdb CFLAGS_release = $(CFLAGS_any) /O2 /D NDEBUG /FR.\WinRel/ /Fp.\WinRel/make.pch /Fo.\WinRel/ LDFLAGS_debug = w32\subproc\WinDebug\subproc.lib /NOLOGO /SUBSYSTEM:console\ /STACK:0x400000 /INCREMENTAL:no /PDB:WinDebug/make.pdb /OUT:WinDebug/make.exe /DEBUG LDFLAGS_release = w32\subproc\WinRel\subproc.lib /NOLOGO /SUBSYSTEM:console\ /STACK:0x400000 /INCREMENTAL:no /OUT:WinRel/make.exe all: config.h subproc Release Debug # # Make sure we build the subproc library first. It has it's own # makefile. To be portable to Windows 95, we put the instructions # on how to build the library into a batch file. On NT, we could # simply have done foo && bar && dog, but this doesn't port. # subproc: w32/subproc/WinDebug/subproc.lib w32/subproc/WinRel/subproc.lib w32/subproc/WinDebug/subproc.lib w32/subproc/WinRel/subproc.lib: w32/subproc/misc.c w32/subproc/sub_proc.c w32/subproc/w32err.c subproc.bat $(SUBPROC_MAKEFILE) $(MAKE) if exist WinDebug\make.exe erase WinDebug\make.exe if exist WinRel\make.exe erase WinRel\make.exe config.h: config.h.W32 copy $? $@ Release: $(MAKE) /f $(MAKEFILE) LDFLAGS="$(LDFLAGS_release)" CFLAGS="$(CFLAGS_release)" OUTDIR=WinRel WinRel/make.exe Debug: $(MAKE) /f $(MAKEFILE) LDFLAGS="$(LDFLAGS_debug)" CFLAGS="$(CFLAGS_debug)" OUTDIR=WinDebug WinDebug/make.exe clean: if exist WinDebug\nul rmdir /s /q WinDebug if exist WinRel\nul rmdir /s /q WinRel if exist w32\subproc\WinDebug\nul rmdir /s /q w32\subproc\WinDebug if exist w32\subproc\WinRel\nul rmdir /s /q w32\subproc\WinRel if exist config.h erase config.h erase *.pdb $(OUTDIR): if not exist .\$@\nul mkdir .\$@ LIBS = kernel32.lib user32.lib advapi32.lib guile = $(OUTDIR)/guile.obj OBJS = \ $(OUTDIR)/ar.obj \ $(OUTDIR)/arscan.obj \ $(OUTDIR)/commands.obj \ $(OUTDIR)/default.obj \ $(OUTDIR)/dir.obj \ $(OUTDIR)/expand.obj \ $(OUTDIR)/file.obj \ $(OUTDIR)/function.obj \ $(OUTDIR)/getloadavg.obj \ $(OUTDIR)/getopt.obj \ $(OUTDIR)/getopt1.obj \ $(OUTDIR)/hash.obj \ $(OUTDIR)/implicit.obj \ $(OUTDIR)/job.obj \ $(OUTDIR)/load.obj \ $(OUTDIR)/main.obj \ $(OUTDIR)/misc.obj \ $(OUTDIR)/output.obj \ $(OUTDIR)/read.obj \ $(OUTDIR)/remake.obj \ $(OUTDIR)/remote-stub.obj \ $(OUTDIR)/rule.obj \ $(OUTDIR)/signame.obj \ $(OUTDIR)/strcache.obj \ $(OUTDIR)/variable.obj \ $(OUTDIR)/version.obj \ $(OUTDIR)/vpath.obj \ $(OUTDIR)/glob.obj \ $(OUTDIR)/fnmatch.obj \ $(OUTDIR)/dirent.obj \ $(OUTDIR)/pathstuff.obj \ $(OUTDIR)/posixfcn.obj \ $(OUTDIR)/w32os.obj \ $(guile) $(OUTDIR)/make.exe: $(OUTDIR) $(OBJS) $(LINK) @<< $(LDFLAGS) $(LIBS) $(OBJS) << .c{$(OUTDIR)}.obj: $(CC) $(CFLAGS) /c $< $(OUTDIR)/glob.obj : glob/glob.c $(CC) $(CFLAGS) /c $? $(OUTDIR)/fnmatch.obj : glob/fnmatch.c $(CC) $(CFLAGS) /c $? $(OUTDIR)/dirent.obj : w32/compat/dirent.c $(CC) $(CFLAGS) /c $? $(OUTDIR)/posixfcn.obj : w32/compat/posixfcn.c $(CC) $(CFLAGS) /c $? $(OUTDIR)/pathstuff.obj : w32/pathstuff.c $(CC) $(CFLAGS) /c $? $(OUTDIR)/w32os.obj : w32/w32os.c $(CC) $(CFLAGS) /c $? kbuild-3686/src/kmk/vmsdir.h0000664000175000017500000000326415053010075015743 0ustar locutuslocutus/* dirent.h for vms Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #ifndef VMSDIR_H #define VMSDIR_H #include #define MAXNAMLEN 255 #ifndef __DECC #if !defined (__GNUC__) && !defined (__ALPHA) typedef unsigned long u_long; typedef unsigned short u_short; #endif #endif struct direct { off_t d_off; u_long d_fileno; u_short d_reclen; u_short d_namlen; char d_name[MAXNAMLEN + 1]; }; #undef DIRSIZ #define DIRSIZ(dp) \ (((sizeof (struct direct) \ - (MAXNAMLEN+1) \ + ((dp)->d_namlen+1)) \ + 3) & ~3) #define d_ino d_fileno /* compatibility */ /* * Definitions for library routines operating on directories. */ typedef struct DIR { struct direct dir; char d_result[MAXNAMLEN + 1]; #if defined (__ALPHA) || defined (__DECC) struct FAB fab; #else struct fabdef fab; #endif } DIR; #ifndef NULL #define NULL 0 #endif #define rewinddir(dirp) seekdir((dirp), (long)0) DIR *opendir (); struct direct *readdir (DIR *dfd); int closedir (DIR *dfd); const char *vmsify (const char *name, int type); #endif /* VMSDIR_H */ kbuild-3686/src/kmk/build_w32.bat0000664000175000017500000001676715053010075016564 0ustar locutuslocutus@echo off rem Copyright (C) 1996-2016 Free Software Foundation, Inc. rem This file is part of GNU Make. rem rem GNU Make is free software; you can redistribute it and/or modify it under rem the terms of the GNU General Public License as published by the Free rem Software Foundation; either version 3 of the License, or (at your option) rem any later version. rem rem GNU Make is distributed in the hope that it will be useful, but WITHOUT rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. rem more details. rem rem You should have received a copy of the GNU General Public License along rem with this program. If not, see . call :Reset if "%1" == "-h" goto Usage if "%1" == "--help" goto Usage set MAKE=gnumake set GUILE=Y set COMPILER=msvc :ParseSW if "%1" == "--debug" goto SetDebug if "%1" == "--without-guile" goto NoGuile if "%1" == "gcc" goto SetCC if "%1" == "" goto DoneSW :SetDebug set DEBUG=Y shift goto ParseSW :NoGuile set GUILE=N echo Building without Guile shift goto ParseSW :SetCC set COMPILER=gcc echo Building with GCC shift goto ParseSW rem Build with Guile is supported only on NT and later versions :DoneSW echo. echo Creating GNU Make for Windows 9X/NT/2K/XP/Vista/7/8 if "%DEBUG%" == "Y" echo Building without compiler optimizations if "%COMPILER%" == "gcc" goto GccBuild set OUTDIR=.\WinRel set "OPTS=/O2 /D NDEBUG" set LINKOPTS= if "%DEBUG%" == "Y" set OUTDIR=.\WinDebug if "%DEBUG%" == "Y" set "OPTS=/Zi /Od /D _DEBUG" if "%DEBUG%" == "Y" set LINKOPTS=/DEBUG call :Build goto Done :GccBuild set OUTDIR=.\GccRel set OPTS=-O2 if "%DEBUG%" == "Y" set OPTS=-O0 if "%DEBUG%" == "Y" set OUTDIR=.\GccDebug call :Build goto Done :Done call :Reset goto :EOF :Build :: Clean the directory if it exists if exist %OUTDIR%\nul rmdir /S /Q %OUTDIR% :: Recreate it mkdir %OUTDIR% mkdir %OUTDIR%\glob mkdir %OUTDIR%\w32 mkdir %OUTDIR%\w32\compat mkdir %OUTDIR%\w32\subproc if "%GUILE%" == "Y" call :ChkGuile echo. echo Compiling %OUTDIR% version if exist config.h.W32.template call :ConfigSCM copy config.h.W32 %OUTDIR%\config.h call :Compile ar call :Compile arscan call :Compile commands call :Compile default call :Compile dir call :Compile expand call :Compile file call :Compile function call :Compile getloadavg call :Compile getopt call :Compile getopt1 call :Compile glob\fnmatch call :Compile glob\glob call :Compile guile GUILE call :Compile hash call :Compile implicit call :Compile job call :Compile load call :Compile loadapi call :Compile main GUILE call :Compile misc call :Compile output call :Compile read call :Compile remake call :Compile remote-stub call :Compile rule call :Compile signame call :Compile strcache call :Compile variable call :Compile version call :Compile vpath call :Compile w32\compat\posixfcn call :Compile w32\pathstuff call :Compile w32\subproc\misc call :Compile w32\subproc\sub_proc call :Compile w32\subproc\w32err call :Compile w32\w32os if not "%COMPILER%" == "gcc" call :Compile w32\compat\dirent call :Link echo. if not exist %OUTDIR%\%MAKE%.exe echo %OUTDIR% build FAILED! if exist %OUTDIR%\%MAKE%.exe echo %OUTDIR% build succeeded. goto :EOF :Compile set EXTRAS= if "%2" == "GUILE" set "EXTRAS=%GUILECFLAGS%" if "%COMPILER%" == "gcc" goto GccCompile :: MSVC Compile echo on cl.exe /nologo /MT /W4 /EHsc %OPTS% /I %OUTDIR% /I . /I glob /I w32/include /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR%OUTDIR% /Fp%OUTDIR%\%MAKE%.pch /Fo%OUTDIR%\%1.obj /Fd%OUTDIR%\%MAKE%.pdb %EXTRAS% /c %1.c @echo off echo %OUTDIR%\%1.obj >>%OUTDIR%\link.sc goto :EOF :GccCompile :: GCC Compile echo on gcc -mthreads -Wall -std=gnu99 -gdwarf-2 -g3 %OPTS% -I%OUTDIR% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H %EXTRAS% -o %OUTDIR%\%1.o -c %1.c @echo off goto :EOF :Link echo Linking %OUTDIR%/%MAKE%.exe if "%COMPILER%" == "gcc" goto GccLink :: MSVC Link echo %GUILELIBS% kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib >>%OUTDIR%\link.sc echo on link.exe /NOLOGO /SUBSYSTEM:console /PDB:%OUTDIR%\%MAKE%.pdb %LINKOPTS% /OUT:%OUTDIR%\%MAKE%.exe @%OUTDIR%\link.sc @echo off goto :EOF :GccLink :: GCC Link echo on gcc -mthreads -gdwarf-2 -g3 -o %OUTDIR%\%MAKE%.exe %OUTDIR%\variable.o %OUTDIR%\rule.o %OUTDIR%\remote-stub.o %OUTDIR%\commands.o %OUTDIR%\file.o %OUTDIR%\getloadavg.o %OUTDIR%\default.o %OUTDIR%\signame.o %OUTDIR%\expand.o %OUTDIR%\dir.o %OUTDIR%\main.o %OUTDIR%\getopt1.o %OUTDIR%\guile.o %OUTDIR%\job.o %OUTDIR%\output.o %OUTDIR%\read.o %OUTDIR%\version.o %OUTDIR%\getopt.o %OUTDIR%\arscan.o %OUTDIR%\remake.o %OUTDIR%\misc.o %OUTDIR%\hash.o %OUTDIR%\strcache.o %OUTDIR%\ar.o %OUTDIR%\function.o %OUTDIR%\vpath.o %OUTDIR%\implicit.o %OUTDIR%\loadapi.o %OUTDIR%\load.o %OUTDIR%\glob\glob.o %OUTDIR%\glob\fnmatch.o %OUTDIR%\w32\pathstuff.o %OUTDIR%\w32\compat\posixfcn.o %OUTDIR%\w32\w32os.o %OUTDIR%\w32\subproc\misc.o %OUTDIR%\w32\subproc\sub_proc.o %OUTDIR%\w32\subproc\w32err.o %GUILELIBS% -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -Wl,--out-implib=%OUTDIR%\libgnumake-1.dll.a @echo off goto :EOF :ConfigSCM echo Generating config from SCM templates sed -n "s/^AC_INIT(\[GNU make\],\[\([^]]\+\)\].*/s,%%VERSION%%,\1,g/p" configure.ac > %OUTDIR%\config.h.W32.sed echo s,%%PACKAGE%%,make,g >> %OUTDIR%\config.h.W32.sed sed -f %OUTDIR%\config.h.W32.sed config.h.W32.template > config.h.W32 echo static const char *const GUILE_module_defn = ^" \> gmk-default.h sed -e "s/;.*//" -e "/^[ \t]*$/d" -e "s/\"/\\\\\"/g" -e "s/$/ \\\/" gmk-default.scm >> gmk-default.h echo ^";>> gmk-default.h goto :EOF :ChkGuile if not "%OS%" == "Windows_NT" goto NoGuile pkg-config --help > %OUTDIR%\guile.tmp 2> NUL if ERRORLEVEL 1 goto NoPkgCfg echo Checking for Guile 2.0 if not "%COMPILER%" == "gcc" set PKGMSC=--msvc-syntax pkg-config --cflags --short-errors "guile-2.0" > %OUTDIR%\guile.tmp if not ERRORLEVEL 1 set /P GUILECFLAGS= < %OUTDIR%\guile.tmp pkg-config --libs --static --short-errors %PKGMSC% "guile-2.0" > %OUTDIR%\guile.tmp if not ERRORLEVEL 1 set /P GUILELIBS= < %OUTDIR%\guile.tmp if not "%GUILECFLAGS%" == "" goto GuileDone echo Checking for Guile 1.8 pkg-config --cflags --short-errors "guile-1.8" > %OUTDIR%\guile.tmp if not ERRORLEVEL 1 set /P GUILECFLAGS= < %OUTDIR%\guile.tmp pkg-config --libs --static --short-errors %PKGMSC% "guile-1.8" > %OUTDIR%\guile.tmp if not ERRORLEVEL 1 set /P GUILELIBS= < %OUTDIR%\guile.tmp if not "%GUILECFLAGS%" == "" goto GuileDone echo No Guile found, building without Guile goto GuileDone :NoPkgCfg echo pkg-config not found, building without Guile :GuileDone if "%GUILECFLAGS%" == "" goto :EOF echo Guile found, building with Guile set "GUILECFLAGS=%GUILECFLAGS% -DHAVE_GUILE" goto :EOF :Usage echo Usage: %0 [options] [gcc] echo Options: echo. --debug For GCC only, make a debug build echo. (MSVC build always makes both debug and release) echo. --without-guile Do not compile Guile support even if found echo. --help Display these instructions and exit goto :EOF :Reset set COMPILER= set DEBUG= set GUILE= set GUILECFLAGS= set GUILELIBS= set LINKOPTS= set MAKE= set NOGUILE= set OPTS= set OUTDIR= set PKGMSC= goto :EOF kbuild-3686/src/kmk/electric.h0000664000175000017500000000336515053010075016233 0ustar locutuslocutus/* $Id: electric.h 3150 2018-03-15 18:18:03Z bird $ */ /** @file * A simple electric heap implementation, wrapper header. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ #ifdef ELECTRIC_HEAP #include #ifdef WINDOWS32 # include #endif #include /* strdup */ void xfree (void *); void *xcalloc (unsigned int); void *xmalloc (unsigned int); void *xrealloc (void *, unsigned int); char *xstrdup (const char *); #ifdef __GNUC__ void *xmalloc_size_t (size_t size); void *xcalloc_size_t (size_t size, size_t items); void *xrealloc_size_t (void *ptr, size_t size); #endif #undef free //#define free(a) xfree(a) #define free xfree #undef strdup #define strdup(a) xstrdup(a) #undef calloc #undef malloc #undef realloc #ifdef __GNUC__ # define calloc(a,b) xcalloc_size_t(a,b) # define malloc(a) xmalloc_size_t(a) # define realloc(a,b) xrealloc_size_t(a,b) #else # define calloc(a,b) xcalloc((a) * (b)) # define malloc(a) xmalloc(a) # define realloc(a,b) xrealloc((a),(b)) #endif #endif kbuild-3686/src/kmk/getopt.c0000664000175000017500000007213115053010075015733 0ustar locutuslocutus/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! Copyright (C) 1987-2016 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO # define _NO_PROTO #endif #ifdef HAVE_CONFIG_H # include #endif #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 # include # if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ # include # include #endif /* GNU C library. */ #ifdef VMS # include # if HAVE_STRING_H - 0 # include # endif #endif /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ macro is predefined. */ #include "gettext.h" #define _(msgid) gettext (msgid) /* This version of `getopt' appears to the caller like standard Unix 'getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ int optind = 1; /* Formerly, initialization of getopt depended on optind==0, which causes problems with re-calling getopt as programs generally don't know that. */ int __getopt_initialized = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ # include # define my_index strchr #else # if HAVE_STRING_H # include # else # include # endif #ifndef KMK /* Avoid depending on library functions or files whose names are inconsistent. */ #ifndef getenv extern char *getenv (); #endif #else /* KMK */ # include #endif /* KMK */ static char * my_index (const char *str, int chr) { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ # if (!defined __STDC__ || !__STDC__) && !defined strlen /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); # endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #ifdef _LIBC /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; static int nonoption_flags_max_len; static int nonoption_flags_len; static int original_argc; static char *const *original_argv; /* Make sure the environment variable bash 2.0 puts in the environment is valid for the getopt call we must make sure that the ARGV passed to getopt is that one passed to the process. */ static void __attribute__ ((unused)) store_args_and_env (int argc, char *const *argv) { /* XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ original_argc = argc; original_argv = argv; } # ifdef text_set_element text_set_element (__libc_subinit, store_args_and_env); # endif /* text_set_element */ # define SWAP_FLAGS(ch1, ch2) \ if (nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } #else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) #endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ #if defined __STDC__ && __STDC__ static void exchange (char **); #endif static void exchange (char **argv) { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ #ifdef _LIBC /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = malloc (top + 1); if (new_str == NULL) nonoption_flags_len = nonoption_flags_max_len = 0; else { memset (__mempcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len), '\0', top + 1 - nonoption_flags_max_len); nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } #endif while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; SWAP_FLAGS (bottom + i, middle + i); } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined __STDC__ && __STDC__ static const char *_getopt_initialize (int, char *const *, const char *); #endif static const char * _getopt_initialize (int argc, char *const *argv, const char *optstring) { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; #ifdef _LIBC if (posixly_correct == NULL && argc == original_argc && argv == original_argv) { if (nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; int len = nonoption_flags_max_len = strlen (orig_str); if (nonoption_flags_max_len < argc) nonoption_flags_max_len = argc; __getopt_nonoption_flags = (char *) malloc (nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) nonoption_flags_max_len = -1; else memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), '\0', nonoption_flags_max_len - len); } } nonoption_flags_len = nonoption_flags_max_len; } else nonoption_flags_len = 0; #endif return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only) { optarg = NULL; if (optind == 0 || !__getopt_initialized) { if (optind == 0) optind = 1; /* Don't scan ARGV[0], the program name. */ optstring = _getopt_initialize (argc, argv, optstring); __getopt_initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #ifdef _LIBC # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ || (optind < nonoption_flags_len \ && __getopt_nonoption_flags[optind] == '1')) #else # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (last_nonopt > optind) last_nonopt = optind; if (first_nonopt > optind) first_nonopt = optind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && NONOPTION_P) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option '%s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) { /* bird: disambiguate */ if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, _("%s: option '--%s' doesn't allow an argument\n"), argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, _("%s: option '%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); } nextchar += strlen (nextchar); optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option '%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, _("%s: unrecognized option '--%s'\n"), argv[0], nextchar); else /* +option or -option */ fprintf (stderr, _("%s: unrecognized option '%c%s'\n"), argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); else fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); } optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) fprintf (stderr, _("\ %s: option '-W %s' doesn't allow an argument\n"), argv[0], pfound->name); nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option '%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt (int argc, char *const *argv, const char *optstring) { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (int argc, char **argv) { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == -1) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value '%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ kbuild-3686/src/kmk/kmk_cc_exec.c0000664000175000017500000110541115053010075016663 0ustar locutuslocutus#ifdef CONFIG_WITH_COMPILER /* $Id: kmk_cc_exec.c 3233 2018-09-24 10:39:36Z bird $ */ /** @file * kmk_cc - Make "Compiler". */ /* * Copyright (c) 2015-2017 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #include "makeint.h" #include "dep.h" #include "variable.h" #include "rule.h" #include "debug.h" #include "hash.h" #include #ifdef HAVE_STDINT_H # include #endif #include #include #include "k/kDefs.h" #include "k/kTypes.h" /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ /** @def KMK_CC_WITH_STATS * Enables the collection of extra statistics. */ #ifndef KMK_CC_WITH_STATS # ifdef CONFIG_WITH_MAKE_STATS # define KMK_CC_WITH_STATS # endif #endif /** @def KMK_CC_STRICT * Indicates whether assertions and other checks are enabled. */ #ifndef KMK_CC_STRICT # ifndef NDEBUG # define KMK_CC_STRICT # endif #endif #ifdef KMK_CC_STRICT # ifdef _MSC_VER # define KMK_CC_ASSERT(a_TrueExpr) do { if (!(a_TrueExpr)) __debugbreak(); } while (0) # elif defined(__GNUC__) && (defined(KBUILD_ARCH_X86) || defined(KBUILD_ARCH_AMD64)) # define KMK_CC_ASSERT(a_TrueExpr) do { if (!(a_TrueExpr)) __asm__ __volatile__("int3;nop"); } while (0) # else # define KMK_CC_ASSERT(a_TrueExpr) assert(a_TrueExpr) # endif #else # define KMK_CC_ASSERT(a_TrueExpr) do {} while (0) #endif #define KMK_CC_ASSERT_ALIGNED(a_uValue, a_uAlignment) \ KMK_CC_ASSERT( ((a_uValue) & ((a_uAlignment) - 1)) == 0 ) /** @def KMK_CC_OFFSETOF * Offsetof for simple stuff. */ #if defined(__GNUC__) # define KMK_CC_OFFSETOF(a_Struct, a_Member) __builtin_offsetof(a_Struct, a_Member) #else # define KMK_CC_OFFSETOF(a_Struct, a_Member) ( (uintptr_t)&( ((a_Struct *)(void *)0)->a_Member) ) #endif /** def KMK_CC_SIZEOF_MEMBER */ #define KMK_CC_SIZEOF_MEMBER(a_Struct, a_Member) ( sizeof( ((a_Struct *)(void *)0x1000)->a_Member) ) /** @def KMK_CC_SIZEOF_VAR_STRUCT * Size of a struct with a variable sized array as the final member. */ #define KMK_CC_SIZEOF_VAR_STRUCT(a_Struct, a_FinalArrayMember, a_cArray) \ ( KMK_CC_OFFSETOF(a_Struct, a_FinalArrayMember) + KMK_CC_SIZEOF_MEMBER(a_Struct, a_FinalArrayMember) * (a_cArray) ) /** @def KMK_CC_STATIC_ASSERT_EX * Compile time assertion with text. */ #ifdef _MSC_VER_ # if _MSC_VER >= 1600 # define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl) static_assert(a_Expr, a_szExpl) # else # define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl) typedef int RTASSERTVAR[(a_Expr) ? 1 : 0] # endif #elif defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) # define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl) static_assert(a_Expr, a_szExpl) #elif !defined(__GNUC__) && !defined(__IBMC__) && !defined(__IBMCPP__) # define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl) typedef int KMK_CC_STATIC_ASSERT_EX_TYPE[(a_Expr) ? 1 : 0] #else # define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl) extern int KMK_CC_STATIC_ASSERT_EX_VAR[(a_Expr) ? 1 : 0] extern int KMK_CC_STATIC_ASSERT_EX_VAR[1]; #endif /** @def KMK_CC_STATIC_ASSERT * Compile time assertion, simple variant. */ #define KMK_CC_STATIC_ASSERT(a_Expr) KMK_CC_STATIC_ASSERT_EX(a_Expr, #a_Expr) /** Aligns a size for the block allocator. */ #define KMK_CC_BLOCK_ALIGN_SIZE(a_cb) ( ((a_cb) + (sizeof(void *) - 1U)) & ~(uint32_t)(sizeof(void *) - 1U) ) /** How to declare a no-return function. * Place between scope (if any) and return type. */ #ifdef _MSC_VER # define KMK_CC_FN_NO_RETURN __declspec(noreturn) #elif defined(__GNUC__) # define KMK_CC_FN_NO_RETURN __attribute__((__noreturn__)) #endif /** Block allocator logging. */ //#define KMK_CC_BLOCK_LOGGING_ENABLED #ifdef KMK_CC_BLOCK_LOGGING_ENABLED # define KMK_CC_BLOCK_DPRINTF_UNPACK(...) __VA_ARGS__ # define KMK_CC_BLOCK_DPRINTF(a) fprintf(stderr, KMK_CC_BLOCK_DPRINTF_UNPACK a) #else # define KMK_CC_BLOCK_DPRINTF(a) do { } while (0) #endif /** @defgroup grp_kmk_cc_evalprog Makefile Evaluation * @{ */ #define KMK_CC_EVAL_LOGGING_ENABLED #ifdef KMK_CC_EVAL_LOGGING_ENABLED # define KMK_CC_EVAL_DPRINTF_UNPACK(...) __VA_ARGS__ # define KMK_CC_EVAL_DPRINTF(a) fprintf(stderr, KMK_CC_EVAL_DPRINTF_UNPACK a) #else # define KMK_CC_EVAL_DPRINTF(a) do { } while (0) #endif /** @name KMK_CC_EVAL_QUALIFIER_XXX - Variable qualifiers. * @{ */ #define KMK_CC_EVAL_QUALIFIER_LOCAL 1 #define KMK_CC_EVAL_QUALIFIER_EXPORT 2 #define KMK_CC_EVAL_QUALIFIER_OVERRIDE 4 #define KMK_CC_EVAL_QUALIFIER_PRIVATE 8 /** @} */ /** Eval: Max makefile size we accept as input (in bytes). */ #define KMK_CC_EVAL_MAX_COMPILE_SIZE (16*1024*1024) /** Eval: Max nesting depth of makefile conditionals. * Affects stack usage in kmk_cc_eval_compile_worker. */ #define KMK_CC_EVAL_MAX_IF_DEPTH 32 /** Eval: Maximum number of escaped end of line sequences to track. * Affects stack usage in kmk_cc_eval_compile_worker, but not the actual * number of consequtive escaped newlines in the input file/variable. */ #define KMK_CC_EVAL_MAX_ESC_EOLS 2 /** Minimum keyword length. */ #define KMK_CC_EVAL_KEYWORD_MIN 2 /** Maximum keyword length. */ #define KMK_CC_EVAL_KEYWORD_MAX 16 /** @name KMK_CC_EVAL_CH_XXX - flags found in g_abEvalCcChars. * @{ */ /** Normal character, nothing special. */ #define KMK_CC_EVAL_CH_NORMAL UINT16_C(0) /** Blank character. */ #define KMK_CC_EVAL_CH_BLANK UINT16_C(1) #define KMK_CC_EVAL_IS_BLANK(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_BLANK) /** Space character. */ #define KMK_CC_EVAL_CH_SPACE UINT16_C(2) #define KMK_CC_EVAL_IS_SPACE(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_SPACE) /** Space character or potential EOL escape backslash. */ #define KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH UINT16_C(4) #define KMK_CC_EVAL_IS_SPACE_OR_BACKSLASH(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH) /** Anything we need to take notice of when parsing something could be a * variable name or a recipe. * All space characters, backslash (EOL escape), variable expansion dollar, * variable assignment operator chars, recipe colon and recipe percent. */ #define KMK_CC_EVAL_CH_SPACE_VAR_OR_RECIPE UINT16_C(8) #define KMK_CC_EVAL_IS_SPACE_VAR_OR_RECIPE(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_SPACE_VAR_OR_RECIPE) /** Dollar character (possible variable expansion). */ #define KMK_CC_EVAL_CH_DOLLAR UINT16_C(16) #define KMK_CC_EVAL_IS_DOLLAR(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_DOLLAR) /** Dollar character (possible variable expansion). */ #define KMK_CC_EVAL_CH_BACKSLASH UINT16_C(32) #define KMK_CC_EVAL_IS_BACKSLASH(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_BACKSLASH) /** Possible EOL character. */ #define KMK_CC_EVAL_CH_EOL_CANDIDATE UINT16_C(64) #define KMK_CC_EVAL_IS_EOL_CANDIDATE(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_EOL_CANDIDATE) /** First character in a keyword. */ #define KMK_CC_EVAL_CH_1ST_IN_KEYWORD UINT16_C(128) #define KMK_CC_EVAL_IS_1ST_IN_KEYWORD(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_1ST_IN_KEYWORD) /** Second character in a keyword. */ #define KMK_CC_EVAL_CH_2ND_IN_KEYWORD UINT16_C(256) #define KMK_CC_EVAL_IS_2ND_IN_KEYWORD(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_2ND_IN_KEYWORD) /** First character in a variable qualifier keyword or 'define'. */ #define KMK_CC_EVAL_CH_1ST_IN_VARIABLE_KEYWORD UINT16_C(512) #define KMK_CC_EVAL_IS_1ST_IN_VARIABLE_KEYWORD(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_1ST_IN_VARIABLE_KEYWORD) /** Used when parsing variable names, looking for the end of a nested * variable reference. Matches parentheses and backslash (escaped eol). */ #define KMK_CC_EVAL_CH_PAREN_OR_SLASH UINT16_C(1024) #define KMK_CC_EVAL_IS_PAREN_OR_SLASH(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_PAREN_OR_SLASH) /** Used when parsing ifeq/ifneq (,) sequences. * Matches parentheses, comma and dollar (for non-plain string detection). */ #define KMK_CC_EVAL_CH_PAREN_COMMA_OR_DOLLAR UINT16_C(2048) #define KMK_CC_EVAL_IS_PAREN_COMMA_OR_DOLLAR(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_PAREN_COMMA_OR_DOLLAR) /** Test of space or dollar characters. */ #define KMK_CC_EVAL_IS_SPACE_OR_DOLLAR(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & (KMK_CC_EVAL_CH_SPACE | KMK_CC_EVAL_CH_DOLLAR)) /** Test of space, dollar or backslash (possible EOL escape) characters. */ #define KMK_CC_EVAL_IS_SPACE_DOLLAR_OR_SLASH(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & (KMK_CC_EVAL_CH_SPACE | KMK_CC_EVAL_CH_DOLLAR | KMK_CC_EVAL_CH_BACKSLASH)) /** Test of space, dollar, backslash (possible EOL escape) or variable * assingment characters. */ #define KMK_CC_EVAL_IS_SPACE_DOLLAR_SLASH_OR_ASSIGN(a_ch) \ (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & (KMK_CC_EVAL_CH_SPACE | KMK_CC_EVAL_CH_SPACE_VAR_OR_RECIPE | KMK_CC_EVAL_CH_DOLLAR)) /** @} */ /** Sets a bitmap entry. * @param a_abBitmap Typically g_abEvalCcChars. * @param a_ch The character to set. * @param a_uVal The value to OR in. */ #define KMK_CC_EVAL_BM_OR(g_abBitmap, a_ch, a_uVal) do { (g_abBitmap)[(unsigned char)(a_ch)] |= (a_uVal); } while (0) /** Gets a bitmap entry. * @returns The value corresponding to @a a_ch. * @param a_abBitmap Typically g_abEvalCcChars. * @param a_ch The character to set. */ #define KMK_CC_EVAL_BM_GET(g_abBitmap, a_ch) ( (g_abBitmap)[(unsigned char)(a_ch)] ) /** @} */ /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ /** * Block of instructions. * * To avoid wasting space on "next" pointers, as well as a lot of time walking * these chains when destroying programs, we work with blocks of instructions. */ typedef struct kmk_cc_block { /** The pointer to the next block (LIFO). */ struct kmk_cc_block *pNext; /** The size of this block. */ uint32_t cbBlock; /** The offset of the next free byte in the block. When set to cbBlock the * block is 100% full. */ uint32_t offNext; } KMKCCBLOCK; typedef KMKCCBLOCK *PKMKCCBLOCK; /** @defgroup grp_kmk_cc_exp String Expansion * @{*/ /** * String expansion statistics. */ typedef struct KMKCCEXPSTATS { /** Recent average size. */ uint32_t cchAvg; } KMKCCEXPSTATS; typedef KMKCCEXPSTATS *PKMKCCEXPSTATS; /** * Expansion instructions. */ typedef enum KMKCCEXPINSTR { /** Copy a plain string. */ kKmkCcExpInstr_CopyString = 0, /** Insert an expanded variable value, which name we already know. */ kKmkCcExpInstr_PlainVariable, /** Insert an expanded variable value, the name is dynamic (sub prog). */ kKmkCcExpInstr_DynamicVariable, /** Insert an expanded variable value, which name we already know, doing * search an replace on a string. */ kKmkCcExpInstr_SearchAndReplacePlainVariable, /** Insert the output of function that requires no argument expansion. */ kKmkCcExpInstr_PlainFunction, /** Insert the output of function that requires dynamic expansion of one ore * more arguments. (Dynamic is perhaps not such a great name, but whatever.) */ kKmkCcExpInstr_DynamicFunction, /** Jump to a new instruction block. */ kKmkCcExpInstr_Jump, /** We're done, return. Has no specific structure. */ kKmkCcExpInstr_Return, /** The end of valid instructions (exclusive). */ kKmkCcExpInstr_End } KMKCCEXPINSTR; /** Instruction core. */ typedef struct kmk_cc_exp_core { /** The instruction opcode number (KMKCCEXPINSTR). */ KMKCCEXPINSTR enmOpcode; } KMKCCEXPCORE; typedef KMKCCEXPCORE *PKMKCCEXPCORE; /** * String expansion subprogram. */ #pragma pack(1) /* save some precious bytes */ typedef struct kmk_cc_exp_subprog { /** Pointer to the first instruction. */ PKMKCCEXPCORE pFirstInstr; /** Statistics. */ KMKCCEXPSTATS Stats; } KMKCCEXPSUBPROG; #pragma pack() typedef KMKCCEXPSUBPROG *PKMKCCEXPSUBPROG; KMK_CC_STATIC_ASSERT(sizeof(KMKCCEXPSUBPROG) == 12 || sizeof(void *) != 8); /** * String expansion subprogram or plain string. */ #pragma pack(1) /* save some precious bytes */ typedef struct kmk_cc_exp_subprog_or_string { /** Either a plain string pointer or a subprogram. */ union { /** Subprogram for expanding this argument. */ KMKCCEXPSUBPROG Subprog; /** Pointer to the plain string. */ struct { /** Pointer to the string. */ const char *psz; /** String length. */ uint32_t cch; } Plain; } u; /** Set if subprogram (u.Subprog), clear if plain string (u.Plain). */ uint8_t fSubprog; /** Set if the plain string is kept in the variable_strcache. * @remarks Here rather than in u.Plain to make use of alignment padding. */ uint8_t fPlainIsInVarStrCache; /** Context/user specific. */ uint8_t bUser; /** Context/user specific #2. */ uint8_t bUser2; } KMKCCEXPSUBPROGORPLAIN; #pragma pack() typedef KMKCCEXPSUBPROGORPLAIN *PKMKCCEXPSUBPROGORPLAIN; KMK_CC_STATIC_ASSERT( sizeof(void *) == 8 ? sizeof(KMKCCEXPSUBPROGORPLAIN) == 16 : sizeof(void *) == 4 ? sizeof(KMKCCEXPSUBPROGORPLAIN) == 12 : 1); /** * kKmkCcExpInstr_CopyString instruction format. */ typedef struct kmk_cc_exp_copy_string { /** The core instruction. */ KMKCCEXPCORE Core; /** The number of bytes to copy. */ uint32_t cchCopy; /** Pointer to the source string (not terminated at cchCopy). */ const char *pachSrc; } KMKCCEXPCOPYSTRING; typedef KMKCCEXPCOPYSTRING *PKMKCCEXPCOPYSTRING; /** * kKmkCcExpInstr_PlainVariable instruction format. */ typedef struct kmk_cc_exp_plain_variable { /** The core instruction. */ KMKCCEXPCORE Core; /** The name of the variable (points into variable_strcache). */ const char *pszName; } KMKCCEXPPLAINVAR; typedef KMKCCEXPPLAINVAR *PKMKCCEXPPLAINVAR; /** * kKmkCcExpInstr_DynamicVariable instruction format. */ typedef struct kmk_cc_exp_dynamic_variable { /** The core instruction. */ KMKCCEXPCORE Core; /** The subprogram that will give us the variable name. */ KMKCCEXPSUBPROG Subprog; /** Where to continue after this instruction. (This is necessary since the * instructions of the subprogram are emitted after this instruction.) */ PKMKCCEXPCORE pNext; } KMKCCEXPDYNVAR; typedef KMKCCEXPDYNVAR *PKMKCCEXPDYNVAR; /** * kKmkCcExpInstr_SearchAndReplacePlainVariable instruction format. */ typedef struct kmk_cc_exp_sr_plain_variable { /** The core instruction. */ KMKCCEXPCORE Core; /** Where to continue after this instruction. (This is necessary since the * instruction contains string data of variable size.) */ PKMKCCEXPCORE pNext; /** The name of the variable (points into variable_strcache). */ const char *pszName; /** Search pattern. */ const char *pszSearchPattern; /** Replacement pattern. */ const char *pszReplacePattern; /** Offset into pszSearchPattern of the significant '%' char. */ uint32_t offPctSearchPattern; /** Offset into pszReplacePattern of the significant '%' char. */ uint32_t offPctReplacePattern; } KMKCCEXPSRPLAINVAR; typedef KMKCCEXPSRPLAINVAR *PKMKCCEXPSRPLAINVAR; /** * Instruction format parts common to both kKmkCcExpInstr_PlainFunction and * kKmkCcExpInstr_DynamicFunction. */ typedef struct kmk_cc_exp_function_core { /** The core instruction. */ KMKCCEXPCORE Core; /** Number of arguments. */ uint32_t cArgs; /**< @todo uint16_t to save 7 bytes of unecessary alignment padding on 64-bit systems, or merge fDirty into this member. */ /** Set if the function could be modifying the input arguments. */ uint8_t fDirty; /** Where to continue after this instruction. (This is necessary since the * instructions are of variable size and may be followed by string data.) */ PKMKCCEXPCORE pNext; /** * Pointer to the function table entry. * * @returns New variable buffer position. * @param pchDst Current variable buffer position. * @param papszArgs Pointer to a NULL terminated array of argument strings. * @param pszFuncName The name of the function being called. */ char * (*pfnFunction)(char *pchDst, char **papszArgs, const char *pszFuncName); /** Pointer to the function name in the variable string cache. */ const char *pszFuncName; } KMKCCEXPFUNCCORE; typedef KMKCCEXPFUNCCORE *PKMKCCEXPFUNCCORE; /** * Instruction format for kKmkCcExpInstr_PlainFunction. */ typedef struct kmk_cc_exp_plain_function { /** The bits comment to both plain and dynamic functions. */ KMKCCEXPFUNCCORE FnCore; /** Variable sized argument list (cArgs + 1 in length, last entry is NULL). * The string pointers are to memory following this instruction, to memory in * the next block or to memory in the variable / makefile we're working on * (if zero terminated appropriately). */ const char *apszArgs[1]; } KMKCCEXPPLAINFUNC; typedef KMKCCEXPPLAINFUNC *PKMKCCEXPPLAINFUNC; /** Calculates the size of an KMKCCEXPPLAINFUNC structure with the apszArgs * member holding a_cArgs entries plus a NULL terminator. */ #define KMKCCEXPPLAINFUNC_SIZE(a_cArgs) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEXPDYNFUNC, aArgs, (a_cArgs) + 1) /** * Instruction format for kKmkCcExpInstr_DynamicFunction. */ typedef struct kmk_cc_exp_dyn_function { /** The bits comment to both plain and dynamic functions. */ KMKCCEXPFUNCCORE FnCore; /** Variable sized argument list (FnCore.cArgs in length). * The subprograms / strings are allocated after this array (or in the next * block). */ KMKCCEXPSUBPROGORPLAIN aArgs[1]; } KMKCCEXPDYNFUNC; typedef KMKCCEXPDYNFUNC *PKMKCCEXPDYNFUNC; /** Calculates the size of an KMKCCEXPDYNFUNC structure with the apszArgs * member holding a_cArgs entries (no zero terminator). */ #define KMKCCEXPDYNFUNC_SIZE(a_cArgs) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEXPDYNFUNC, aArgs, a_cArgs) /** * Instruction format for kKmkCcExpInstr_Jump. */ typedef struct kmk_cc_exp_jump { /** The core instruction. */ KMKCCEXPCORE Core; /** Where to jump to (new instruction block, typically). */ PKMKCCEXPCORE pNext; } KMKCCEXPJUMP; typedef KMKCCEXPJUMP *PKMKCCEXPJUMP; /** * String expansion program. */ typedef struct kmk_cc_expandprog { /** Pointer to the first instruction for this program. */ PKMKCCEXPCORE pFirstInstr; /** List of blocks for this program (LIFO). */ PKMKCCBLOCK pBlockTail; /** Statistics. */ KMKCCEXPSTATS Stats; #ifdef KMK_CC_STRICT /** The hash of the input string. Used to check that we get all the change * notifications we require. */ uint32_t uInputHash; #endif /** Reference count. */ uint32_t volatile cRefs; } KMKCCEXPPROG; /** Pointer to a string expansion program. */ typedef KMKCCEXPPROG *PKMKCCEXPPROG; /** @} */ /** @addtogroup grp_kmk_cc_evalprog * @{ */ /** Pointer to a makefile evaluation program. */ typedef struct kmk_cc_evalprog *PKMKCCEVALPROG; /** * Makefile evaluation instructions. */ typedef enum KMKCCEVALINSTR { /** Jump instruction - KMKCCEVALJUMP. */ kKmkCcEvalInstr_jump = 0, /** [local|override|export] variable = value - KMKCCEVALASSIGN. * @note Can be used for target-specific variables. */ kKmkCcEvalInstr_assign_recursive, /** [local|override|export] variable := value - KMKCCEVALASSIGN. * Also: [local|override|export] define variable := ... endef * @note Can be used for target-specific variables. */ kKmkCcEvalInstr_assign_simple, /** [local|override|export] variable += value - KMKCCEVALASSIGN. * Also: [local|override|export] define variable += ... endef * @note Can be used for target-specific variables. */ kKmkCcEvalInstr_assign_append, /** [local|override|export] variable <= value - KMKCCEVALASSIGN. * Also: [local|override|export] define variable <= ... endef * @note Can be used for target-specific variables. */ kKmkCcEvalInstr_assign_prepend, /** [local|override|export] variable ?= value - KMKCCEVALASSIGN. * @note Can be used for target-specific variables. */ kKmkCcEvalInstr_assign_if_new, /* [local|override|export] define variable[=] ... endef - KMKCCEVALASSIGNDEF. */ kKmkCcEvalInstr_define_recursive, /* [local|override|export] define variable ?= ... endef - KMKCCEVALASSIGNDEF. */ kKmkCcEvalInstr_define_if_new, /** export variable1 [variable2...] - KMKCCEVALVARIABLES. */ kKmkCcEvalInstr_export, /** unexport variable1 [variable2...] - KMKCCEVALVARIABLES. */ kKmkCcEvalInstr_unexport, /** export - KMKCCEVALCORE. */ kKmkCcEvalInstr_export_all, /** unexport - KMKCCEVALCORE. */ kKmkCcEvalInstr_unexport_all, /** [local|override] undefine - KMKCCEVALVARIABLES. */ kKmkCcEvalInstr_undefine, /** [else] ifdef variable - KMKCCEVALIFDEFPLAIN. */ kKmkCcEvalInstr_ifdef_plain, /** [else] ifndef variable - KMKCCEVALIFDEFPLAIN. */ kKmkCcEvalInstr_ifndef_plain, /** [else] ifdef variable - KMKCCEVALIFDEFDYNAMIC. */ kKmkCcEvalInstr_ifdef_dynamic, /** [else] ifndef variable - KMKCCEVALIFDEFDYNAMIC. */ kKmkCcEvalInstr_ifndef_dynamic, /** [else] ifeq (a,b) - KMKCCEVALIFEQ. */ kKmkCcEvalInstr_ifeq, /** [else] ifeq (a,b) - KMKCCEVALIFEQ. */ kKmkCcEvalInstr_ifneq, /** [else] if1of (set-a,set-b) - KMKCCEVALIF1OF. */ kKmkCcEvalInstr_if1of, /** [else] ifn1of (set-a,set-b) - KMKCCEVALIF1OF. */ kKmkCcEvalInstr_ifn1of, /** [else] if expr - KMKCCEVALIFEXPR. */ kKmkCcEvalInstr_if, /** include file1 [file2...] - KMKCCEVALINCLUDE. */ kKmkCcEvalInstr_include, /** [sinclude|-include] file1 [file2...] - KMKCCEVALINCLUDE. */ kKmkCcEvalInstr_include_silent, /** includedep file1 [file2...] - KMKCCEVALINCLUDE. */ kKmkCcEvalInstr_includedep, /** includedep-queue file1 [file2...] - KMKCCEVALINCLUDE. */ kKmkCcEvalInstr_includedep_queue, /** includedep-flush file1 [file2...] - KMKCCEVALINCLUDE. */ kKmkCcEvalInstr_includedep_flush, /** Recipe without commands (defines dependencies) - KMKCCEVALRECIPE. */ kKmkCcEvalInstr_recipe_no_commands, /** Recipe with commands (defines dependencies) - KMKCCEVALRECIPE. */ kKmkCcEvalInstr_recipe_start_normal, /** Recipe with commands (defines dependencies) - KMKCCEVALRECIPE. */ kKmkCcEvalInstr_recipe_start_double_colon, /** Recipe with commands (defines dependencies) - KMKCCEVALRECIPE. */ kKmkCcEvalInstr_recipe_start_pattern, /** Adds more commands to the current recipe - KMKCCEVALRECIPECOMMANDS. */ kKmkCcEvalInstr_recipe_commands, /** Special instruction for indicating the end of the recipe commands - KMKCCEVALCORE. */ kKmkCcEvalInstr_recipe_end, /** Cancel previously defined pattern rule - KMKCCEVALRECIPE. */ kKmkCcEvalInstr_recipe_cancel_pattern, /** @todo target variables. */ /** vpath pattern directories - KMKCCEVALVPATH. */ kKmkCcEvalInstr_vpath, /** vpath pattern directories - KMKCCEVALVPATH. */ kKmkCcEvalInstr_vpath_clear_pattern, /** vpath - KMKCCEVALCORE. */ kKmkCcEvalInstr_vpath_clear_all, /** Make 'code' needing expanding and evaluation - KMKCCEVALEXPAND. * @note That this could in theory be used to start a recipe. This will be * detected by the interpreter and loading will for now fail. A * strategy for implement support for it would require picking up * potential commands following the statements too. */ kKmkCcEvalInstr_expand, /** The end of valid instructions (exclusive). */ kKmkCcEvalInstr_End } KMKCCEVALINSTR; /** * Instruction core common to all instructions. */ typedef struct kmk_cc_eval_core { /** The instruction opcode number (KMKCCEVALINSTR). */ KMKCCEVALINSTR enmOpcode; /** The line number in the source this statement is associated with. */ unsigned iLine; } KMKCCEVALCORE; /** Pointer to an instruction core structure. */ typedef KMKCCEVALCORE *PKMKCCEVALCORE; /** * Instruction format for kKmkCcEvalInstr_jump. */ typedef struct kmk_cc_eval_jump { /** The core instruction. */ KMKCCEVALCORE Core; /** Where to jump to (new instruction block or endif, typically). */ PKMKCCEVALCORE pNext; } KMKCCEVALJUMP; typedef KMKCCEVALJUMP *PKMKCCEVALJUMP; /** * Instruction format for kKmkCcEvalInstr_assign_recursive, * kKmkCcEvalInstr_assign_simple, kKmkCcEvalInstr_assign_append, * kKmkCcEvalInstr_assign_prepend and kKmkCcEvalInstr_assign_if_new. */ typedef struct kmk_cc_eval_assign { /** The core instruction. */ KMKCCEVALCORE Core; /** Whether the 'export' qualifier was used. */ uint8_t fExport; /** Whether the 'override' qualifier was used. */ uint8_t fOverride; /** Whether the 'local' qualifier was used. */ uint8_t fLocal; /** Whether the 'private' qualifier was used. */ uint8_t fPrivate; /** The variable name. * @remarks Plain text names are in variable_strcache. */ KMKCCEXPSUBPROGORPLAIN Variable; /** The value or value expression. */ KMKCCEXPSUBPROGORPLAIN Value; /** Pointer to the next instruction. */ PKMKCCEVALCORE pNext; } KMKCCEVALASSIGN; typedef KMKCCEVALASSIGN *PKMKCCEVALASSIGN; /** * Instruction format for kKmkCcEvalInstr_define_recursive and * kKmkCcEvalInstr_define_if_new. */ typedef struct kmk_cc_eval_assign_define { /** The assignment core structure. */ KMKCCEVALASSIGN AssignCore; /** Makefile evaluation program compiled from the define. * NULL if it does not compile. * @todo Let's see if this is actually doable... */ PKMKCCEVALPROG pEvalProg; } KMKCCEVALASSIGNDEF; typedef KMKCCEVALASSIGNDEF *PKMKCCEVALASSIGNDEF; /** * Instruction format for kKmkCcEvalInstr_export, kKmkCcEvalInstr_unexport and * kKmkCcEvalInstr_undefine. */ typedef struct kmk_cc_eval_variables { /** The core instruction. */ KMKCCEVALCORE Core; /** The number of variables named in aVars. */ uint32_t cVars; /** Whether the 'local' qualifier was used (undefine only). */ uint8_t fLocal; /** Pointer to the next instruction. */ PKMKCCEVALCORE pNext; /** The variable names. * Expressions will be expanded and split on space. * @remarks Plain text names are in variable_strcache. */ KMKCCEXPSUBPROGORPLAIN aVars[1]; } KMKCCEVALVARIABLES; typedef KMKCCEVALVARIABLES *PKMKCCEVALVARIABLES; /** Calculates the size of an KMKCCEVALVARIABLES structure for @a a_cVars. */ #define KMKCCEVALVARIABLES_SIZE(a_cVars) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALVARIABLES, aVars, a_cVars) /** * Core structure for all conditionals (kKmkCcEvalInstr_if*). */ typedef struct kmk_cc_eval_if_core { /** The core instruction. */ KMKCCEVALCORE Core; /** Condition true: Pointer to the next instruction. */ PKMKCCEVALCORE pNextTrue; /** Condition false: Pointer to the next instruction (i.e. 'else if*' * or whatever follows 'else' / 'endif'. */ PKMKCCEVALCORE pNextFalse; /** Pointer to the previous conditional for 'else if*' directives. * This is only to assist the compilation process. */ struct kmk_cc_eval_if_core *pPrevCond; /** Pointer to the jump out of the true block, if followed by 'else'. * This is only to assist the compilation process. */ PKMKCCEVALJUMP pTrueEndJump; } KMKCCEVALIFCORE; typedef KMKCCEVALIFCORE *PKMKCCEVALIFCORE; /** * Instruction format for kKmkCcEvalInstr_ifdef_plain and * kKmkCcEvalInstr_ifndef_plain. * The variable name is known at compilation time. */ typedef struct kmk_cc_eval_ifdef_plain { /** The 'if' core structure. */ KMKCCEVALIFCORE IfCore; /** The name of the variable (points into variable_strcache). */ const char *pszName; } KMKCCEVALIFDEFPLAIN; typedef KMKCCEVALIFDEFPLAIN *PKMKCCEVALIFDEFPLAIN; /** * Instruction format for kKmkCcEvalInstr_ifdef_dynamic and * kKmkCcEvalInstr_ifndef_dynamic. * The variable name is dynamically expanded at run time. */ typedef struct kmk_cc_eval_ifdef_dynamic { /** The 'if' core structure. */ KMKCCEVALIFCORE IfCore; /** Alignment padding, MBZ. */ KU32 uPadding; /** The subprogram that will give us the variable name. */ KMKCCEXPSUBPROG NameSubprog; } KMKCCEVALIFDEFDYNAMIC; typedef KMKCCEVALIFDEFDYNAMIC *PKMKCCEVALIFDEFDYNAMIC; /** * Instruction format for kKmkCcEvalInstr_ifeq and kKmkCcEvalInstr_ifneq. */ typedef struct kmk_cc_eval_ifeq { /** The 'if' core structure. */ KMKCCEVALIFCORE IfCore; /** The left hand side string expression (dynamic or plain). */ KMKCCEXPSUBPROGORPLAIN Left; /** The rigth hand side string expression (dynamic or plain). */ KMKCCEXPSUBPROGORPLAIN Right; } KMKCCEVALIFEQ; typedef KMKCCEVALIFEQ *PKMKCCEVALIFEQ; /** * Instruction format for kKmkCcEvalInstr_if1of and kKmkCcEvalInstr_ifn1of. * * @todo This can be optimized further by pre-hashing plain text items. One of * the sides are usually plain text. */ typedef struct kmk_cc_eval_if1of { /** The 'if' core structure. */ KMKCCEVALIFCORE IfCore; /** The left hand side string expression (dynamic or plain). */ KMKCCEXPSUBPROGORPLAIN Left; /** The rigth hand side string expression (dynamic or plain). */ KMKCCEXPSUBPROGORPLAIN Right; } KMKCCEVALIF1OF; typedef KMKCCEVALIF1OF *PKMKCCEVALIF1OF; /** * Instruction format for kKmkCcEvalInstr_if. * * @todo Parse and compile the expression. At least strip whitespace in it. */ typedef struct kmk_cc_eval_if_expr { /** The 'if' core structure. */ KMKCCEVALIFCORE IfCore; /** The expression string length. */ uint16_t cchExpr; /** The expression string. */ char szExpr[1]; } KMKCCEVALIFEXPR; typedef KMKCCEVALIFEXPR *PKMKCCEVALIFEXPR; /** Calculates the size of an KMKCCEVALIFEXPR structure for @a a_cchExpr long * expression string (terminator is automatically added). */ #define KMKCCEVALIFEXPR_SIZE(a_cchExpr) KMK_CC_BLOCK_ALIGN_SIZE(KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALIFEXPR, szExpr, (a_cchExpr) + 1)) /** * Instruction format for kKmkCcEvalInstr_include, * kKmkCcEvalInstr_include_silent, kKmkCcEvalInstr_includedep, * kKmkCcEvalInstr_includedep_queue, kKmkCcEvalInstr_includedep_flush. */ typedef struct kmk_cc_eval_include { /** The core instruction. */ KMKCCEVALCORE Core; /** The number of files. */ uint32_t cFiles; /** Pointer to the next instruction (subprogs and strings after this one). */ PKMKCCEVALCORE pNext; /** The files to be included. * Expressions will be expanded and split on space. * @todo Plain text file name could be replaced by file string cache entries. */ KMKCCEXPSUBPROGORPLAIN aFiles[1]; } KMKCCEVALINCLUDE; typedef KMKCCEVALINCLUDE *PKMKCCEVALINCLUDE; /** Calculates the size of an KMKCCEVALINCLUDE structure for @a a_cFiles files. */ #define KMKCCEVALINCLUDE_SIZE(a_cFiles) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALINCLUDE, aFiles, a_cFiles) /** * Instruction format for kKmkCcEvalInstr_recipe_no_commands, * kKmkCcEvalInstr_recipe_start_normal, * kKmkCcEvalInstr_recipe_start_double_colon, kKmkCcEvalInstr_includedep_queue, * kKmkCcEvalInstr_recipe_start_pattern. */ typedef struct kmk_cc_eval_recipe { /** The core instruction. */ KMKCCEVALCORE Core; /** The total number of files and dependencies in aFilesAndDeps. */ uint16_t cFilesAndDeps; /** Number of targets (from index 0). * This is always 1 if this is an explicit multitarget or pattern recipe, * indicating the main target. */ uint16_t cTargets; /** Explicit multitarget & patterns: First always made target. */ uint16_t iFirstAlwaysMadeTargets; /** Explicit multitarget & patterns: Number of always targets. */ uint16_t cAlwaysMadeTargets; /** Explicit multitarget: First maybe made target. */ uint16_t iFirstMaybeTarget; /** Explicit multitarget: Number of maybe made targets. */ uint16_t cMaybeTargets; /** First dependency. */ uint16_t iFirstDep; /** Number of ordinary dependencies. */ uint16_t cDeps; /** First order only dependency. */ uint16_t iFirstOrderOnlyDep; /** Number of ordinary dependencies. */ uint16_t cOrderOnlyDeps; /** Pointer to the next instruction (subprogs and strings after this one). */ PKMKCCEVALCORE pNext; /** The .MUST_MAKE variable value, if present. * If not present, this is a zero length plain string. */ KMKCCEXPSUBPROGORPLAIN MustMake; /** The target files and dependencies. * This is sorted into several sections, as defined by the above indexes and * counts. Expressions will be expanded and split on space. * * The KMKCCEXPSUBPROGORPLAIN::bUser member one of KMKCCEVALRECIPE_FD_XXX. * * @todo Plain text file name could be replaced by file string cache entries. */ KMKCCEXPSUBPROGORPLAIN aFilesAndDeps[1]; } KMKCCEVALRECIPE; typedef KMKCCEVALRECIPE *PKMKCCEVALRECIPE; /** Calculates the size of an KMKCCEVALRECIPE structure for @a a_cFiles * files. */ #define KMKCCEVALRECIPE_SIZE(a_cFilesAndDeps) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALRECIPE, aFilesAndDeps, a_cFilesAndDeps) /** @name KMKCCEVALRECIPE_FD_XXX - Values for KMKCCEVALRECIPE::aFilesAndDeps[x].bUser * @{ */ #define KMKCCEVALRECIPE_FD_NORMAL 0 #define KMKCCEVALRECIPE_FD_SEC_EXP 1 #define KMKCCEVALRECIPE_FD_SPECIAL_POSIX 2 #define KMKCCEVALRECIPE_FD_SPECIAL_SECONDEXPANSION 3 #define KMKCCEVALRECIPE_FD_SPECIAL_ONESHELL 4 /** @} */ /** * Instruction format for kKmkCcEvalInstr_recipe_commands. */ typedef struct kmk_cc_eval_recipe_commands { /** The core instruction. */ KMKCCEVALCORE Core; /** The number of commands. */ uint32_t cCommands; /** Pointer to the next instruction (subprogs and strings after this one). */ PKMKCCEVALCORE pNext; /** Commands to add to the current recipe. * Expressions will be expanded and split on newline? */ KMKCCEXPSUBPROGORPLAIN aCommands[1]; } KMKCCEVALRECIPECOMMANDS; typedef KMKCCEVALRECIPECOMMANDS *PKMKCCEVALRECIPECOMMANDS; /** Calculates the size of an KMKCCEVALRECIPECOMMANDS structure for * @a a_cCommands commands. */ #define KMKCCEVALRECIPECOMMANDS_SIZE(a_cCommands) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALRECIPECOMMANDS, aCommands, a_cCommands) /** * Instruction format for kKmkCcEvalInstr_vpath and * kKmkCcEvalInstr_vpath_clear_pattern. */ typedef struct kmk_cc_eval_vpath { /** The core instruction. */ KMKCCEVALCORE Core; /** The number of search directories. * This will be zero for kKmkCcEvalInstr_vpath_clear_pattern. */ uint32_t cDirs; /** Pointer to the next instruction (subprogs and strings after this one). */ PKMKCCEVALCORE pNext; /** The pattern. */ KMKCCEXPSUBPROGORPLAIN Pattern; /** The directory. Expressions will be expanded and split on space. */ KMKCCEXPSUBPROGORPLAIN aDirs[1]; } KMKCCEVALVPATH; typedef KMKCCEVALVPATH *PKMKCCEVALVPATH; /** Calculates the size of an KMKCCEVALVPATH structure for @a a_cFiles files. */ #define KMKCCEVALVPATH_SIZE(a_cFiles) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALVPATH, aDirs, a_cDirs) /** * Instruction format for kKmkCcEvalInstr_expand. */ typedef struct kmk_cc_eval_expand { /** The core instruction. */ KMKCCEVALCORE Core; /** Alignment padding, MBZ. */ KU32 uPadding; /** The expansion subprogram that to execute and evaluate the output of. */ KMKCCEXPSUBPROG Subprog; } KMKCCEVALEXPAND; typedef KMKCCEVALEXPAND *PKMKCCEVALEXPAND; /** * Makefile evaluation program. */ typedef struct kmk_cc_evalprog { /** Pointer to the first instruction for this program. */ PKMKCCEVALCORE pFirstInstr; /** List of blocks for this program (LIFO). */ PKMKCCBLOCK pBlockTail; /** The name of the file containing this program. */ const char *pszFilename; /** The name of the variable containing this program, if applicable. */ const char *pszVarName; #ifdef KMK_CC_STRICT /** The hash of the input string. Used to check that we get all the change * notifications we require. */ uint32_t uInputHash; #endif /** Reference count. */ uint32_t volatile cRefs; } KMKCCEVALPROG; typedef KMKCCEVALPROG *PKMKCCEVALPROG; /** @} */ /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ static uint32_t g_cVarForExpandCompilations = 0; static uint32_t g_cVarForExpandExecs = 0; static uint32_t g_cVarForEvalCompilations = 0; static uint32_t g_cVarForEvalExecs = 0; static uint32_t g_cFileForEvalCompilations = 0; static uint32_t g_cFileForEvalExecs = 0; #ifdef KMK_CC_WITH_STATS static uint32_t g_cBlockAllocated = 0; static uint32_t g_cbAllocated = 0; static uint32_t g_cBlocksAllocatedExpProgs = 0; static uint32_t g_cbAllocatedExpProgs = 0; static uint32_t g_cSingleBlockExpProgs = 0; static uint32_t g_cTwoBlockExpProgs = 0; static uint32_t g_cMultiBlockExpProgs = 0; static uint32_t g_cbUnusedMemExpProgs = 0; static uint32_t g_cBlocksAllocatedEvalProgs = 0; static uint32_t g_cbAllocatedEvalProgs = 0; static uint32_t g_cSingleBlockEvalProgs = 0; static uint32_t g_cTwoBlockEvalProgs = 0; static uint32_t g_cMultiBlockEvalProgs = 0; static uint32_t g_cbUnusedMemEvalProgs = 0; #endif /** Generic character classification, taking an 'unsigned char' index. * ASSUMES unsigned char is 8-bits. */ static uint16_t g_abEvalCcChars[256]; /** * Makefile evaluation keywords. */ static const char * const g_apszEvalKeywords[] = { "define", "export", "else", "endef", "endif", "ifdef", "ifndef", "ifeq", "ifneq", "if1of", "ifn1of", "if", "include", "includedep", "includedep-queue", "includedep-flush", "local", "override", "private", "sinclude", "unexport", "undefine", "vpath", "-include", }; /** This is parallel to KMKCCEVALINSTR. */ static const char * const g_apszEvalInstrNms[] = { "jump", "assign_recursive", "assign_simple", "assign_append", "assign_prepend", "assign_if_new", "define_recursive", "define_if_new", "export", "unexport", "export_all", "unexport_all", "undefine", "ifdef_plain", "ifndef_plain", "ifdef_dynamic", "ifndef_dynamic", "ifeq", "ifneq", "if1of", "ifn1of", "if", "include", "include_silent", "includedep", "includedep_queue", "includedep_flush", "recipe_no_commands", "recipe_start_normal", "recipe_start_double_colon", "recipe_start_pattern", "recipe_commands", "recipe_end", "recipe_cancel_pattern", "vpath", "vpath_clear_pattern", "vpath_clear_all", }; /********************************************************************************************************************************* * Internal Functions * *********************************************************************************************************************************/ static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubprog); static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubprog, uint32_t *pcch); /** * Initializes global variables for the 'compiler'. */ void kmk_cc_init(void) { unsigned i; /* * Initialize the bitmap. */ memset(g_abEvalCcChars, 0, sizeof(g_abEvalCcChars)); /* blank chars */ KMK_CC_EVAL_BM_OR(g_abEvalCcChars, ' ', KMK_CC_EVAL_CH_BLANK); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\t', KMK_CC_EVAL_CH_BLANK); /* space chars and zero terminator. */ #define MY_SPACE_BITS KMK_CC_EVAL_CH_SPACE | KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH | KMK_CC_EVAL_CH_SPACE_VAR_OR_RECIPE KMK_CC_EVAL_BM_OR(g_abEvalCcChars, ' ', MY_SPACE_BITS); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\t', MY_SPACE_BITS); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\n', MY_SPACE_BITS | KMK_CC_EVAL_CH_EOL_CANDIDATE); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\v', MY_SPACE_BITS); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\f', MY_SPACE_BITS); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\r', MY_SPACE_BITS | KMK_CC_EVAL_CH_EOL_CANDIDATE); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\\', KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH | KMK_CC_EVAL_CH_SPACE_VAR_OR_RECIPE); #undef MY_SPACE_BITS /* keywords */ for (i = 0; i < K_ELEMENTS(g_apszEvalKeywords); i++) { #ifdef KMK_CC_STRICT size_t cch = strlen(g_apszEvalKeywords[i]); KMK_CC_ASSERT(cch >= KMK_CC_EVAL_KEYWORD_MIN); KMK_CC_ASSERT(cch <= KMK_CC_EVAL_KEYWORD_MAX); #endif KMK_CC_EVAL_BM_OR(g_abEvalCcChars, g_apszEvalKeywords[i][0], KMK_CC_EVAL_CH_1ST_IN_KEYWORD); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, g_apszEvalKeywords[i][1], KMK_CC_EVAL_CH_2ND_IN_KEYWORD); } KMK_CC_EVAL_BM_OR(g_abEvalCcChars, 'd', KMK_CC_EVAL_CH_1ST_IN_VARIABLE_KEYWORD); /* define */ KMK_CC_EVAL_BM_OR(g_abEvalCcChars, 'e', KMK_CC_EVAL_CH_1ST_IN_VARIABLE_KEYWORD); /* export, endef */ KMK_CC_EVAL_BM_OR(g_abEvalCcChars, 'l', KMK_CC_EVAL_CH_1ST_IN_VARIABLE_KEYWORD); /* local */ KMK_CC_EVAL_BM_OR(g_abEvalCcChars, 'o', KMK_CC_EVAL_CH_1ST_IN_VARIABLE_KEYWORD); /* override */ KMK_CC_EVAL_BM_OR(g_abEvalCcChars, 'p', KMK_CC_EVAL_CH_1ST_IN_VARIABLE_KEYWORD); /* private */ KMK_CC_EVAL_BM_OR(g_abEvalCcChars, 'u', KMK_CC_EVAL_CH_1ST_IN_VARIABLE_KEYWORD); /* undefine, unexport */ /* Assignment punctuation and recipe stuff. */ KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '=', KMK_CC_EVAL_CH_SPACE_VAR_OR_RECIPE); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, ':', KMK_CC_EVAL_CH_SPACE_VAR_OR_RECIPE); /* For locating the end of variable expansion. */ KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '(', KMK_CC_EVAL_CH_PAREN_OR_SLASH); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, ')', KMK_CC_EVAL_CH_PAREN_OR_SLASH); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '{', KMK_CC_EVAL_CH_PAREN_OR_SLASH); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '}', KMK_CC_EVAL_CH_PAREN_OR_SLASH); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\\', KMK_CC_EVAL_CH_PAREN_OR_SLASH); /* For parsing ifeq and if1of expressions. (GNU weirdly does not respect {} style function references.) */ KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '(', KMK_CC_EVAL_CH_PAREN_COMMA_OR_DOLLAR); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, ')', KMK_CC_EVAL_CH_PAREN_COMMA_OR_DOLLAR); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, ',', KMK_CC_EVAL_CH_PAREN_COMMA_OR_DOLLAR); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '$', KMK_CC_EVAL_CH_PAREN_COMMA_OR_DOLLAR); /* Misc. */ KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '$', KMK_CC_EVAL_CH_DOLLAR); KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\\', KMK_CC_EVAL_CH_BACKSLASH); /* * Check that the eval instruction names match up. */ KMK_CC_ASSERT(strcmp(g_apszEvalInstrNms[kKmkCcEvalInstr_ifneq], "ifneq") == 0); KMK_CC_ASSERT(strcmp(g_apszEvalInstrNms[kKmkCcEvalInstr_vpath_clear_all], "vpath_clear_all") == 0); } /** * Prints stats (for kmk -p). */ void kmk_cc_print_stats(void) { #ifdef KMK_CC_WITH_STATS uint32_t const cEvalCompilations = g_cFileForEvalCompilations + g_cVarForEvalCompilations; #endif puts(_("\n# The kmk 'compiler' and kmk 'program executor':\n")); printf(_("# Variables compiled for string expansion: %6u\n"), g_cVarForExpandCompilations); printf(_("# Variables string expansion runs: %6u\n"), g_cVarForExpandExecs); printf(_("# String expansion runs per compile: %6u\n"), g_cVarForExpandExecs / g_cVarForExpandCompilations); #ifdef KMK_CC_WITH_STATS printf(_("# Single alloc block exp progs: %6u (%u%%)\n" "# Two alloc block exp progs: %6u (%u%%)\n" "# Three or more alloc block exp progs: %6u (%u%%)\n" ), g_cSingleBlockExpProgs, (uint32_t)((uint64_t)g_cSingleBlockExpProgs * 100 / g_cVarForExpandCompilations), g_cTwoBlockExpProgs, (uint32_t)((uint64_t)g_cTwoBlockExpProgs * 100 / g_cVarForExpandCompilations), g_cMultiBlockExpProgs, (uint32_t)((uint64_t)g_cMultiBlockExpProgs * 100 / g_cVarForExpandCompilations)); printf(_("# Total amount of memory for exp progs: %8u bytes\n" "# in: %6u blocks\n" "# avg block size: %6u bytes\n" "# unused memory: %8u bytes (%u%%)\n" "# avg unused memory per block: %6u bytes\n" "\n"), g_cbAllocatedExpProgs, g_cBlocksAllocatedExpProgs, g_cbAllocatedExpProgs / g_cBlocksAllocatedExpProgs, g_cbUnusedMemExpProgs, (uint32_t)((uint64_t)g_cbUnusedMemExpProgs * 100 / g_cbAllocatedExpProgs), g_cbUnusedMemExpProgs / g_cBlocksAllocatedExpProgs); puts(""); #endif printf(_("# Variables compiled for string eval: %6u\n"), g_cVarForEvalCompilations); printf(_("# Variables string eval runs: %6u\n"), g_cVarForEvalExecs); printf(_("# String evals runs per compile: %6u\n"), g_cVarForEvalExecs / g_cVarForEvalCompilations); printf(_("# Files compiled: %6u\n"), g_cFileForEvalCompilations); printf(_("# Files runs: %6u\n"), g_cFileForEvalExecs); printf(_("# Files eval runs per compile: %6u\n"), g_cFileForEvalExecs / g_cFileForEvalCompilations); #ifdef KMK_CC_WITH_STATS printf(_("# Single alloc block eval progs: %6u (%u%%)\n" "# Two alloc block eval progs: %6u (%u%%)\n" "# Three or more alloc block eval progs: %6u (%u%%)\n" ), g_cSingleBlockEvalProgs, (uint32_t)((uint64_t)g_cSingleBlockEvalProgs * 100 / cEvalCompilations), g_cTwoBlockEvalProgs, (uint32_t)((uint64_t)g_cTwoBlockEvalProgs * 100 / cEvalCompilations), g_cMultiBlockEvalProgs, (uint32_t)((uint64_t)g_cMultiBlockEvalProgs * 100 / cEvalCompilations)); printf(_("# Total amount of memory for eval progs: %8u bytes\n" "# in: %6u blocks\n" "# avg block size: %6u bytes\n" "# unused memory: %8u bytes (%u%%)\n" "# avg unused memory per block: %6u bytes\n" "\n"), g_cbAllocatedEvalProgs, g_cBlocksAllocatedEvalProgs, g_cbAllocatedEvalProgs / g_cBlocksAllocatedEvalProgs, g_cbUnusedMemEvalProgs, (uint32_t)((uint64_t)g_cbUnusedMemEvalProgs * 100 / g_cbAllocatedEvalProgs), g_cbUnusedMemEvalProgs / g_cBlocksAllocatedEvalProgs); puts(""); printf(_("# Total amount of block mem allocated: %8u bytes\n"), g_cbAllocated); printf(_("# Total number of block allocated: %8u\n"), g_cBlockAllocated); printf(_("# Average block size: %8u byte\n"), g_cbAllocated / g_cBlockAllocated); #endif puts(""); } /* * * Various utility functions. * Various utility functions. * Various utility functions. * */ /** * Counts the number of dollar chars in the string. * * @returns Number of dollar chars. * @param pchStr The string to search (does not need to be zero * terminated). * @param cchStr The length of the string. */ static uint32_t kmk_cc_count_dollars(const char *pchStr, uint32_t cchStr) { uint32_t cDollars = 0; const char *pch; while ((pch = memchr(pchStr, '$', cchStr)) != NULL) { cDollars++; cchStr -= pch - pchStr + 1; pchStr = pch + 1; } return cDollars; } #ifdef KMK_CC_STRICT /** * Used to check that function arguments are left alone. * @returns Updated hash. * @param uHash The current hash value. * @param psz The string to hash. */ static uint32_t kmk_cc_debug_string_hash(uint32_t uHash, const char *psz) { unsigned char ch; while ((ch = *(unsigned char const *)psz++) != '\0') uHash = (uHash << 6) + (uHash << 16) - uHash + (unsigned char)ch; return uHash; } /** * Used to check that function arguments are left alone. * @returns Updated hash. * @param uHash The current hash value. * @param pch The string to hash, not terminated. * @param cch The number of chars to hash. */ static uint32_t kmk_cc_debug_string_hash_n(uint32_t uHash, const char *pch, uint32_t cch) { while (cch-- > 0) { unsigned char ch = *(unsigned char const *)pch++; uHash = (uHash << 6) + (uHash << 16) - uHash + (unsigned char)ch; } return uHash; } #endif /* * * The allocator. * The allocator. * The allocator. * */ /** * For the first allocation using the block allocator. * * @returns Pointer to the first allocation (@a cbFirst in size). * @param ppBlockTail Where to return the pointer to the first block. * @param cbFirst The size of the first allocation. * @param cbHint Hint about how much memory we might be needing. */ static void *kmk_cc_block_alloc_first(PKMKCCBLOCK *ppBlockTail, size_t cbFirst, size_t cbHint) { uint32_t cbBlock; PKMKCCBLOCK pNewBlock; KMK_CC_ASSERT_ALIGNED(cbFirst, sizeof(void *)); KMK_CC_ASSERT(cbFirst <= 128); /* * Turn the hint into a block size. */ cbHint += cbFirst; if (cbHint <= 512) { if (cbHint <= 256) { if (cbFirst <= 64) cbBlock = 128; else cbBlock = 256; } else cbBlock = 256; } else if (cbHint < 2048) cbBlock = 1024; else if (cbHint < 3072) cbBlock = 2048; else cbBlock = 4096; /* * Allocate and initialize the first block. */ pNewBlock = (PKMKCCBLOCK)xmalloc(cbBlock); pNewBlock->cbBlock = cbBlock; pNewBlock->offNext = sizeof(*pNewBlock) + cbFirst; pNewBlock->pNext = NULL; *ppBlockTail = pNewBlock; #ifdef KMK_CC_WITH_STATS g_cBlockAllocated++; g_cbAllocated += cbBlock; #endif return pNewBlock + 1; } /** * Used for getting the address of the next instruction. * * @returns Pointer to the next allocation. * @param pBlockTail The allocator tail pointer. */ static void *kmk_cc_block_get_next_ptr(PKMKCCBLOCK pBlockTail) { return (char *)pBlockTail + pBlockTail->offNext; } /** * Realigns the allocator after doing byte or string allocations. * * @param ppBlockTail Pointer to the allocator tail pointer. */ static void kmk_cc_block_realign(PKMKCCBLOCK *ppBlockTail) { PKMKCCBLOCK pBlockTail = *ppBlockTail; uint32_t offNext = pBlockTail->offNext; if (offNext & (sizeof(void *) - 1U)) { pBlockTail->offNext = KMK_CC_BLOCK_ALIGN_SIZE(offNext); KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_realign: offNext=%#x -> %#x\n", offNext, pBlockTail->offNext)); KMK_CC_ASSERT(pBlockTail->cbBlock - pBlockTail->offNext >= sizeof(KMKCCEXPJUMP)); } } /** * Grows the allocation with another block, byte allocator case. * * @returns Pointer to the byte allocation. * @param ppBlockTail Pointer to the allocator tail pointer. * @param cb The number of bytes to allocate. */ static void *kmk_cc_block_byte_alloc_grow(PKMKCCBLOCK *ppBlockTail, uint32_t cb) { PKMKCCBLOCK pOldBlock = *ppBlockTail; PKMKCCBLOCK pPrevBlock = pOldBlock->pNext; PKMKCCBLOCK pNewBlock; uint32_t cbBlock; /* * Check if there accidentally is some space left in the previous block first. */ if ( pPrevBlock && pPrevBlock->cbBlock - pPrevBlock->offNext >= cb) { void *pvRet = (char *)pPrevBlock + pPrevBlock->offNext; pPrevBlock->offNext += cb; KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_byte_alloc_grow: %p LB %#x offNext=%#x [prev]\n", pvRet, cb, pPrevBlock->offNext)); return pvRet; } /* * Allocate a new block. */ /* Figure the block size. */ cbBlock = pOldBlock->cbBlock; while (cbBlock - sizeof(KMKCCEXPJUMP) - sizeof(*pNewBlock) < cb) cbBlock *= 2; /* Allocate and initialize the block it with the new instruction already accounted for. */ pNewBlock = (PKMKCCBLOCK)xmalloc(cbBlock); pNewBlock->cbBlock = cbBlock; pNewBlock->offNext = sizeof(*pNewBlock) + cb; pNewBlock->pNext = pOldBlock; *ppBlockTail = pNewBlock; #ifdef KMK_CC_WITH_STATS g_cBlockAllocated++; g_cbAllocated += cbBlock; #endif KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_byte_alloc_grow: %p LB %#x offNext=%#x\n", pNewBlock + 1, cb, pNewBlock->offNext)); return pNewBlock + 1; } /** * Make a byte allocation. * * Must call kmk_cc_block_realign() when done doing byte and string allocations. * * @returns Pointer to the byte allocation (byte aligned). * @param ppBlockTail Pointer to the allocator tail pointer. * @param cb The number of bytes to allocate. */ static void *kmk_cc_block_byte_alloc(PKMKCCBLOCK *ppBlockTail, uint32_t cb) { PKMKCCBLOCK pBlockTail = *ppBlockTail; uint32_t cbLeft = pBlockTail->cbBlock - pBlockTail->offNext; KMK_CC_ASSERT(cbLeft >= sizeof(KMKCCEXPJUMP)); if (cbLeft >= cb + sizeof(KMKCCEXPJUMP)) { void *pvRet = (char *)pBlockTail + pBlockTail->offNext; pBlockTail->offNext += cb; KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_byte_alloc: %p LB %#x offNext=%#x\n", pvRet, cb, pBlockTail->offNext)); return pvRet; } return kmk_cc_block_byte_alloc_grow(ppBlockTail, cb); } /** * Duplicates the given string in a byte allocation. * * Must call kmk_cc_block_realign() when done doing byte and string allocations. * * @returns Pointer to the byte allocation (byte aligned). * @param ppBlockTail Pointer to the allocator tail pointer. * @param cb The number of bytes to allocate. */ static const char *kmk_cc_block_strdup(PKMKCCBLOCK *ppBlockTail, const char *pachStr, uint32_t cchStr) { char *pszCopy; if (cchStr) { pszCopy = kmk_cc_block_byte_alloc(ppBlockTail, cchStr + 1); memcpy(pszCopy, pachStr, cchStr); pszCopy[cchStr] = '\0'; return pszCopy; } return ""; } /** * Grows the allocation with another block, string expansion program case. * * @returns Pointer to a string expansion instruction core. * @param ppBlockTail Pointer to the allocator tail pointer. * @param cb The number of bytes to allocate. */ static PKMKCCEXPCORE kmk_cc_block_alloc_exp_grow(PKMKCCBLOCK *ppBlockTail, uint32_t cb) { PKMKCCBLOCK pOldBlock = *ppBlockTail; PKMKCCBLOCK pNewBlock; PKMKCCEXPCORE pRet; PKMKCCEXPJUMP pJump; /* Figure the block size. */ uint32_t cbBlock = !pOldBlock->pNext ? 128 : pOldBlock->cbBlock; while (cbBlock - sizeof(KMKCCEXPJUMP) - sizeof(*pNewBlock) < cb) cbBlock *= 2; /* Allocate and initialize the block it with the new instruction already accounted for. */ pNewBlock = (PKMKCCBLOCK)xmalloc(cbBlock); pNewBlock->cbBlock = cbBlock; pNewBlock->offNext = sizeof(*pNewBlock) + cb; pNewBlock->pNext = pOldBlock; *ppBlockTail = pNewBlock; #ifdef KMK_CC_WITH_STATS g_cBlockAllocated++; g_cbAllocated += cbBlock; #endif pRet = (PKMKCCEXPCORE)(pNewBlock + 1); KMK_CC_ASSERT(((size_t)pRet & (sizeof(void *) - 1)) == 0); /* Emit jump. */ pJump = (PKMKCCEXPJUMP)((char *)pOldBlock + pOldBlock->offNext); pJump->Core.enmOpcode = kKmkCcExpInstr_Jump; pJump->pNext = pRet; pOldBlock->offNext += sizeof(*pJump); KMK_CC_ASSERT(pOldBlock->offNext <= pOldBlock->cbBlock); KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_alloc_exp_grow: %p LB %#x offNext=%#x\n", pRet, cb, pNewBlock->offNext)); return pRet; } /** * Allocates a string expansion instruction of size @a cb. * * @returns Pointer to a string expansion instruction core. * @param ppBlockTail Pointer to the allocator tail pointer. * @param cb The number of bytes to allocate. */ static PKMKCCEXPCORE kmk_cc_block_alloc_exp(PKMKCCBLOCK *ppBlockTail, uint32_t cb) { PKMKCCBLOCK pBlockTail = *ppBlockTail; uint32_t cbLeft = pBlockTail->cbBlock - pBlockTail->offNext; KMK_CC_ASSERT(cbLeft >= sizeof(KMKCCEXPJUMP)); KMK_CC_ASSERT( (cb & (sizeof(void *) - 1)) == 0 || cb == sizeof(KMKCCEXPCORE) /* final */ ); KMK_CC_ASSERT((pBlockTail->offNext & (sizeof(void *) - 1)) == 0); if (cbLeft >= cb + sizeof(KMKCCEXPJUMP)) { PKMKCCEXPCORE pRet = (PKMKCCEXPCORE)((char *)pBlockTail + pBlockTail->offNext); pBlockTail->offNext += cb; KMK_CC_ASSERT(((size_t)pRet & (sizeof(void *) - 1)) == 0); KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_alloc_exp: %p LB %#x offNext=%#x\n", pRet, cb, pBlockTail->offNext)); return pRet; } return kmk_cc_block_alloc_exp_grow(ppBlockTail, cb); } /** * Grows the allocation with another block, makefile evaluation program case. * * @returns Pointer to a makefile evaluation instruction core. * @param ppBlockTail Pointer to the allocator tail pointer. * @param cb The number of bytes to allocate. */ static PKMKCCEVALCORE kmk_cc_block_alloc_eval_grow(PKMKCCBLOCK *ppBlockTail, uint32_t cb) { PKMKCCBLOCK pOldBlock = *ppBlockTail; PKMKCCBLOCK pNewBlock; PKMKCCEVALCORE pRet; PKMKCCEVALJUMP pJump; /* Figure the block size. */ uint32_t cbBlock = !pOldBlock->pNext ? 128 : pOldBlock->cbBlock; while (cbBlock - sizeof(KMKCCEVALJUMP) - sizeof(*pNewBlock) < cb) cbBlock *= 2; /* Allocate and initialize the block it with the new instruction already accounted for. */ pNewBlock = (PKMKCCBLOCK)xmalloc(cbBlock); pNewBlock->cbBlock = cbBlock; pNewBlock->offNext = sizeof(*pNewBlock) + cb; pNewBlock->pNext = pOldBlock; *ppBlockTail = pNewBlock; #ifdef KMK_CC_WITH_STATS g_cBlockAllocated++; g_cbAllocated += cbBlock; #endif pRet = (PKMKCCEVALCORE)(pNewBlock + 1); /* Emit jump. */ pJump = (PKMKCCEVALJUMP)((char *)pOldBlock + pOldBlock->offNext); pJump->Core.enmOpcode = kKmkCcEvalInstr_jump; pJump->pNext = pRet; pOldBlock->offNext += sizeof(*pJump); KMK_CC_ASSERT(pOldBlock->offNext <= pOldBlock->cbBlock); KMK_CC_ASSERT((pNewBlock->offNext & (sizeof(void *) - 1)) == 0); KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_alloc_eval_grow: %p LB %#x offNext=%#x (*ppBlockTail=%p, was %p)\n", pRet, cb, pNewBlock->offNext, *ppBlockTail, pOldBlock)); return pRet; } /** * Allocates a makefile evaluation instruction of size @a cb. * * @returns Pointer to a makefile evaluation instruction core. * @param ppBlockTail Pointer to the allocator tail pointer. * @param cb The number of bytes to allocate. */ static PKMKCCEVALCORE kmk_cc_block_alloc_eval(PKMKCCBLOCK *ppBlockTail, uint32_t cb) { PKMKCCBLOCK pBlockTail = *ppBlockTail; uint32_t cbLeft = pBlockTail->cbBlock - pBlockTail->offNext; KMK_CC_ASSERT(cbLeft >= sizeof(KMKCCEVALJUMP)); KMK_CC_ASSERT( (cb & (sizeof(void *) - 1)) == 0 ); KMK_CC_ASSERT((pBlockTail->offNext & (sizeof(void *) - 1)) == 0); if (cbLeft >= cb + sizeof(KMKCCEVALJUMP)) { PKMKCCEVALCORE pRet = (PKMKCCEVALCORE)((char *)pBlockTail + pBlockTail->offNext); pBlockTail->offNext += cb; KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_alloc_eval: %p LB %#x offNext=%#x\n", pRet, cb, pBlockTail->offNext)); return pRet; } return kmk_cc_block_alloc_eval_grow(ppBlockTail, cb); } /** * Frees all memory used by an allocator. * * @param ppBlockTail The allocator tail pointer. */ static void kmk_cc_block_free_list(PKMKCCBLOCK pBlockTail) { while (pBlockTail) { PKMKCCBLOCK pThis = pBlockTail; pBlockTail = pBlockTail->pNext; free(pThis); } } /* * * The string expansion compiler. * The string expansion compiler. * The string expansion compiler. * */ /** * Emits a kKmkCcExpInstr_Return. * * @param ppBlockTail Pointer to the allocator tail pointer. */ static void kmk_cc_exp_emit_return(PKMKCCBLOCK *ppBlockTail) { PKMKCCEXPCORE pCore = kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pCore)); pCore->enmOpcode = kKmkCcExpInstr_Return; kmk_cc_block_realign(ppBlockTail); } /** * Checks if a function is known to mess up the arguments its given. * * When executing calls to "dirty" functions, all arguments must be duplicated * on the heap. * * @returns 1 if dirty, 0 if clean. * @param pszFunction The function name. */ static uint8_t kmk_cc_is_dirty_function(const char *pszFunction) { switch (pszFunction[0]) { default: return 0; case 'e': if (!strcmp(pszFunction, "eval")) return 1; if (!strcmp(pszFunction, "evalctx")) return 1; return 0; case 'f': if (!strcmp(pszFunction, "filter")) return 1; if (!strcmp(pszFunction, "filter-out")) return 1; if (!strcmp(pszFunction, "for")) return 1; return 0; case 's': if (!strcmp(pszFunction, "sort")) return 1; return 0; } } /** * Emits a function call instruction taking arguments that needs expanding. * * @returns 0 on success, non-zero on failure. * @param ppBlockTail Pointer to the allocator tail pointer. * @param pszFunction The function name (const string from function.c). * @param pchArgs Pointer to the arguments expression string, leading * any blanks has been stripped. * @param cchArgs The length of the arguments expression string. * @param cArgs Number of arguments found. * @param chOpen The char used to open the function call. * @param chClose The char used to close the function call. * @param pfnFunction The function implementation. * @param cMaxArgs Maximum number of arguments the function takes. */ static int kmk_cc_exp_emit_dyn_function(PKMKCCBLOCK *ppBlockTail, const char *pszFunction, const char *pchArgs, uint32_t cchArgs, uint32_t cArgs, char chOpen, char chClose, make_function_ptr_t pfnFunction, unsigned char cMaxArgs) { uint32_t iArg; /* * The function instruction has variable size. The maximum argument count * isn't quite like the minium one. Zero means no limit. While a non-zero * value means that any commas beyond the max will be taken to be part of * the final argument. */ uint32_t cActualArgs = cArgs <= cMaxArgs || !cMaxArgs ? cArgs : cMaxArgs; PKMKCCEXPDYNFUNC pInstr = (PKMKCCEXPDYNFUNC)kmk_cc_block_alloc_exp(ppBlockTail, KMKCCEXPDYNFUNC_SIZE(cActualArgs)); pInstr->FnCore.Core.enmOpcode = kKmkCcExpInstr_DynamicFunction; pInstr->FnCore.cArgs = cActualArgs; pInstr->FnCore.pfnFunction = pfnFunction; pInstr->FnCore.pszFuncName = pszFunction; pInstr->FnCore.fDirty = kmk_cc_is_dirty_function(pszFunction); /* * Parse the arguments. Plain arguments gets duplicated in the program * memory so that they are terminated and no extra processing is necessary * later on. ASSUMES that the function implementations do NOT change * argument memory. Other arguments the compiled into their own expansion * sub programs. */ iArg = 0; for (;;) { /* Find the end of the argument. Check for $. */ char ch = '\0'; uint8_t fDollar = 0; int32_t cDepth = 0; uint32_t cchThisArg = 0; while (cchThisArg < cchArgs) { ch = pchArgs[cchThisArg]; if (ch == chClose) { KMK_CC_ASSERT(cDepth > 0); if (cDepth > 0) cDepth--; } else if (ch == chOpen) cDepth++; else if (ch == ',' && cDepth == 0 && iArg + 1 < cActualArgs) break; else if (ch == '$') fDollar = 1; cchThisArg++; } pInstr->aArgs[iArg].fSubprog = fDollar; if (fDollar) { /* Compile it. */ int rc; kmk_cc_block_realign(ppBlockTail); rc = kmk_cc_exp_compile_subprog(ppBlockTail, pchArgs, cchThisArg, &pInstr->aArgs[iArg].u.Subprog); if (rc != 0) return rc; } else { /* Duplicate it. */ pInstr->aArgs[iArg].u.Plain.psz = kmk_cc_block_strdup(ppBlockTail, pchArgs, cchThisArg); pInstr->aArgs[iArg].u.Plain.cch = cchThisArg; } iArg++; if (ch != ',') break; pchArgs += cchThisArg + 1; cchArgs -= cchThisArg + 1; } KMK_CC_ASSERT(iArg == cActualArgs); /* * Realign the allocator and take down the address of the next instruction. */ kmk_cc_block_realign(ppBlockTail); pInstr->FnCore.pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail); return 0; } /** * Emits a function call instruction taking plain arguments. * * @returns 0 on success, non-zero on failure. * @param ppBlockTail Pointer to the allocator tail pointer. * @param pszFunction The function name (const string from function.c). * @param pchArgs Pointer to the arguments string, leading any blanks * has been stripped. * @param cchArgs The length of the arguments string. * @param cArgs Number of arguments found. * @param chOpen The char used to open the function call. * @param chClose The char used to close the function call. * @param pfnFunction The function implementation. * @param cMaxArgs Maximum number of arguments the function takes. */ static void kmk_cc_exp_emit_plain_function(PKMKCCBLOCK *ppBlockTail, const char *pszFunction, const char *pchArgs, uint32_t cchArgs, uint32_t cArgs, char chOpen, char chClose, make_function_ptr_t pfnFunction, unsigned char cMaxArgs) { uint32_t iArg; /* * The function instruction has variable size. The maximum argument count * isn't quite like the minium one. Zero means no limit. While a non-zero * value means that any commas beyond the max will be taken to be part of * the final argument. */ uint32_t cActualArgs = cArgs <= cMaxArgs || !cMaxArgs ? cArgs : cMaxArgs; PKMKCCEXPPLAINFUNC pInstr = (PKMKCCEXPPLAINFUNC)kmk_cc_block_alloc_exp(ppBlockTail, KMKCCEXPPLAINFUNC_SIZE(cActualArgs)); pInstr->FnCore.Core.enmOpcode = kKmkCcExpInstr_PlainFunction; pInstr->FnCore.cArgs = cActualArgs; pInstr->FnCore.pfnFunction = pfnFunction; pInstr->FnCore.pszFuncName = pszFunction; pInstr->FnCore.fDirty = kmk_cc_is_dirty_function(pszFunction); /* * Parse the arguments. Plain arguments gets duplicated in the program * memory so that they are terminated and no extra processing is necessary * later on. ASSUMES that the function implementations do NOT change * argument memory. */ iArg = 0; for (;;) { /* Find the end of the argument. */ char ch = '\0'; int32_t cDepth = 0; uint32_t cchThisArg = 0; while (cchThisArg < cchArgs) { ch = pchArgs[cchThisArg]; if (ch == chClose) { KMK_CC_ASSERT(cDepth > 0); if (cDepth > 0) cDepth--; } else if (ch == chOpen) cDepth++; else if (ch == ',' && cDepth == 0 && iArg + 1 < cActualArgs) break; cchThisArg++; } /* Duplicate it. */ pInstr->apszArgs[iArg++] = kmk_cc_block_strdup(ppBlockTail, pchArgs, cchThisArg); if (ch != ',') break; pchArgs += cchThisArg + 1; cchArgs -= cchThisArg + 1; } KMK_CC_ASSERT(iArg == cActualArgs); pInstr->apszArgs[iArg] = NULL; /* * Realign the allocator and take down the address of the next instruction. */ kmk_cc_block_realign(ppBlockTail); pInstr->FnCore.pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail); } /** * Emits a kKmkCcExpInstr_DynamicVariable. * * @returns 0 on success, non-zero on failure. * @param ppBlockTail Pointer to the allocator tail pointer. * @param pchNameExpr The name of the variable (ASSUMED presistent * thru-out the program life time). * @param cchNameExpr The length of the variable name. If zero, * nothing will be emitted. */ static int kmk_cc_exp_emit_dyn_variable(PKMKCCBLOCK *ppBlockTail, const char *pchNameExpr, uint32_t cchNameExpr) { PKMKCCEXPDYNVAR pInstr; int rc; KMK_CC_ASSERT(cchNameExpr > 0); pInstr = (PKMKCCEXPDYNVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr)); pInstr->Core.enmOpcode = kKmkCcExpInstr_DynamicVariable; rc = kmk_cc_exp_compile_subprog(ppBlockTail, pchNameExpr, cchNameExpr, &pInstr->Subprog); pInstr->pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail); return rc; } /** * Emits either a kKmkCcExpInstr_PlainVariable or * kKmkCcExpInstr_SearchAndReplacePlainVariable instruction. * * @param ppBlockTail Pointer to the allocator tail pointer. * @param pchName The name of the variable. (Does not need to be * valid beyond the call.) * @param cchName The length of the variable name. If zero, * nothing will be emitted. */ static void kmk_cc_exp_emit_plain_variable_maybe_sr(PKMKCCBLOCK *ppBlockTail, const char *pchName, uint32_t cchName) { if (cchName > 0) { /* * Hopefully, we're not expected to do any search and replace on the * expanded variable string later... Requires both ':' and '='. */ const char *pchEqual; const char *pchColon = (const char *)memchr(pchName, ':', cchName); if ( pchColon == NULL || (pchEqual = (const char *)memchr(pchColon + 1, ':', cchName - (pchColon - pchName - 1))) == NULL || pchEqual == pchEqual + 1) { PKMKCCEXPPLAINVAR pInstr = (PKMKCCEXPPLAINVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr)); pInstr->Core.enmOpcode = kKmkCcExpInstr_PlainVariable; pInstr->pszName = strcache2_add(&variable_strcache, pchName, cchName); } else if (pchColon != pchName) { /* * Okay, we need to do search and replace the variable value. * This is performed by patsubst_expand_pat using '%' patterns. */ uint32_t cchName2 = (uint32_t)(pchColon - pchName); uint32_t cchSearch = (uint32_t)(pchEqual - pchColon - 1); uint32_t cchReplace = cchName - cchName2 - cchSearch - 2; const char *pchPct; char *psz; PKMKCCEXPSRPLAINVAR pInstr; pInstr = (PKMKCCEXPSRPLAINVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr)); pInstr->Core.enmOpcode = kKmkCcExpInstr_SearchAndReplacePlainVariable; pInstr->pszName = strcache2_add(&variable_strcache, pchName, cchName2); /* Figure out the search pattern, unquoting percent chars.. */ psz = (char *)kmk_cc_block_byte_alloc(ppBlockTail, cchSearch + 2); psz[0] = '%'; memcpy(psz + 1, pchColon + 1, cchSearch); psz[1 + cchSearch] = '\0'; pchPct = find_percent(psz + 1); /* also performs unquoting */ if (pchPct) { pInstr->pszSearchPattern = psz + 1; pInstr->offPctSearchPattern = (uint32_t)(pchPct - psz - 1); } else { pInstr->pszSearchPattern = psz; pInstr->offPctSearchPattern = 0; } /* Figure out the replacement pattern, unquoting percent chars.. */ if (cchReplace == 0) { pInstr->pszReplacePattern = "%"; pInstr->offPctReplacePattern = 0; } else { psz = (char *)kmk_cc_block_byte_alloc(ppBlockTail, cchReplace + 2); psz[0] = '%'; memcpy(psz + 1, pchEqual + 1, cchReplace); psz[1 + cchReplace] = '\0'; pchPct = find_percent(psz + 1); /* also performs unquoting */ if (pchPct) { pInstr->pszReplacePattern = psz + 1; pInstr->offPctReplacePattern = (uint32_t)(pchPct - psz - 1); } else { pInstr->pszReplacePattern = psz; pInstr->offPctReplacePattern = 0; } } /* Note down where the next instruction is after realigning the allocator. */ kmk_cc_block_realign(ppBlockTail); pInstr->pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail); } } } /** * Emits a kKmkCcExpInstr_CopyString. * * @param ppBlockTail Pointer to the allocator tail pointer. * @param pchStr The string to emit (ASSUMED presistent thru-out * the program life time). * @param cchStr The number of chars to copy. If zero, nothing * will be emitted. */ static void kmk_cc_exp_emit_copy_string(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr) { if (cchStr > 0) { PKMKCCEXPCOPYSTRING pInstr = (PKMKCCEXPCOPYSTRING)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr)); pInstr->Core.enmOpcode = kKmkCcExpInstr_CopyString; pInstr->cchCopy = cchStr; pInstr->pachSrc = pchStr; } } /** * String expansion compilation function common to both normal and sub programs. * * @returns 0 on success, non-zero on failure. * @param ppBlockTail Pointer to the allocator tail pointer. * @param pchStr The expression to compile. * @param cchStr The length of the expression to compile. */ static int kmk_cc_exp_compile_common(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr) { /* * Process the string. */ while (cchStr > 0) { /* Look for dollar sign, marks variable expansion or dollar-escape. */ int rc; const char *pchDollar = memchr(pchStr, '$', cchStr); if (pchDollar) { /* * Check for multiple dollar chars. */ uint32_t offDollar = (uint32_t)(pchDollar - pchStr); uint32_t cDollars = 1; while ( offDollar + cDollars < cchStr && pchStr[offDollar + cDollars] == '$') cDollars++; /* * Emit a string copy for any preceeding stuff, including half of * the dollars we found (dollar escape: $$ -> $). * (kmk_cc_exp_emit_copy_string ignore zero length strings). */ kmk_cc_exp_emit_copy_string(ppBlockTail, pchStr, offDollar + cDollars / 2); pchStr += offDollar + cDollars; cchStr -= offDollar + cDollars; /* * Odd number of dollar chars means there is a variable to expand * or function to call. */ if (cDollars & 1) { if (cchStr > 0) { char const chOpen = *pchStr; if (chOpen == '(' || chOpen == '{') { /* There are several alternative ways of finding the ending parenthesis / braces. GNU make does one thing for functions and variable containing any '$' chars before the first closing char. While for variables where a closing char comes before any '$' char, a simplified approach is taken. This means that for example: Given VAR=var, the expressions "$(var())" and "$($(VAR)())" would be expanded differently. In the first case the variable "var(" would be used and in the second "var()". This code will not duplicate this weird behavior, but work the same regardless of whether there is a '$' char before the first closing char. */ make_function_ptr_t pfnFunction; const char *pszFunction; unsigned char cMaxArgs; unsigned char cMinArgs; char fExpandArgs; char const chClose = chOpen == '(' ? ')' : '}'; char ch = 0; uint32_t cchName = 0; uint32_t cDepth = 1; uint32_t cMaxDepth = 1; cDollars = 0; pchStr++; cchStr--; /* First loop: Identify potential function calls and dynamic expansion. */ KMK_CC_ASSERT(!func_char_map[(unsigned char)chOpen]); KMK_CC_ASSERT(!func_char_map[(unsigned char)chClose]); KMK_CC_ASSERT(!func_char_map[(unsigned char)'$']); while (cchName < cchStr) { ch = pchStr[cchName]; if (!func_char_map[(unsigned char)ch]) break; cchName++; } if ( cchName >= MIN_FUNCTION_LENGTH && cchName <= MAX_FUNCTION_LENGTH && (ISBLANK(ch) || ch == chClose || cchName == cchStr) && (pfnFunction = lookup_function_for_compiler(pchStr, cchName, &cMinArgs, &cMaxArgs, &fExpandArgs, &pszFunction)) != NULL) { /* * It's a function invocation, we should count parameters while * looking for the end. * Note! We use cchName for the length of the argument list. */ uint32_t cArgs = 1; if (ch != chClose) { /* Skip leading spaces before the first arg. */ cchName++; while (cchName < cchStr && ISBLANK(pchStr[cchName])) cchName++; pchStr += cchName; cchStr -= cchName; cchName = 0; while (cchName < cchStr) { ch = pchStr[cchName]; if (ch == ',') { if (cDepth == 1) cArgs++; } else if (ch == chClose) { if (!--cDepth) break; } else if (ch == chOpen) { if (++cDepth > cMaxDepth) cMaxDepth = cDepth; } else if (ch == '$') cDollars++; cchName++; } } else { pchStr += cchName; cchStr -= cchName; cchName = 0; } if (cArgs < cMinArgs) { fatal(NULL, _("Function '%s' takes a minimum of %d arguments: %d given"), pszFunction, (int)cMinArgs, (int)cArgs); return -1; /* not reached */ } if (cDepth != 0) { fatal(NULL, chOpen == '(' ? _("Missing closing parenthesis calling '%s'") : _("Missing closing braces calling '%s'"), pszFunction); return -1; /* not reached */ } if (cMaxDepth > 16 && fExpandArgs) { fatal(NULL, _("Too many levels of nested function arguments expansions: %s"), pszFunction); return -1; /* not reached */ } if (!fExpandArgs || cDollars == 0) kmk_cc_exp_emit_plain_function(ppBlockTail, pszFunction, pchStr, cchName, cArgs, chOpen, chClose, pfnFunction, cMaxArgs); else { rc = kmk_cc_exp_emit_dyn_function(ppBlockTail, pszFunction, pchStr, cchName, cArgs, chOpen, chClose, pfnFunction, cMaxArgs); if (rc != 0) return rc; } } else { /* * Variable, find the end while checking whether anything needs expanding. */ if (ch == chClose) cDepth = 0; else if (cchName < cchStr) { if (ch != '$') { /* Second loop: Look for things that needs expanding. */ while (cchName < cchStr) { ch = pchStr[cchName]; if (ch == chClose) { if (!--cDepth) break; } else if (ch == chOpen) { if (++cDepth > cMaxDepth) cMaxDepth = cDepth; } else if (ch == '$') break; cchName++; } } if (ch == '$') { /* Third loop: Something needs expanding, just find the end. */ cDollars = 1; cchName++; while (cchName < cchStr) { ch = pchStr[cchName]; if (ch == chClose) { if (!--cDepth) break; } else if (ch == chOpen) { if (++cDepth > cMaxDepth) cMaxDepth = cDepth; } cchName++; } } } if (cDepth > 0) /* After warning, we just assume they're all there. */ error(NULL, chOpen == '(' ? _("Missing closing parenthesis ") : _("Missing closing braces")); if (cMaxDepth >= 16) { fatal(NULL, _("Too many levels of nested variable expansions: '%.*s'"), (int)cchName + 2, pchStr - 1); return -1; /* not reached */ } if (cDollars == 0) kmk_cc_exp_emit_plain_variable_maybe_sr(ppBlockTail, pchStr, cchName); else { rc = kmk_cc_exp_emit_dyn_variable(ppBlockTail, pchStr, cchName); if (rc != 0) return rc; } } pchStr += cchName + 1; cchStr -= cchName + (cDepth == 0); } else { /* Single character variable name. */ kmk_cc_exp_emit_plain_variable_maybe_sr(ppBlockTail, pchStr, 1); pchStr++; cchStr--; } } else { error(NULL, _("Unexpected end of string after $")); break; } } } else { /* * Nothing more to expand, the remainder is a simple string copy. */ kmk_cc_exp_emit_copy_string(ppBlockTail, pchStr, cchStr); break; } } /* * Emit final instruction. */ kmk_cc_exp_emit_return(ppBlockTail); return 0; } /** * Initializes string expansion program statistics. * @param pStats Pointer to the statistics structure to init. */ static void kmk_cc_exp_stats_init(PKMKCCEXPSTATS pStats) { pStats->cchAvg = 0; } /** * Compiles a string expansion subprogram. * * The caller typically make a call to kmk_cc_block_get_next_ptr after this * function returns to figure out where to continue executing. * * @returns 0 on success, non-zero on failure. * @param ppBlockTail Pointer to the allocator tail pointer. * @param pchStr Pointer to the string to compile an expansion * program for (ASSUMED to be valid for the * lifetime of the program). * @param cchStr The length of the string to compile. Expected to * be at least on char long. * @param pSubprog The subprogram structure to initialize. */ static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubprog) { KMK_CC_ASSERT(cchStr > 0); pSubprog->pFirstInstr = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail); kmk_cc_exp_stats_init(&pSubprog->Stats); return kmk_cc_exp_compile_common(ppBlockTail, pchStr, cchStr); } /** * Compiles a string expansion program. * * @returns Pointer to the program on success, NULL on failure. * @param pchStr Pointer to the string to compile an expansion * program for (ASSUMED to be valid for the * lifetime of the program). * @param cchStr The length of the string to compile. Expected to * be at least on char long. */ static PKMKCCEXPPROG kmk_cc_exp_compile(const char *pchStr, uint32_t cchStr) { /* * Estimate block size, allocate one and initialize it. */ PKMKCCEXPPROG pProg; PKMKCCBLOCK pBlock; pProg = kmk_cc_block_alloc_first(&pBlock, sizeof(*pProg), (kmk_cc_count_dollars(pchStr, cchStr) + 4) * 8); if (pProg) { pProg->pBlockTail = pBlock; pProg->pFirstInstr = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(pBlock); kmk_cc_exp_stats_init(&pProg->Stats); pProg->cRefs = 1; #ifdef KMK_CC_STRICT pProg->uInputHash = kmk_cc_debug_string_hash_n(0, pchStr, cchStr); #endif /* * Join forces with the subprogram compilation code. */ if (kmk_cc_exp_compile_common(&pProg->pBlockTail, pchStr, cchStr) == 0) { #ifdef KMK_CC_WITH_STATS pBlock = pProg->pBlockTail; if (!pBlock->pNext) g_cSingleBlockExpProgs++; else if (!pBlock->pNext->pNext) g_cTwoBlockExpProgs++; else g_cMultiBlockExpProgs++; for (; pBlock; pBlock = pBlock->pNext) { g_cBlocksAllocatedExpProgs++; g_cbAllocatedExpProgs += pBlock->cbBlock; g_cbUnusedMemExpProgs += pBlock->cbBlock - pBlock->offNext; } #endif return pProg; } kmk_cc_block_free_list(pProg->pBlockTail); } return NULL; } /** * Updates the recursive_without_dollar member of a variable structure. * * This avoid compiling string expansion programs with only a CopyString * instruction. By setting recursive_without_dollar to 1, code calling * kmk_cc_compile_variable_for_expand and kmk_exec_expand_to_var_buf will * instead treat start treating it as a simple variable, which is faster. * * @returns The updated recursive_without_dollar value. * @param pVar Pointer to the variable. */ static int kmk_cc_update_variable_recursive_without_dollar(struct variable *pVar) { int fValue; KMK_CC_ASSERT(pVar->recursive_without_dollar == 0); if (memchr(pVar->value, '$', pVar->value_length)) fValue = -1; else fValue = 1; pVar->recursive_without_dollar = fValue; return fValue; } /** * Compiles a variable for string expansion. * * @returns Pointer to the string expansion program on success, NULL if no * program was created. * @param pVar Pointer to the variable. */ struct kmk_cc_expandprog *kmk_cc_compile_variable_for_expand(struct variable *pVar) { KMK_CC_ASSERT(strlen(pVar->value) == pVar->value_length); KMK_CC_ASSERT(!pVar->expandprog); KMK_CC_ASSERT(pVar->recursive_without_dollar <= 0); if ( !pVar->expandprog && pVar->recursive) { if ( pVar->recursive_without_dollar < 0 || ( pVar->recursive_without_dollar == 0 && kmk_cc_update_variable_recursive_without_dollar(pVar) < 0) ) { pVar->expandprog = kmk_cc_exp_compile(pVar->value, pVar->value_length); g_cVarForExpandCompilations++; } } return pVar->expandprog; } /** * String expansion execution worker for outputting a variable. * * @returns The new variable buffer position. * @param pVar The variable to reference. * @param pchDst The current variable buffer position. */ static char *kmk_exec_expand_worker_reference_variable(struct variable *pVar, char *pchDst) { if (pVar->value_length > 0) { if (!pVar->recursive || IS_VARIABLE_RECURSIVE_WITHOUT_DOLLAR(pVar)) pchDst = variable_buffer_output(pchDst, pVar->value, pVar->value_length); else pchDst = reference_recursive_variable(pchDst, pVar); } else if (pVar->append) pchDst = reference_recursive_variable(pchDst, pVar); return pchDst; } /** * Executes a stream string expansion instructions, outputting to the current * varaible buffer. * * @returns The new variable buffer position. * @param pInstrCore The instruction to start executing at. * @param pchDst The current variable buffer position. */ static char *kmk_exec_expand_instruction_stream_to_var_buf(PKMKCCEXPCORE pInstrCore, char *pchDst) { for (;;) { switch (pInstrCore->enmOpcode) { case kKmkCcExpInstr_CopyString: { PKMKCCEXPCOPYSTRING pInstr = (PKMKCCEXPCOPYSTRING)pInstrCore; pchDst = variable_buffer_output(pchDst, pInstr->pachSrc, pInstr->cchCopy); pInstrCore = &(pInstr + 1)->Core; break; } case kKmkCcExpInstr_PlainVariable: { PKMKCCEXPPLAINVAR pInstr = (PKMKCCEXPPLAINVAR)pInstrCore; struct variable *pVar = lookup_variable_strcached(pInstr->pszName); if (pVar) pchDst = kmk_exec_expand_worker_reference_variable(pVar, pchDst); else warn_undefined(pInstr->pszName, strcache2_get_len(&variable_strcache, pInstr->pszName)); pInstrCore = &(pInstr + 1)->Core; break; } case kKmkCcExpInstr_DynamicVariable: { PKMKCCEXPDYNVAR pInstr = (PKMKCCEXPDYNVAR)pInstrCore; struct variable *pVar; uint32_t cchName; char *pszName = kmk_exec_expand_subprog_to_tmp(&pInstr->Subprog, &cchName); char *pszColon = (char *)memchr(pszName, ':', cchName); char *pszEqual; if ( pszColon == NULL || (pszEqual = (char *)memchr(pszColon + 1, '=', &pszName[cchName] - pszColon - 1)) == NULL || pszEqual == pszColon + 1) { pVar = lookup_variable(pszName, cchName); if (pVar) pchDst = kmk_exec_expand_worker_reference_variable(pVar, pchDst); else warn_undefined(pszName, cchName); } else if (pszColon != pszName) { /* * Oh, we have to do search and replace. How tedious. * Since the variable name is a temporary buffer, we can transform * the strings into proper search and replacement patterns directly. */ pVar = lookup_variable(pszName, pszColon - pszName); if (pVar) { char const *pszExpandedVarValue = pVar->recursive ? recursively_expand(pVar) : pVar->value; char *pszSearchPat = pszColon + 1; char *pszReplacePat = pszEqual + 1; const char *pchPctSearchPat; const char *pchPctReplacePat; *pszEqual = '\0'; pchPctSearchPat = find_percent(pszSearchPat); pchPctReplacePat = find_percent(pszReplacePat); if (!pchPctReplacePat) { if (pszReplacePat[-2] != '\0') /* On the offchance that a pct was unquoted by find_percent. */ { memmove(pszName + 1, pszSearchPat, pszReplacePat - pszSearchPat); if (pchPctSearchPat) pchPctSearchPat -= pszSearchPat - &pszName[1]; pszSearchPat = &pszName[1]; } pchPctReplacePat = --pszReplacePat; *pszReplacePat = '%'; } if (!pchPctSearchPat) { pchPctSearchPat = --pszSearchPat; *pszSearchPat = '%'; } pchDst = patsubst_expand_pat(pchDst, pszExpandedVarValue, pszSearchPat, pszReplacePat, pchPctSearchPat, pchPctReplacePat); if (pVar->recursive) free((void *)pszExpandedVarValue); } else warn_undefined(pszName, pszColon - pszName); } free(pszName); pInstrCore = pInstr->pNext; break; } case kKmkCcExpInstr_SearchAndReplacePlainVariable: { PKMKCCEXPSRPLAINVAR pInstr = (PKMKCCEXPSRPLAINVAR)pInstrCore; struct variable *pVar = lookup_variable_strcached(pInstr->pszName); if (pVar) { char const *pszExpandedVarValue = pVar->recursive ? recursively_expand(pVar) : pVar->value; pchDst = patsubst_expand_pat(pchDst, pszExpandedVarValue, pInstr->pszSearchPattern, pInstr->pszReplacePattern, &pInstr->pszSearchPattern[pInstr->offPctSearchPattern], &pInstr->pszReplacePattern[pInstr->offPctReplacePattern]); if (pVar->recursive) free((void *)pszExpandedVarValue); } else warn_undefined(pInstr->pszName, strcache2_get_len(&variable_strcache, pInstr->pszName)); pInstrCore = pInstr->pNext; break; } case kKmkCcExpInstr_PlainFunction: { PKMKCCEXPPLAINFUNC pInstr = (PKMKCCEXPPLAINFUNC)pInstrCore; uint32_t iArg; if (!pInstr->FnCore.fDirty) { #ifdef KMK_CC_STRICT uint32_t uCrcBefore = 0; uint32_t uCrcAfter = 0; iArg = pInstr->FnCore.cArgs; while (iArg-- > 0) uCrcBefore = kmk_cc_debug_string_hash(uCrcBefore, pInstr->apszArgs[iArg]); #endif pchDst = pInstr->FnCore.pfnFunction(pchDst, (char **)&pInstr->apszArgs[0], pInstr->FnCore.pszFuncName); #ifdef KMK_CC_STRICT iArg = pInstr->FnCore.cArgs; while (iArg-- > 0) uCrcAfter = kmk_cc_debug_string_hash(uCrcAfter, pInstr->apszArgs[iArg]); KMK_CC_ASSERT(uCrcBefore == uCrcAfter); #endif } else { char **papszShadowArgs = xmalloc((pInstr->FnCore.cArgs * 2 + 1) * sizeof(papszShadowArgs[0])); char **papszArgs = &papszShadowArgs[pInstr->FnCore.cArgs]; iArg = pInstr->FnCore.cArgs; papszArgs[iArg] = NULL; while (iArg-- > 0) papszArgs[iArg] = papszShadowArgs[iArg] = xstrdup(pInstr->apszArgs[iArg]); pchDst = pInstr->FnCore.pfnFunction(pchDst, (char **)&pInstr->apszArgs[0], pInstr->FnCore.pszFuncName); iArg = pInstr->FnCore.cArgs; while (iArg-- > 0) free(papszShadowArgs[iArg]); free(papszShadowArgs); } pInstrCore = pInstr->FnCore.pNext; break; } case kKmkCcExpInstr_DynamicFunction: { PKMKCCEXPDYNFUNC pInstr = (PKMKCCEXPDYNFUNC)pInstrCore; char **papszArgsShadow = xmalloc( (pInstr->FnCore.cArgs * 2 + 1) * sizeof(char *)); char **papszArgs = &papszArgsShadow[pInstr->FnCore.cArgs]; uint32_t iArg; if (!pInstr->FnCore.fDirty) { #ifdef KMK_CC_STRICT uint32_t uCrcBefore = 0; uint32_t uCrcAfter = 0; #endif iArg = pInstr->FnCore.cArgs; papszArgs[iArg] = NULL; while (iArg-- > 0) { char *pszArg; if (pInstr->aArgs[iArg].fSubprog) pszArg = kmk_exec_expand_subprog_to_tmp(&pInstr->aArgs[iArg].u.Subprog, NULL); else pszArg = (char *)pInstr->aArgs[iArg].u.Plain.psz; papszArgsShadow[iArg] = pszArg; papszArgs[iArg] = pszArg; #ifdef KMK_CC_STRICT uCrcBefore = kmk_cc_debug_string_hash(uCrcBefore, pszArg); #endif } pchDst = pInstr->FnCore.pfnFunction(pchDst, papszArgs, pInstr->FnCore.pszFuncName); iArg = pInstr->FnCore.cArgs; while (iArg-- > 0) { #ifdef KMK_CC_STRICT KMK_CC_ASSERT(papszArgsShadow[iArg] == papszArgs[iArg]); uCrcAfter = kmk_cc_debug_string_hash(uCrcAfter, papszArgsShadow[iArg]); #endif if (pInstr->aArgs[iArg].fSubprog) free(papszArgsShadow[iArg]); } KMK_CC_ASSERT(uCrcBefore == uCrcAfter); } else { iArg = pInstr->FnCore.cArgs; papszArgs[iArg] = NULL; while (iArg-- > 0) { char *pszArg; if (pInstr->aArgs[iArg].fSubprog) pszArg = kmk_exec_expand_subprog_to_tmp(&pInstr->aArgs[iArg].u.Subprog, NULL); else pszArg = xstrdup(pInstr->aArgs[iArg].u.Plain.psz); papszArgsShadow[iArg] = pszArg; papszArgs[iArg] = pszArg; } pchDst = pInstr->FnCore.pfnFunction(pchDst, papszArgs, pInstr->FnCore.pszFuncName); iArg = pInstr->FnCore.cArgs; while (iArg-- > 0) free(papszArgsShadow[iArg]); } free(papszArgsShadow); pInstrCore = pInstr->FnCore.pNext; break; } case kKmkCcExpInstr_Jump: { PKMKCCEXPJUMP pInstr = (PKMKCCEXPJUMP)pInstrCore; pInstrCore = pInstr->pNext; break; } case kKmkCcExpInstr_Return: return pchDst; default: fatal(NULL, _("Unknown string expansion opcode: %d (%#x)"), (int)pInstrCore->enmOpcode, (int)pInstrCore->enmOpcode); return NULL; } } } /** * Updates the string expansion statistics. * * @param pStats The statistics structure to update. * @param cchResult The result lenght. */ void kmk_cc_exp_stats_update(PKMKCCEXPSTATS pStats, uint32_t cchResult) { /* * The average is simplified and not an exact average for every * expansion that has taken place. */ pStats->cchAvg = (pStats->cchAvg * 7 + cchResult) / 8; } /** * Execute a string expansion subprogram, outputting to a new heap buffer. * * @returns Pointer to the output buffer (hand to free when done). * @param pSubprog The subprogram to execute. * @param pcchResult Where to return the size of the result. Optional. */ static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubprog, uint32_t *pcchResult) { char *pchOldVarBuf; unsigned int cbOldVarBuf; char *pchDst; char *pszResult; uint32_t cchResult; /* * Temporarily replace the variable buffer while executing the instruction * stream for this subprogram. */ pchDst = install_variable_buffer_with_hint(&pchOldVarBuf, &cbOldVarBuf, pSubprog->Stats.cchAvg ? pSubprog->Stats.cchAvg + 32 : 256); pchDst = kmk_exec_expand_instruction_stream_to_var_buf(pSubprog->pFirstInstr, pchDst); /* Ensure that it's terminated. */ pchDst = variable_buffer_output(pchDst, "\0", 1) - 1; /* Grab the result buffer before restoring the previous one. */ pszResult = variable_buffer; cchResult = (uint32_t)(pchDst - pszResult); if (pcchResult) *pcchResult = cchResult; kmk_cc_exp_stats_update(&pSubprog->Stats, cchResult); variable_buffer = pchOldVarBuf; variable_buffer_length = cbOldVarBuf; return pszResult; } /** * Execute a string expansion program, outputting to the current variable * buffer. * * @returns New variable buffer position. * @param pProg The program to execute. * @param pchDst The current varaible buffer position. */ static char *kmk_exec_expand_prog_to_var_buf(PKMKCCEXPPROG pProg, char *pchDst) { uint32_t cchResult; uint32_t offStart = (uint32_t)(pchDst - variable_buffer); if (pProg->Stats.cchAvg >= variable_buffer_length - offStart) pchDst = ensure_variable_buffer_space(pchDst, offStart + pProg->Stats.cchAvg + 32); KMK_CC_ASSERT(pProg->cRefs > 0); pProg->cRefs++; pchDst = kmk_exec_expand_instruction_stream_to_var_buf(pProg->pFirstInstr, pchDst); pProg->cRefs--; KMK_CC_ASSERT(pProg->cRefs > 0); cchResult = (uint32_t)(pchDst - variable_buffer); KMK_CC_ASSERT(cchResult >= offStart); cchResult -= offStart; kmk_cc_exp_stats_update(&pProg->Stats, cchResult); g_cVarForExpandExecs++; return pchDst; } /** * Expands a variable into a variable buffer using its expandprog. * * @returns The new variable buffer position. * @param pVar Pointer to the variable. Must have a program. * @param pchDst Pointer to the current variable buffer position. */ char *kmk_exec_expand_to_var_buf(struct variable *pVar, char *pchDst) { KMK_CC_ASSERT(pVar->expandprog); KMK_CC_ASSERT(pVar->expandprog->uInputHash == kmk_cc_debug_string_hash(0, pVar->value)); return kmk_exec_expand_prog_to_var_buf(pVar->expandprog, pchDst); } /* * * Makefile evaluation programs. * Makefile evaluation programs. * Makefile evaluation programs. * */ static size_t kmk_cc_eval_detect_eol_style(char *pchFirst, char *pchSecond, const char *pszContent, size_t cchContent) { /* Look for LF first. */ const char *pszTmp = (const char *)memchr(pszContent, '\n', cchContent); if (pszTmp) { /* CRLF? */ if (pszTmp != pszContent && pszTmp[-1] == '\r') { *pchFirst = '\r'; *pchSecond = '\n'; return 2; } /* No, LF or LFCR. (pszContent is zero terminated, so no bounds checking necessary.) */ *pchFirst = '\n'; if (pszTmp[1] != '\r') { *pchSecond = 0; return 1; } *pchSecond = '\r'; return 2; } /* Probably no EOLs here. */ if (memchr(pszContent, '\r', cchContent) == NULL) { *pchSecond = *pchFirst = 0; return 0; } /* kind of unlikely */ *pchFirst = '\r'; *pchSecond = 0; return 1; } #if 0 /** * Checks whether we've got an EOL escape sequence or not. * * @returns non-zero if escaped EOL, 0 if not (i.e. actual EOL). * @param pszContent The string pointer @a offEol is relative to. * @param offEol The offset of the first EOL char. */ static unsigned kmk_cc_eval_is_eol_escape_seq(const char *pszContent, size_t offEol) { /* The caller has already checked out two backslashes. */ size_t offFirstBackslash = offEol; KMK_CC_ASSERT(offFirstBackslash >= 2); offFirstBackslash -= 2; /* Find the first backslash. */ while (offFirstBackslash > 0 && pszContent[offFirstBackslash - 1] == '\\') offFirstBackslash--; /* Odd number -> escaped EOL; Even number -> real EOL; */ return (offEol - offFirstBackslash) & 1; } #endif /** * Tokens (for KMKCCEVALWORD). */ typedef enum kmk_cc_eval_token { /** Invalid token value 0. */ kKmkCcEvalToken_Invalid = 0, /** Plain word. */ kKmkCcEvalToken_WordPlain, /** Plain word with one or more escaped EOLs. (Currently not possible.) */ kKmkCcEvalToken_WordPlainWithEscEol, /** Word that maybe in need of expanding. */ kKmkCcEvalToken_WordWithDollar, /** Word that is in need of expanding and include one or more escped EOLs. */ kKmkCcEvalToken_WordWithDollarAndEscEol, /** Recipe colon. */ kKmkCcEvalToken_colon, /** Recipe double colon. */ kKmkCcEvalToken_double_colon, /** Recipe multi target plus. */ kKmkCcEvalToken_plus, /** Recipe multi target plus-maybe (+|). */ kKmkCcEvalToken_plus_maybe, /** Recipe semicolon. */ kKmkCcEvalToken_semicolon, /** End of valid token values (not included). */ kKmkCcEvalToken_End } KMKCCEVALTOKEN; /** * A tokenized word. */ typedef struct kmk_cc_eval_word { /** The token word (lexeme). */ const char *pchWord; /** The length of the word (lexeme). */ uint32_t cchWord; /** The token classification. */ KMKCCEVALTOKEN enmToken; } KMKCCEVALWORD; typedef KMKCCEVALWORD *PKMKCCEVALWORD; typedef KMKCCEVALWORD const *PCKMKCCEVALWORD; /** * Escaped end-of-line sequence in the current line. */ typedef struct KMKCCEVALESCEOL { /** Offset at which the EOL escape sequence starts for a non-command line. */ size_t offEsc; /** Offset of the newline sequence. */ size_t offEol; } KMKCCEVALESCEOL; typedef KMKCCEVALESCEOL *PKMKCCEVALESCEOL; /** * String copy segment. */ typedef struct KMKCCEVALSTRCPYSEG { /** The start. */ const char *pchSrc; /** The number of chars to copy and whether to prepend space. * Negative values indicates that we should prepend a space. */ ssize_t cchSrcAndPrependSpace; } KMKCCEVALSTRCPYSEG; typedef KMKCCEVALSTRCPYSEG *PKMKCCEVALSTRCPYSEG; typedef KMKCCEVALSTRCPYSEG const *PCKMKCCEVALSTRCPYSEG; typedef struct KMKCCEVALCOMPILER { /** Pointer to the KMKCCEVALPROG::pBlockTail member. */ PKMKCCBLOCK *ppBlockTail; /** @name Line parsing state. * @{ */ /** Offset of newline escape sequences in the current line. * This is only applicable if cEscEols is not zero. */ PKMKCCEVALESCEOL paEscEols; /** The number of number of paEscEols entries we've allocated. */ unsigned cEscEolsAllocated; /** Number of escaped EOLs (line count - 1). */ unsigned cEscEols; /** The paEscEols entry corresponding to the current parsing location. * Still to be seen how accurate this can be made to be. */ unsigned iEscEol; /** The current line number for error handling / debugging (1-based). */ unsigned iLine; /** The start offset (into pchContent) of the current line. */ size_t offLine; /** Length of the current line, sans the final EOL and comments. */ size_t cchLine; /** Length of the current line, sans the final EOL but with comments. */ size_t cchLineWithComments; /** For 'define' only, the start offset of the next line. Modified to the * line following 'endef'. */ size_t offNext; /** The first char in an EOL sequence. * We ASSUMES that this char won't appear in any other sequence in the file, * thus skipping matching any subsequent chars. */ char chFirstEol; /** The second char in an EOL sequence, if applicable. */ char chSecondEol; /** The length of the EOL sequence. */ size_t cchEolSeq; /** The minimum length of an esacped EOL sequence (cchEolSeq + 1). */ size_t cchEscEolSeq; /** String copy segments. */ PKMKCCEVALSTRCPYSEG paStrCopySegs; /** The number of segments that has been prepared. */ unsigned cStrCopySegs; /** The number of segments we've allocated. */ unsigned cStrCopySegsAllocated; /** @} */ /** @name Recipe state. * @{ */ /** Set if we're working on a recipe. */ PKMKCCEVALRECIPE pRecipe; /** Set for ignoring recipes without targets (SunOS 4 Make). */ uint8_t fNoTargetRecipe; /** The command prefix character. */ char chCmdPrefix; /** @} */ /** @name Tokenzied words. * @{ */ unsigned cWords; unsigned cWordsAllocated; PKMKCCEVALWORD paWords; /** @} */ /** @name Conditionals. * @{ */ /** Current conditional stack depth. */ unsigned cIfs; /** The conditional directive stack. */ PKMKCCEVALIFCORE apIfs[KMK_CC_EVAL_MAX_IF_DEPTH]; /** @} */ /** The program being compiled. */ PKMKCCEVALPROG pEvalProg; /** Pointer to the content. */ const char *pszContent; /** The amount of input to parse. */ size_t cchContent; } KMKCCEVALCOMPILER; typedef KMKCCEVALCOMPILER *PKMKCCEVALCOMPILER; static void kmk_cc_eval_init_compiler(PKMKCCEVALCOMPILER pCompiler, PKMKCCEVALPROG pEvalProg, unsigned iLine, const char *pszContent, size_t cchContent) { pCompiler->ppBlockTail = &pEvalProg->pBlockTail; pCompiler->pRecipe = NULL; pCompiler->fNoTargetRecipe = 0; pCompiler->chCmdPrefix = cmd_prefix; pCompiler->cWordsAllocated = 0; pCompiler->paWords = NULL; pCompiler->cEscEolsAllocated = 0; pCompiler->paEscEols = NULL; pCompiler->iLine = iLine; pCompiler->cStrCopySegsAllocated = 0; pCompiler->paStrCopySegs = NULL; pCompiler->cIfs = 0; pCompiler->pEvalProg = pEvalProg; pCompiler->pszContent = pszContent; pCompiler->cchContent = cchContent; /* Detect EOL style. */ pCompiler->cchEolSeq = kmk_cc_eval_detect_eol_style(&pCompiler->chFirstEol, &pCompiler->chSecondEol, pszContent, cchContent); pCompiler->cchEscEolSeq = 1 + pCompiler->cchEolSeq; } static void kmk_cc_eval_delete_compiler(PKMKCCEVALCOMPILER pCompiler) { if (pCompiler->paWords) free(pCompiler->paWords); if (pCompiler->paEscEols) free(pCompiler->paEscEols); } /** * Translates a makefile source pointer to a line number and offset. * * @returns Line number (1-based) * @param pCompiler The compiler state. * @param pszWhere There location to translate. * @param piColumn Where to return the line offset (1-based). */ static unsigned kmk_cc_eval_translate_location(PKMKCCEVALCOMPILER pCompiler, const char *pchWhere, unsigned *piColumn) { unsigned iLine = pCompiler->iLine; size_t offLine = pCompiler->offLine; size_t off = pchWhere - pCompiler->pszContent; unsigned i = 0; while ( i < pCompiler->cEscEols && off > pCompiler->paEscEols[i].offEol) { offLine = pCompiler->paEscEols[i].offEol + 1 + pCompiler->cchEolSeq; iLine++; i++; } KMK_CC_ASSERT(off <= pCompiler->cchContent); if (piColumn) *piColumn = (unsigned)(off - offLine) + 1; return iLine; } static void KMK_CC_FN_NO_RETURN kmk_cc_eval_fatal(PKMKCCEVALCOMPILER pCompiler, const char *pchWhere, const char *pszMsg, ...) { va_list va; log_working_directory(1); /* * If we have a pointer location, use it to figure out the exact line and column. */ if (pchWhere) { unsigned iColumn; unsigned iLine = kmk_cc_eval_translate_location(pCompiler, pchWhere, &iColumn); if (pCompiler->pEvalProg->pszVarName) fprintf(stderr, "%s:%u:%u: *** fatal parsing error in %s: ", pCompiler->pEvalProg->pszFilename, iLine, iColumn, pCompiler->pEvalProg->pszVarName); else fprintf(stderr, "%s:%u:%u: *** fatal parsing error: ", pCompiler->pEvalProg->pszFilename, iLine, iColumn); } else if (pCompiler->pEvalProg->pszVarName) fprintf(stderr, "%s:%u: *** fatal parsing error in %s: ", pCompiler->pEvalProg->pszFilename, pCompiler->iLine, pCompiler->pEvalProg->pszVarName); else fprintf(stderr, "%s:%u: *** fatal parsing error: ", pCompiler->pEvalProg->pszFilename, pCompiler->iLine); /* * Print the message and die. */ va_start(va, pszMsg); vfprintf(stderr, pszMsg, va); va_end(va); fputs(". Stop.\n", stderr); for (;;) die(2); } static KMK_CC_FN_NO_RETURN void kmk_cc_eval_fatal_eol(PKMKCCEVALCOMPILER pCompiler, const char *pchEol, unsigned iLine, size_t offLine) { pCompiler->iLine = iLine; pCompiler->offLine = offLine; for (;;) kmk_cc_eval_fatal(pCompiler, pchEol, "Missing 2nd EOL character: found %#x instead of %#x\n", pchEol, pCompiler->chSecondEol); } static void kmk_cc_eval_warn(PKMKCCEVALCOMPILER pCompiler, const char *pchWhere, const char *pszMsg, ...) { va_list va; log_working_directory(1); /* * If we have a pointer location, use it to figure out the exact line and column. */ if (pchWhere) { unsigned iColumn; unsigned iLine = kmk_cc_eval_translate_location(pCompiler, pchWhere, &iColumn); if (pCompiler->pEvalProg->pszVarName) fprintf(stderr, "%s:%u:%u: *** warning in %s: ", pCompiler->pEvalProg->pszFilename, iLine, iColumn, pCompiler->pEvalProg->pszVarName); else fprintf(stderr, "%s:%u:%u: *** warning: ", pCompiler->pEvalProg->pszFilename, iLine, iColumn); } else if (pCompiler->pEvalProg->pszVarName) fprintf(stderr, "%s:%u: *** warning in %s: ", pCompiler->pEvalProg->pszFilename, pCompiler->iLine, pCompiler->pEvalProg->pszVarName); else fprintf(stderr, "%s:%u: *** warning: ", pCompiler->pEvalProg->pszFilename, pCompiler->iLine); /* * Print the message. */ va_start(va, pszMsg); vfprintf(stderr, pszMsg, va); va_end(va); fputs(".\n", stderr); } /** * Compiles a string expansion subprogram. * * @param pCompiler The compiler state. * @param pszExpr The expression to compile. * @param cchExpr The length of the expression. * @param pSubprog The subprogram to compile. */ static void kmk_cc_eval_compile_string_exp_subprog(PKMKCCEVALCOMPILER pCompiler, const char *pszExpr, size_t cchExpr, PKMKCCEXPSUBPROG pSubprog) { int rc = kmk_cc_exp_compile_subprog(pCompiler->ppBlockTail, pszExpr, cchExpr, pSubprog); if (rc == 0) return; kmk_cc_eval_fatal(pCompiler, NULL, "String expansion compile error"); } /** * Initializes a subprogam or plain operand structure. * * @param pCompiler The compiler state. * @param pOperand The subprogram or plain structure to init. * @param pszString The string. * @param cchString The length of the string. * @param fPlain Whether it's plain or not. If not, we'll compile it. */ static void kmk_cc_eval_init_subprogram_or_plain(PKMKCCEVALCOMPILER pCompiler, PKMKCCEXPSUBPROGORPLAIN pOperand, const char *pszString, size_t cchString, int fPlain) { pOperand->fPlainIsInVarStrCache = 0; pOperand->bUser = 0; pOperand->bUser2 = 0; pOperand->fSubprog = fPlain; if (fPlain) { pOperand->u.Plain.cch = cchString; pOperand->u.Plain.psz = pszString; } else kmk_cc_eval_compile_string_exp_subprog(pCompiler, pszString, cchString, &pOperand->u.Subprog); } /** * Initializes an array of subprogram-or-plain (spp) operands from a word array. * * The words will be duplicated and the caller must therefore call * kmk_cc_block_realign() when done (it's not done here as the caller may * initialize several string operands and we don't want any unnecessary * fragmentation). * * @param pCompiler The compiler state. * @param cWords The number of words to copy. * @param paSrc The source words. * @param paDst The destination subprogram-or-plain array. */ static void kmk_cc_eval_init_spp_array_from_duplicated_words(PKMKCCEVALCOMPILER pCompiler, unsigned cWords, PKMKCCEVALWORD paSrc, PKMKCCEXPSUBPROGORPLAIN paDst) { unsigned i; for (i = 0; i < cWords; i++) { const char *pszCopy = kmk_cc_block_strdup(pCompiler->ppBlockTail, paSrc[i].pchWord, paSrc[i].cchWord); paDst[i].fPlainIsInVarStrCache = 0; paDst[i].bUser = 0; paDst[i].bUser2 = 0; if (paSrc[i].enmToken == kKmkCcEvalToken_WordWithDollar) { paDst[i].fSubprog = 1; kmk_cc_block_realign(pCompiler->ppBlockTail); kmk_cc_eval_compile_string_exp_subprog(pCompiler, pszCopy, paSrc[i].cchWord, &paDst[i].u.Subprog); } else { paDst[i].fSubprog = 0; paDst[i].u.Plain.cch = paSrc[i].cchWord; paDst[i].u.Plain.psz = pszCopy; } KMK_CC_EVAL_DPRINTF((" %s\n", pszCopy)); } } /** @name KMK_CC_WORD_COMP_CONST_XXX - Optimal(/insane) constant work matching. * @{ */ #if (defined(KBUILD_ARCH_X86) || defined(KBUILD_ARCH_AMD64)) /* Unaligned access is reasonably cheap. */ \ && !defined(GCC_ADDRESS_SANITIZER) # define KMK_CC_WORD_COMP_CONST_2(a_pchLine, a_pszWord) \ ( *(uint16_t const *)(a_pchLine) == *(uint16_t const *)(a_pszWord) ) # define KMK_CC_WORD_COMP_CONST_3(a_pchLine, a_pszWord) \ ( *(uint16_t const *)(a_pchLine) == *(uint16_t const *)(a_pszWord) \ && (a_pchLine)[2] == (a_pszWord)[2] ) # define KMK_CC_WORD_COMP_CONST_4(a_pchLine, a_pszWord) \ ( *(uint32_t const *)(a_pchLine) == *(uint32_t const *)(a_pszWord) ) # define KMK_CC_WORD_COMP_CONST_5(a_pchLine, a_pszWord) \ ( *(uint32_t const *)(a_pchLine) == *(uint32_t const *)(a_pszWord) \ && (a_pchLine)[4] == (a_pszWord)[4] ) # define KMK_CC_WORD_COMP_CONST_6(a_pchLine, a_pszWord) \ ( *(uint32_t const *)(a_pchLine) == *(uint32_t const *)(a_pszWord) \ && ((uint16_t const *)(a_pchLine))[2] == ((uint16_t const *)(a_pszWord))[2] ) # define KMK_CC_WORD_COMP_CONST_7(a_pchLine, a_pszWord) \ ( *(uint32_t const *)(a_pchLine) == *(uint32_t const *)(a_pszWord) \ && ((uint16_t const *)(a_pchLine))[2] == ((uint16_t const *)(a_pszWord))[2] \ && (a_pchLine)[6] == (a_pszWord)[6] ) # define KMK_CC_WORD_COMP_CONST_8(a_pchLine, a_pszWord) \ ( *(uint64_t const *)(a_pchLine) == *(uint64_t const *)(a_pszWord) ) # define KMK_CC_WORD_COMP_CONST_10(a_pchLine, a_pszWord) \ ( *(uint64_t const *)(a_pchLine) == *(uint64_t const *)(a_pszWord) \ && ((uint16_t const *)(a_pchLine))[4] == ((uint16_t const *)(a_pszWord))[4] ) # define KMK_CC_WORD_COMP_CONST_16(a_pchLine, a_pszWord) \ ( *(uint64_t const *)(a_pchLine) == *(uint64_t const *)(a_pszWord) \ && ((uint64_t const *)(a_pchLine))[1] == ((uint64_t const *)(a_pszWord))[1] ) #else # define KMK_CC_WORD_COMP_CONST_2(a_pchLine, a_pszWord) \ ( (a_pchLine)[0] == (a_pszWord)[0] \ && (a_pchLine)[1] == (a_pszWord)[1] ) # define KMK_CC_WORD_COMP_CONST_3(a_pchLine, a_pszWord) \ ( (a_pchLine)[0] == (a_pszWord)[0] \ && (a_pchLine)[1] == (a_pszWord)[1] \ && (a_pchLine)[2] == (a_pszWord)[2] ) # define KMK_CC_WORD_COMP_CONST_4(a_pchLine, a_pszWord) \ ( (a_pchLine)[0] == (a_pszWord)[0] \ && (a_pchLine)[1] == (a_pszWord)[1] \ && (a_pchLine)[2] == (a_pszWord)[2] \ && (a_pchLine)[3] == (a_pszWord)[3] ) # define KMK_CC_WORD_COMP_CONST_5(a_pchLine, a_pszWord) \ ( (a_pchLine)[0] == (a_pszWord)[0] \ && (a_pchLine)[1] == (a_pszWord)[1] \ && (a_pchLine)[2] == (a_pszWord)[2] \ && (a_pchLine)[3] == (a_pszWord)[3] \ && (a_pchLine)[4] == (a_pszWord)[4] ) # define KMK_CC_WORD_COMP_CONST_6(a_pchLine, a_pszWord) \ ( (a_pchLine)[0] == (a_pszWord)[0] \ && (a_pchLine)[1] == (a_pszWord)[1] \ && (a_pchLine)[2] == (a_pszWord)[2] \ && (a_pchLine)[3] == (a_pszWord)[3] \ && (a_pchLine)[4] == (a_pszWord)[4] \ && (a_pchLine)[5] == (a_pszWord)[5] ) # define KMK_CC_WORD_COMP_CONST_7(a_pchLine, a_pszWord) \ ( (a_pchLine)[0] == (a_pszWord)[0] \ && (a_pchLine)[1] == (a_pszWord)[1] \ && (a_pchLine)[2] == (a_pszWord)[2] \ && (a_pchLine)[3] == (a_pszWord)[3] \ && (a_pchLine)[4] == (a_pszWord)[4] \ && (a_pchLine)[5] == (a_pszWord)[5] \ && (a_pchLine)[6] == (a_pszWord)[6] ) # define KMK_CC_WORD_COMP_CONST_8(a_pchLine, a_pszWord) \ ( (a_pchLine)[0] == (a_pszWord)[0] \ && (a_pchLine)[1] == (a_pszWord)[1] \ && (a_pchLine)[2] == (a_pszWord)[2] \ && (a_pchLine)[3] == (a_pszWord)[3] \ && (a_pchLine)[4] == (a_pszWord)[4] \ && (a_pchLine)[5] == (a_pszWord)[5] \ && (a_pchLine)[6] == (a_pszWord)[6] \ && (a_pchLine)[7] == (a_pszWord)[7] ) # define KMK_CC_WORD_COMP_CONST_10(a_pchLine, a_pszWord) \ ( (a_pchLine)[0] == (a_pszWord)[0] \ && (a_pchLine)[1] == (a_pszWord)[1] \ && (a_pchLine)[2] == (a_pszWord)[2] \ && (a_pchLine)[3] == (a_pszWord)[3] \ && (a_pchLine)[4] == (a_pszWord)[4] \ && (a_pchLine)[5] == (a_pszWord)[5] \ && (a_pchLine)[6] == (a_pszWord)[6] \ && (a_pchLine)[7] == (a_pszWord)[7] \ && (a_pchLine)[8] == (a_pszWord)[8] \ && (a_pchLine)[9] == (a_pszWord)[9] ) # define KMK_CC_WORD_COMP_CONST_16(a_pchLine, a_pszWord) \ ( (a_pchLine)[0] == (a_pszWord)[0] \ && (a_pchLine)[1] == (a_pszWord)[1] \ && (a_pchLine)[2] == (a_pszWord)[2] \ && (a_pchLine)[3] == (a_pszWord)[3] \ && (a_pchLine)[4] == (a_pszWord)[4] \ && (a_pchLine)[5] == (a_pszWord)[5] \ && (a_pchLine)[6] == (a_pszWord)[6] \ && (a_pchLine)[7] == (a_pszWord)[7] \ && (a_pchLine)[8] == (a_pszWord)[8] \ && (a_pchLine)[9] == (a_pszWord)[9] \ && (a_pchLine)[10] == (a_pszWord)[10] \ && (a_pchLine)[11] == (a_pszWord)[11] \ && (a_pchLine)[12] == (a_pszWord)[12] \ && (a_pchLine)[13] == (a_pszWord)[13] \ && (a_pchLine)[14] == (a_pszWord)[14] \ && (a_pchLine)[15] == (a_pszWord)[15]) #endif /** See if the given string match a constant string. */ #define KMK_CC_STRCMP_CONST(a_pchLeft, a_cchLeft, a_pszConst, a_cchConst) \ ( (a_cchLeft) == (a_cchConst) \ && KMK_CC_WORD_COMP_CONST_##a_cchConst(a_pchLeft, a_pszConst) ) /** See if a starting of a given length starts with a constant word. */ #define KMK_CC_EVAL_WORD_COMP_IS_EOL(a_pCompiler, a_pchLine, a_cchLine) \ ( (a_cchLine) == 0 \ || KMK_CC_EVAL_IS_SPACE((a_pchLine)[0]) \ || ((a_pchLine)[0] == '\\' && (a_pchLine)[1] == (a_pCompiler)->chFirstEol) ) \ /** See if a starting of a given length starts with a constant word. */ #define KMK_CC_EVAL_WORD_COMP_CONST(a_pCompiler, a_pchLine, a_cchLine, a_pszWord, a_cchWord) \ ( (a_cchLine) >= (a_cchWord) \ && ( (a_cchLine) == (a_cchWord) \ || KMK_CC_EVAL_IS_SPACE((a_pchLine)[a_cchWord]) \ || ((a_pchLine)[a_cchWord] == '\\' && (a_pchLine)[(a_cchWord) + 1] == (a_pCompiler)->chFirstEol) ) \ && KMK_CC_WORD_COMP_CONST_##a_cchWord(a_pchLine, a_pszWord) ) /** @} */ /** * Checks if a_ch is a space after a word. * * Since there is always a terminating zero, the user can safely access a char * beyond @a a_cchLeft. However, that byte isn't necessarily a zero terminator * character, so we have to check @a a_cchLeft whether we're at the end of the * parsing input string. * * @returns true / false. * @param a_pCompiler The compiler instance data. * @param a_ch The character to inspect. * @param a_ch2 The character following it, in case of escaped EOL. * @param a_cchLeft The number of chars left to parse (from @a a_ch). */ #define KMK_CC_EVAL_IS_SPACE_AFTER_WORD(a_pCompiler, a_ch, a_ch2, a_cchLeft) \ ( a_cchLeft == 0 \ || KMK_CC_EVAL_IS_SPACE(a_ch) \ || ((a_ch) == '\\' && (a_ch2) == (a_pCompiler)->chFirstEol) ) /** * Common path for space skipping worker functions when escaped EOLs may be * involed. * * @returns Points to the first non-space character or end of input. * @param pchWord The current position. There is some kind of char * @param cchLeft The current number of chars left to parse in the * current line. * @param pcchLeft Where to store the updated @a cchLeft value. * @param pCompiler The compiler instance data. */ static const char *kmk_cc_eval_skip_spaces_with_esc_eol(const char *pchWord, size_t cchLeft, size_t *pcchLeft, PKMKCCEVALCOMPILER pCompiler) { /* * Skip further spaces. We unrolls 4 loops here. * ASSUMES cchEscEolSeq is either 2 or 3! */ KMK_CC_ASSERT(pCompiler->cchEscEolSeq == 2 || pCompiler->cchEscEolSeq == 3); KMK_CC_ASSERT(pCompiler->iEscEol < pCompiler->cEscEols); while (cchLeft >= 4) { /* First char. */ char ch = pchWord[0]; if (KMK_CC_EVAL_IS_SPACE(ch)) { /* maybe likely */ } else if ( ch == '\\' && pchWord[1] == pCompiler->chFirstEol) { pchWord += pCompiler->cchEscEolSeq; cchLeft -= pCompiler->cchEscEolSeq; pCompiler->iEscEol++; continue; } else { *pcchLeft = cchLeft; return pchWord; } /* Second char. */ ch = pchWord[1]; if (KMK_CC_EVAL_IS_SPACE(ch)) { /* maybe likely */ } else if ( ch == '\\' && pchWord[2] == pCompiler->chFirstEol) { pchWord += 1 + pCompiler->cchEscEolSeq; cchLeft -= 1 + pCompiler->cchEscEolSeq; pCompiler->iEscEol++; continue; } else { *pcchLeft = cchLeft - 1; return pchWord + 1; } /* Third char. */ ch = pchWord[2]; if (KMK_CC_EVAL_IS_SPACE(ch)) { /* maybe likely */ } else if ( ch == '\\' && pchWord[3] == pCompiler->chFirstEol && cchLeft >= 2 + pCompiler->cchEscEolSeq) { pchWord += 2 + pCompiler->cchEscEolSeq; cchLeft -= 2 + pCompiler->cchEscEolSeq; pCompiler->iEscEol++; continue; } else { *pcchLeft = cchLeft - 2; return pchWord + 2; } /* Third char. */ ch = pchWord[3]; if (KMK_CC_EVAL_IS_SPACE(ch)) { pchWord += 4; cchLeft -= 4; } else if ( ch == '\\' && cchLeft >= 3 + pCompiler->cchEscEolSeq && pchWord[4] == pCompiler->chFirstEol) { pchWord += 3 + pCompiler->cchEscEolSeq; cchLeft -= 3 + pCompiler->cchEscEolSeq; pCompiler->iEscEol++; } else { *pcchLeft = cchLeft - 3; return pchWord + 3; } } /* * Simple loop for the final three chars. */ while (cchLeft > 0) { /* First char. */ char ch = *pchWord; if (KMK_CC_EVAL_IS_SPACE(ch)) { pchWord += 1; cchLeft -= 1; } else if ( ch == '\\' && cchLeft > pCompiler->cchEolSeq && pchWord[1] == pCompiler->chFirstEol) { pchWord += pCompiler->cchEscEolSeq; cchLeft -= pCompiler->cchEscEolSeq; pCompiler->iEscEol++; } else break; } *pcchLeft = cchLeft; return pchWord; } /** * Common path for space skipping worker functions when no escaped EOLs need * considering. * * @returns Points to the first non-space character or end of input. * @param pchWord The current position. There is some kind of char * @param cchLeft The current number of chars left to parse in the * current line. * @param pcchLeft Where to store the updated @a cchLeft value. * @param pCompiler The compiler instance data. */ static const char *kmk_cc_eval_skip_spaces_without_esc_eol(const char *pchWord, size_t cchLeft, size_t *pcchLeft, PKMKCCEVALCOMPILER pCompiler) { /* * 4x loop unroll. */ while (cchLeft >= 4) { if (KMK_CC_EVAL_IS_SPACE(pchWord[0])) { if (KMK_CC_EVAL_IS_SPACE(pchWord[1])) { if (KMK_CC_EVAL_IS_SPACE(pchWord[2])) { if (KMK_CC_EVAL_IS_SPACE(pchWord[3])) { pchWord += 4; cchLeft -= 4; } else { *pcchLeft = cchLeft - 3; return pchWord + 3; } } else { *pcchLeft = cchLeft - 2; return pchWord + 2; } } else { *pcchLeft = cchLeft - 1; return pchWord + 1; } } else { *pcchLeft = cchLeft; return pchWord; } } /* * The last 3. Not entirely sure if this yield good code. */ switch (cchLeft & 3) { case 3: if (!KMK_CC_EVAL_IS_SPACE(*pchWord)) break; pchWord++; cchLeft--; case 2: if (!KMK_CC_EVAL_IS_SPACE(*pchWord)) break; pchWord++; cchLeft--; case 1: if (!KMK_CC_EVAL_IS_SPACE(*pchWord)) break; pchWord++; cchLeft--; case 0: break; } *pcchLeft = cchLeft; return pchWord; } /** * Used to skip spaces after a word. * * We ASSUME that the first char is a space or that we've reached the end of the * string (a_cchLeft == 0). * * @param a_pCompiler The compiler instance data. * @param a_pchWord The current input position, this will be moved to * the start of the next word or end of the input. * @param a_cchLeft The number of chars left to parse. This will be * updated. */ #define KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(a_pCompiler, a_pchWord, a_cchLeft) \ do { \ /* Skip the first char which is known to be a space, end of line or end of input. */ \ if ((a_cchLeft) > 0) \ { \ char const chSkipBlanksFirst = *(a_pchWord); \ KMK_CC_ASSERT(KMK_CC_EVAL_IS_SPACE_AFTER_WORD(a_pCompiler, chSkipBlanksFirst, (a_pchWord)[1], a_cchLeft)); \ if (chSkipBlanksFirst != '\\') \ { \ (a_pchWord) += 1; \ (a_cchLeft) -= 1; \ \ /* Another space or escaped EOL? Then there are probably more then, so call worker function. */ \ if ((a_cchLeft) > 0) \ { \ char const chSkipBlanksSecond = *(a_pchWord); \ if (KMK_CC_EVAL_IS_SPACE_OR_BACKSLASH(chSkipBlanksSecond)) \ (a_pchWord) = kmk_cc_eval_skip_spaces_after_word_slow(a_pchWord, &(a_cchLeft), \ chSkipBlanksSecond, a_pCompiler); \ } \ } \ else /* escape sequences can be complicated. */ \ (a_pchWord) = kmk_cc_eval_skip_spaces_after_word_slow(a_pchWord, &(a_cchLeft), \ chSkipBlanksFirst, a_pCompiler); \ } \ } while (0) /** * The slow path of KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD. * * This is called to handles escaped EOL sequences, as these can involve * multiple backslashes and therefore doesn't led themselves well to inlined * code. * * The other case this is used for is to handle more than once space, since it's * likely that when there are two there might be more. No point in inlining * that, better do some loop unrolling instead. * * @returns Points to the first non-space character or end of input. * @param pchWord The current position. There is some kind of char * @param pcchLeft Pointer to the cchLeft variable, this is both * input and output. * @param ch The current character. * @param pCompiler The compiler instance data. */ static const char *kmk_cc_eval_skip_spaces_after_word_slow(const char *pchWord, size_t *pcchLeft, char ch, PKMKCCEVALCOMPILER pCompiler) { size_t cchLeft = *pcchLeft; /* * It's all very simple when we don't have to consider escaped EOLs. */ if (pCompiler->iEscEol >= pCompiler->cEscEols) { if (ch != '\\') { pchWord += 1; cchLeft -= 1; } else return pchWord; return kmk_cc_eval_skip_spaces_without_esc_eol(pchWord, cchLeft, pcchLeft, pCompiler); } /* * Skip the pending space or EOL found by the caller. We need to * confirm the EOL. * * Note! We only need to care about simple backslash+EOL sequences here * since we're either at the end of a validated word, or we've already * skipped one space. In the former case, someone else has already * validated the escape esequence, in the latter case multiple * backslashes would indicate a new word that that we should return. */ if (ch != '\\') { pchWord += 1; cchLeft -= 1; } else if ( cchLeft >= pCompiler->cchEscEolSeq && pchWord[1] == pCompiler->chFirstEol) { KMK_CC_ASSERT(pCompiler->cchEolSeq == 1 || pchWord[2] == pCompiler->chSecondEol); pchWord += pCompiler->cchEscEolSeq; cchLeft -= pCompiler->cchEscEolSeq; pCompiler->iEscEol++; if (pCompiler->iEscEol < pCompiler->cEscEols) { /* likely */ } else return kmk_cc_eval_skip_spaces_without_esc_eol(pchWord, cchLeft, pcchLeft, pCompiler); } else return pchWord; return kmk_cc_eval_skip_spaces_with_esc_eol(pchWord, cchLeft, pcchLeft, pCompiler); } /** * Skip zero or more spaces. * * This macro deals with a single space, if there are more or we're hittin some * possible escaped EOL sequence, work is deferred to a worker function. * * @param a_pCompiler The compiler state. * @param a_pchWord The current input position. Advanced past spaces. * @param a_cchLeft The amount of input left to parse. Will be updated. */ #define KMK_CC_EVAL_SKIP_SPACES(a_pCompiler, a_pchWord, a_cchLeft) \ do { \ if ((a_cchLeft) > 0) \ { \ char chSkipSpaces = *(a_pchWord); \ if (KMK_CC_EVAL_IS_SPACE_OR_BACKSLASH(chSkipSpaces)) \ { \ if (chSkipSpaces != '\\') \ { \ (a_pchWord) += 1; \ (a_cchLeft) -= 1; \ chSkipSpaces = *(a_pchWord); \ if (KMK_CC_EVAL_IS_SPACE_OR_BACKSLASH(chSkipSpaces)) \ (a_pchWord) = kmk_cc_eval_skip_spaces_slow(a_pchWord, &(a_cchLeft), chSkipSpaces, a_pCompiler); \ } \ else \ (a_pchWord) = kmk_cc_eval_skip_spaces_slow(a_pchWord, &(a_cchLeft), chSkipSpaces, a_pCompiler); \ } \ } \ } while (0) /** * Worker for KMK_CC_EVAL_SKIP_SPACES. * * @returns Points to the first non-space character or end of input. * @param pchWord The current position. There is some kind of char * @param pcchLeft Pointer to the cchLeft variable, this is both * input and output. * @param ch The current character. * @param pCompiler The compiler instance data. */ static const char *kmk_cc_eval_skip_spaces_slow(const char *pchWord, size_t *pcchLeft, char ch, PKMKCCEVALCOMPILER pCompiler) { size_t cchLeft = *pcchLeft; #ifdef KMK_CC_STRICT size_t offWordCcStrict = pchWord - pCompiler->pszContent; #endif KMK_CC_ASSERT(cchLeft > 0); KMK_CC_ASSERT(cchLeft <= pCompiler->cchLine); KMK_CC_ASSERT(*pchWord == ch); KMK_CC_ASSERT(KMK_CC_EVAL_IS_SPACE_OR_BACKSLASH(ch)); KMK_CC_ASSERT(offWordCcStrict >= pCompiler->offLine); KMK_CC_ASSERT(offWordCcStrict < pCompiler->offLine + pCompiler->cchLine); KMK_CC_ASSERT( pCompiler->iEscEol >= pCompiler->cEscEols || offWordCcStrict <= pCompiler->paEscEols[pCompiler->iEscEol].offEsc); KMK_CC_ASSERT( pCompiler->iEscEol >= pCompiler->cEscEols || pCompiler->iEscEol == 0 || offWordCcStrict >= pCompiler->paEscEols[pCompiler->iEscEol - 1].offEol + pCompiler->cchEolSeq); /* * If we don't need to consider escaped EOLs, things are much much simpler. */ if (pCompiler->iEscEol >= pCompiler->cEscEols) { if (ch != '\\') { pchWord++; cchLeft--; } else return pchWord; return kmk_cc_eval_skip_spaces_without_esc_eol(pchWord, cchLeft, pcchLeft, pCompiler); } /* * Possible escaped EOL complications. */ if (ch != '\\') { pchWord++; cchLeft--; } else { size_t cchSkip; size_t offWord; unsigned iEscEol = pCompiler->iEscEol; if (iEscEol >= pCompiler->cEscEols) return pchWord; offWord = pchWord - pCompiler->pszContent; if (offWord < pCompiler->paEscEols[iEscEol].offEsc) return pchWord; KMK_CC_ASSERT(offWord == pCompiler->paEscEols[iEscEol].offEsc); cchSkip = pCompiler->paEscEols[iEscEol].offEol + pCompiler->cchEolSeq - offWord; pchWord += cchSkip; cchLeft -= cchSkip; pCompiler->iEscEol = ++iEscEol; if (iEscEol < pCompiler->cEscEols) { /* likely */ } else return kmk_cc_eval_skip_spaces_without_esc_eol(pchWord, cchLeft, pcchLeft, pCompiler); } return kmk_cc_eval_skip_spaces_with_esc_eol(pchWord, cchLeft, pcchLeft, pCompiler); } #if 0 /* unused - probably forever. */ /** * Skips to the end of a variable name. * * This may advance pCompiler->iEscEol. * * @returns Pointer to the first char after the variable name. * @param pCompiler The compiler state. * @param pchWord The current position. Must be at the start of the * variable name. * @param cchLeft The number of chars left to parse in the current line. * @param pcchLeft The to store the updated count of characters left to * parse. * @param pfPlain Where to store the plain variable name indicator. * Returns 0 if plain, and 1 if there are variable * references in it. */ static const char *kmk_cc_eval_skip_var_name(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, size_t *pcchLeft, int *pfPlain) { const char * const pszContent = pCompiler->pszContent; size_t off = pchWord - pszContent; size_t const offLineEnd = off + cchLeft; int fPlain = 1; unsigned iEscEol = pCompiler->iEscEol; /* Check our expectations. */ KMK_CC_ASSERT(cchLeft); KMK_CC_ASSERT(!KMK_CC_EVAL_IS_SPACE(*pchWord)); KMK_CC_ASSERT(iEscEol <= pCompiler->cEscEols); KMK_CC_ASSERT( iEscEol >= pCompiler->cEscEols || off < pCompiler->paEscEols[iEscEol].offEol); KMK_CC_ASSERT(off >= (iEscEol == 0 ? pCompiler->offLine : pCompiler->paEscEols[iEscEol - 1].offEol + pCompiler->cchEolSeq)); /* * The outer loop parses plain text. Variable expansion ($) is handled * by the inner loop. */ while (off < offLineEnd) { char ch = pszContent[off]; if (!KMK_CC_EVAL_IS_SPACE_DOLLAR_OR_SLASH(ch)) off++; else if (KMK_CC_EVAL_IS_SPACE(ch)) break; else if (ch == '$') { off++; if (off < offLineEnd) { char const chOpen = pszContent[off]; if (chOpen == '(' || chOpen == '{') { /* * Got a $(VAR) or ${VAR} to deal with here. This may * include nested variable references and span multiple * lines (at least for function calls). * * We scan forward till we've found the corresponding * closing parenthesis, considering any open parentheses * of the same kind as worth counting, even if there are * no dollar preceeding them, just like GNU make does. */ size_t const offStart = off - 1; char const chClose = chOpen == '(' ? ')' : '}'; unsigned cOpen = 1; off++; for (;;) { if (off < offLineEnd) { ch = pszContent[off]; if (!(KMK_CC_EVAL_IS_PAREN_OR_SLASH(ch))) off++; else { off++; if (ch == chClose) { if (--cOpen == 0) break; } else if (ch == chOpen) cOpen++; else if ( ch == '\\' && iEscEol < pCompiler->cEscEols && off == pCompiler->paEscEols[iEscEol].offEsc) { off = pCompiler->paEscEols[iEscEol].offEol + pCompiler->cchEolSeq; pCompiler->iEscEol = ++iEscEol; } } } else if (cOpen == 1) kmk_cc_eval_fatal(pCompiler, &pszContent[offStart], "Variable reference is missing '%c'", chClose); else kmk_cc_eval_fatal(pCompiler, &pszContent[offStart], "%u variable references are missing '%c'", cOpen, chClose); } } /* Single char variable name. */ else if (!KMK_CC_EVAL_IS_SPACE(chOpen)) { /* likely */ } else kmk_cc_eval_fatal(pCompiler, &pszContent[off], "Expected variable name after '$', not end of line"); } else kmk_cc_eval_fatal(pCompiler, &pszContent[off], "Expected variable name after '$', not end of line"); fPlain = 0; } /* Deal with potential escaped EOL. */ else if ( ch != '\\' || iEscEol >= pCompiler->cEscEols || off != pCompiler->paEscEols[iEscEol].offEsc ) off++; else break; } *pcchLeft = offLineEnd - off; *pfPlain = fPlain; return &pszContent[off]; } #endif /* unused */ #if 0 /* unused atm */ /** * Prepares for copying a command line. * * The current version of this code will not modify any of the paEscEols * entries, unlike our kmk_cc_eval_prep_normal_line sibling function. * * @returns The number of chars that will be copied by * kmk_cc_eval_copy_prepped_command_line(). * @param pCompiler The compiler instance data. * @param pchLeft Pointer to the first char to copy from the current line. * This does not have to the start of a word. * @param cchLeft The number of chars left on the current line starting at * @a pchLeft. */ static size_t kmk_cc_eval_prep_command_line(PKMKCCEVALCOMPILER pCompiler, const char * const pchLeft, size_t cchLeft) { size_t cchRet; unsigned iEscEol = pCompiler->iEscEol; unsigned const cEscEols = pCompiler->cEscEols; KMK_CC_ASSERT(cchLeft > 0); KMK_CC_ASSERT(iEscEol <= cEscEols); if (iEscEol >= cEscEols) { /* * No escaped EOLs left, dead simple. */ cchRet = cchLeft; } else { /* * Compared to the normal prepping of a line, this is actually * really simple. We need to account for two kind of conversions: * - One leading tab is skipped after escaped EOL. * - Convert EOL to LF. */ const char * const pszContent = pCompiler->pszContent; size_t const cchEolSeq = pCompiler->cchEolSeq; #ifdef KMK_CC_STRICT size_t const offLeft = pchLeft - pszContent; KMK_CC_ASSERT(offLeft + cchLeft <= pCompiler->offLine + pCompiler->cchLine); KMK_CC_ASSERT(offLeft + cchLeft <= pCompiler->cchContent); KMK_CC_ASSERT(offLeft < pCompiler->paEscEols[iEscEol].offEsc); KMK_CC_ASSERT(offLeft >= (iEscEol ? pCompiler->paEscEols[cEscEols - 1].offEol + pCompiler->cchEolSeq : pCompiler->offLine)); #endif cchRet = cchLeft; if (cchEolSeq > 1) cchRet -= (cchEolSeq - 1) * cEscEols; do { if (pszContent[pCompiler->paEscEols[cchEolSeq].offEol]) cchRet--; iEscEol++; } while (iEscEol < cEscEols); } return cchRet; } /** * Copies a command line to the buffer @a pszDst points to. * * Must only be used immediately after kmk_cc_eval_prep_command_line(). * * @returns * @param pCompiler The compiler instance data. * @param pchLeft Pointer to the first char to copy from the current line. * This does not have to the start of a word. * @param cchPrepped The return value of kmk_cc_eval_prep_command_line(). * @param pszDst The destination buffer, must be at least @a cchPrepped * plus one (terminator) char big. */ static void kmk_cc_eval_copy_prepped_command_line(PKMKCCEVALCOMPILER pCompiler, const char *pchLeft, size_t cchPrepped, char *pszDst) { unsigned iEscEol = pCompiler->iEscEol; unsigned const cEscEols = pCompiler->cEscEols; if (iEscEol >= cEscEols) { /* Single line. */ memcpy(pszDst, pchLeft, cchPrepped); pszDst[cchPrepped] = '\0'; } else { /* Multiple lines with normalized EOL and maybe one stripped leading TAB. */ char * const pszDstStart = pszDst; const char * const pszContent = pCompiler->pszContent; size_t const cchEolSeq = pCompiler->cchEolSeq; size_t offLeft = pchLeft - pCompiler->pszContent; size_t cchCopy; do { size_t offEol = pCompiler->paEscEols[iEscEol].offEsc; cchCopy = offEol - offLeft; KMK_CC_ASSERT(offEol >= offLeft); memcpy(pszDst, &pszContent[offLeft], cchCopy); pszDst += cchCopy; *pszDst += '\n'; offLeft = offEol + cchEolSeq; if (pszContent[offLeft] == '\t') offLeft++; } while (iEscEol < cEscEols); cchCopy = cchPrepped - (pszDst - pszDstStart); KMK_CC_ASSERT(cchCopy <= cchPrepped); memcpy(pszDst, &pszContent[offLeft], cchCopy); pszDst += cchCopy; *pszDst = '\0'; KMK_CC_ASSERT(pszDst == &pszDstStart[cchPrepped]); } } #endif /* unused atm */ static size_t kmk_cc_eval_parse_var_exp(PKMKCCEVALCOMPILER pCompiler, const char *pch, size_t cchLeft, size_t off) { off++; if (off < cchLeft) { char const chOpen = pch[++off]; if (chOpen == '(' || chOpen == '{') { /* * Got a $(VAR) or ${VAR} to deal with here. This may include nested * variable references and span multiple lines (at least for function * calls). * * We scan forward till we've found the corresponding closing * parenthesis, considering any open parentheses of the same kind as * worth counting, even if there are no dollar preceeding them, just * like GNU make does. */ size_t const offStart = off - 1; char const chClose = chOpen == '(' ? ')' : '}'; unsigned cOpen = 1; off++; for (;;) { if (off < cchLeft) { char ch = pch[off]; if (!(KMK_CC_EVAL_IS_PAREN_OR_SLASH(ch))) off++; else { off++; if (ch == chClose) { if (--cOpen == 0) break; } else if (ch == chOpen) cOpen++; else if ( ch == '\\' && pCompiler->iEscEol < pCompiler->cEscEols && (size_t)(&pch[off] - pCompiler->pszContent) == pCompiler->paEscEols[pCompiler->iEscEol].offEsc) { off += pCompiler->paEscEols[pCompiler->iEscEol].offEol - pCompiler->paEscEols[pCompiler->iEscEol].offEsc + pCompiler->cchEolSeq; pCompiler->iEscEol++; } } } else if (cOpen == 1) kmk_cc_eval_fatal(pCompiler, &pch[offStart], "Variable reference is missing '%c'", chClose); else kmk_cc_eval_fatal(pCompiler, &pch[offStart], "%u variable references are missing '%c'", cOpen, chClose); } } /* Single char variable name. */ else if (!KMK_CC_EVAL_IS_SPACE(chOpen)) { /* likely */ } else kmk_cc_eval_fatal(pCompiler, &pch[off], "Expected variable name after '$', not space "); } else kmk_cc_eval_fatal(pCompiler, &pch[off], "Expected variable name after '$', end of line"); return off; } /** * Helper for ensuring that we've got sufficient number of words allocated. */ #define KMK_CC_EVAL_ENSURE_WORDS(a_pCompiler, a_cRequiredWords) \ do { \ if ((a_cRequiredWords) < (a_pCompiler)->cWordsAllocated) \ { /* likely */ } \ else \ { \ unsigned cEnsureWords = ((a_cRequiredWords) + 3 /*15*/) & ~(unsigned)3/*15*/; \ KMK_CC_ASSERT((a_cRequiredWords) < 0x8000); \ (a_pCompiler)->paWords = (PKMKCCEVALWORD)xrealloc((a_pCompiler)->paWords, \ cEnsureWords * sizeof((a_pCompiler)->paWords)[0]); \ } \ } while (0) /** * Word parser helper function for dealing with dollars, simple variant that * doesn't need to take multiple lines into account. * * @returns New word length placing us after the * @param pCompiler The compiler state. * @param cchWord Offset of the dollar into pchWord. * @param pchWord The word we're currently parsing. * @param cchLeft How much we've got left to parse. */ K_INLINE size_t kmk_cc_eval_parse_along_dollar_simple(PKMKCCEVALCOMPILER pCompiler, size_t cchWord, const char *pchWord, size_t cchLeft) { const size_t cchStart = cchWord; cchWord++; if (cchWord < cchLeft) { /* * Got a $(VAR) or ${VAR} to deal with here. This may include nested variable * references and span multiple lines (at least for function calls). * * We scan forward till we've found the corresponding closing parenthesis, * considering any open parentheses of the same kind as worth counting, even * if there are no dollar preceeding them, just like GNU make does. * * We leave the other parenthesis type to the expansion compiler to deal with. */ unsigned cOpens = 1; char const chOpen = pchWord[cchWord++]; if (chOpen == '(') { for (;;) { if (cchWord < cchLeft) { char const ch = pchWord[cchWord++]; if (!KMK_CC_EVAL_IS_PAREN_OR_SLASH(ch)) { /* likely */ } else if (ch == ')') { if (--cOpens == 0) return cchWord; } else if (ch == '(') cOpens++; } else break; } } else if (chOpen == '{') { for (;;) { if (cchWord < cchLeft) { char const ch = pchWord[cchWord++]; if (!KMK_CC_EVAL_IS_PAREN_OR_SLASH(ch)) { /* likely */ } else if (ch == '}') { if (--cOpens == 0) return cchWord; } else if (ch == '{') cOpens++; } else break; } } else return cchWord; /* Unterminated. */ if (cOpens == 1) kmk_cc_eval_fatal(pCompiler, &pchWord[cchStart], "Variable reference is missing '%c'", chOpen == '(' ? ')' : '}'); else kmk_cc_eval_fatal(pCompiler, &pchWord[cchStart], "%u variable references are missing '%c'", cOpens, chOpen == '(' ? ')' : '}'); } else kmk_cc_eval_warn(pCompiler, &pchWord[cchWord - 1], "found '$' at end of line"); return cchWord; } /** * Word parser helper function for dealing with dollars, complicated variant * that takes escaped EOLs into account. * * @returns New word length placing us after the * @param pCompiler The compiler state. * @param cchWord Offset of the dollar into pchWord. * @param pchWord The word we're currently parsing. * @param cchLeft How much we've got left to parse. */ static size_t kmk_cc_eval_parse_along_dollar_esc_eol(PKMKCCEVALCOMPILER pCompiler, size_t cchWord, const char *pchWord, size_t cchLeft) { const size_t cchStart = cchWord; cchWord++; if (cchWord < cchLeft) { /* * Got a $(VAR) or ${VAR} to deal with here. This may include nested variable * references and span multiple lines (at least for function calls). * * We scan forward till we've found the corresponding closing parenthesis, * considering any open parentheses of the same kind as worth counting, even * if there are no dollar preceeding them, just like GNU make does. * * We leave the other parenthesis type to the expansion compiler to deal with. */ unsigned cOpens = 1; char const chOpen = pchWord[cchWord++]; if (chOpen == '(') { for (;;) { if (cchWord < cchLeft) { char const ch = pchWord[cchWord++]; if (!KMK_CC_EVAL_IS_PAREN_OR_SLASH(ch)) { /* likely */ } else if (ch == ')') { if (--cOpens == 0) return cchWord; } else if (ch == '(') cOpens++; else if (ch == '\\') { unsigned const iEscEol = pCompiler->iEscEol; if ( iEscEol < pCompiler->cEscEols && (size_t)(&pchWord[cchWord] - pCompiler->pszContent) == pCompiler->paEscEols[iEscEol].offEsc) { cchWord += pCompiler->paEscEols[iEscEol].offEol - pCompiler->paEscEols[iEscEol].offEsc + pCompiler->cchEolSeq; pCompiler->iEscEol = iEscEol + 1; } } } else break; } } else if (chOpen == '{') { for (;;) { if (cchWord < cchLeft) { char const ch = pchWord[cchWord++]; if (!KMK_CC_EVAL_IS_PAREN_OR_SLASH(ch)) { /* likely */ } else if (ch == '}') { if (--cOpens == 0) return cchWord; } else if (ch == '{') cOpens++; else if (ch == '\\') { unsigned const iEscEol = pCompiler->iEscEol; if ( iEscEol < pCompiler->cEscEols && (size_t)(&pchWord[cchWord] - pCompiler->pszContent) == pCompiler->paEscEols[iEscEol].offEsc) { cchWord += pCompiler->paEscEols[iEscEol].offEol - pCompiler->paEscEols[iEscEol].offEsc + pCompiler->cchEolSeq; pCompiler->iEscEol = iEscEol + 1; } } } else break; } } else return cchWord; /* Unterminated. */ if (cOpens == 1) kmk_cc_eval_fatal(pCompiler, &pchWord[cchStart], "Variable reference is missing '%c'", chOpen == '(' ? ')' : '}'); else kmk_cc_eval_fatal(pCompiler, &pchWord[cchStart], "%u variable references are missing '%c'", cOpens, chOpen == '(' ? ')' : '}'); } else kmk_cc_eval_warn(pCompiler, &pchWord[cchWord - 1], "found '$' at end of line"); return cchWord; } /** * Parses the remainder of the line into simple words. * * The resulting words are classified as either kKmkCcEvalToken_WordPlain, * kKmkCcEvalToken_WordWithDollar, or kKmkCcEvalToken_WordWithDollarAndEscEol. * * @returns Number of words. * @param pCompiler The compiler state. * @param pchWord Where to start, we expect this to be at a word. * @param cchLeft The number of chars left to parse on this line. * This is expected to be non-zero. */ static unsigned kmk_cc_eval_parse_words(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft) { unsigned iEscEol = pCompiler->iEscEol; unsigned cEscEols = pCompiler->cEscEols; unsigned cWords = 0; /* Precoditions. */ KMK_CC_ASSERT(cchLeft > 0); KMK_CC_ASSERT(!KMK_CC_EVAL_IS_SPACE(*pchWord)); /* * If we don't have to deal with escaped EOLs, the find-end-of word search * becomes a little bit simpler. Since this function will be used a lot * for simple lines with single words, this could maybe save a nano second * or two. */ if (iEscEol >= cEscEols) { do { size_t cchSkipAfter = 0; size_t cchWord = 0; KMKCCEVALTOKEN enmToken = kKmkCcEvalToken_WordPlain; /* Find the end of the current word. */ while (cchWord < cchLeft) { char ch = pchWord[cchWord]; if (!KMK_CC_EVAL_IS_SPACE_OR_DOLLAR(ch)) cchWord++; else if (ch == '$') { #ifdef XXXX cchWord = kmk_cc_eval_parse_var_exp(pCompiler, pchWord, cchLeft, cchWord); enmToken = kKmkCcEvalToken_WordWithDollar; #else enmToken = kKmkCcEvalToken_WordWithDollar; cchWord = kmk_cc_eval_parse_along_dollar_simple(pCompiler, cchWord, pchWord, cchLeft); #endif } else break; } /* Add the word. */ KMK_CC_EVAL_ENSURE_WORDS(pCompiler, cWords + 1); pCompiler->paWords[cWords].pchWord = pchWord; pCompiler->paWords[cWords].cchWord = cchWord; pCompiler->paWords[cWords].enmToken = enmToken; cWords++; /* Skip the work and any trailing blanks. */ cchWord += cchSkipAfter; pchWord += cchWord; cchLeft -= cchWord; KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); } while (cchLeft > 0); } /* * Have to deal with escaped EOLs. */ else { const char *pszContent = pCompiler->pszContent; do { size_t cchSkipAfter = 0; size_t cchWord = 0; KMKCCEVALTOKEN enmToken = kKmkCcEvalToken_WordPlain; /* Find the end of the current word. */ while (cchWord < cchLeft) { char ch = pchWord[cchWord]; if (!KMK_CC_EVAL_IS_SPACE_DOLLAR_OR_SLASH(ch)) cchWord++; else if (ch == '$') #ifdef XXXX { const unsigned iEscEolBefore = pCompiler->iEscEol; cchWord = kmk_cc_eval_parse_var_exp(pCompiler, pchWord, cchLeft, cchWord); enmToken = pCompiler->iEscEol == iEscEolBefore ? kKmkCcEvalToken_WordWithDollar : kKmkCcEvalToken_WordWithDollarAndEscEol; } #else { enmToken = kKmkCcEvalToken_WordWithDollar; cchWord = kmk_cc_eval_parse_along_dollar_esc_eol(pCompiler, cchWord, pchWord, cchLeft); } #endif else if (ch != '\\') break; else if ((size_t)(&pchWord[cchWord] - pszContent) != pCompiler->paEscEols[iEscEol].offEsc) cchWord++; else { cchSkipAfter = pCompiler->paEscEols[iEscEol].offEol - pCompiler->paEscEols[iEscEol].offEsc + pCompiler->cchEolSeq; iEscEol++; break; } } /* Add the word. */ KMK_CC_EVAL_ENSURE_WORDS(pCompiler, cWords + 1); pCompiler->paWords[cWords].pchWord = pchWord; pCompiler->paWords[cWords].cchWord = cchWord; pCompiler->paWords[cWords].enmToken = enmToken; cWords++; /* Skip the work and any trailing blanks. */ cchWord += cchSkipAfter; pchWord += cchWord; cchLeft -= cchWord; KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); } while (cchLeft > 0); } pCompiler->cWords = cWords; return cWords; } /** * Parses the remainder of the line into target words. * * The resulting words are classified as either kKmkCcEvalToken_WordPlain or * kKmkCcEvalToken_WordWithDollar. * * @returns Number of words. * @param pCompiler The compiler state. * @param pchWord Where to start, we expect this to be at a word. * @param cchLeft The number of chars left to parse on this line. * This is expected to be non-zero. */ static unsigned kmk_cc_eval_parse_recipe_words(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft) { unsigned iEscEol = pCompiler->iEscEol; unsigned cEscEols = pCompiler->cEscEols; unsigned cWords = 0; /* Precoditions. */ KMK_CC_ASSERT(cchLeft > 0); KMK_CC_ASSERT(!KMK_CC_EVAL_IS_SPACE(*pchWord)); /* * If we don't have to deal with escaped EOLs, the find-end-of word search * becomes a little bit simpler. Since this function will be used a lot * for simple lines with single words, this could maybe save a nano second * or two. */ if (iEscEol >= cEscEols) { do { size_t cchSkipAfter = 0; size_t cchWord = 0; KMKCCEVALTOKEN enmToken = kKmkCcEvalToken_WordPlain; /* Find the end of the current word. */ while (cchWord < cchLeft) { char ch = pchWord[cchWord]; if (!KMK_CC_EVAL_IS_SPACE_OR_DOLLAR(ch)) cchWord++; else if (ch == '$') { enmToken = kKmkCcEvalToken_WordWithDollar; cchWord = kmk_cc_eval_parse_along_dollar_simple(pCompiler, cchWord, pchWord, cchLeft); } else break; } /* Add the word. */ KMK_CC_EVAL_ENSURE_WORDS(pCompiler, cWords + 1); pCompiler->paWords[cWords].pchWord = pchWord; pCompiler->paWords[cWords].cchWord = cchWord; pCompiler->paWords[cWords].enmToken = enmToken; cWords++; /* Skip the work and any trailing blanks. */ cchWord += cchSkipAfter; pchWord += cchWord; cchLeft -= cchWord; KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); } while (cchLeft > 0); } /* * Have to deal with escaped EOLs. */ else { const char *pszContent = pCompiler->pszContent; do { size_t cchSkipAfter = 0; size_t cchWord = 0; KMKCCEVALTOKEN enmToken = kKmkCcEvalToken_WordPlain; /* Find the end of the current word. */ while (cchWord < cchLeft) { char ch = pchWord[cchWord]; if (!KMK_CC_EVAL_IS_SPACE_DOLLAR_OR_SLASH(ch)) cchWord++; else if (ch == '$') { enmToken = kKmkCcEvalToken_WordWithDollar; cchWord = kmk_cc_eval_parse_along_dollar_esc_eol(pCompiler, cchWord, pchWord, cchLeft); } else if (ch != '\\') break; else if ((size_t)(&pchWord[cchWord] - pszContent) != pCompiler->paEscEols[iEscEol].offEsc) cchWord++; else { cchSkipAfter = pCompiler->paEscEols[iEscEol].offEol - pCompiler->paEscEols[iEscEol].offEsc + pCompiler->cchEolSeq; iEscEol++; break; } } /* Add the word. */ KMK_CC_EVAL_ENSURE_WORDS(pCompiler, cWords + 1); pCompiler->paWords[cWords].pchWord = pchWord; pCompiler->paWords[cWords].cchWord = cchWord; pCompiler->paWords[cWords].enmToken = enmToken; cWords++; /* Skip the work and any trailing blanks. */ cchWord += cchSkipAfter; pchWord += cchWord; cchLeft -= cchWord; KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); } while (cchLeft > 0); } pCompiler->cWords = cWords; return cWords; } /** * Gather string from segments and optional space insertion trick. * * @param pszDst The destination buffer. * @param paSegs The source segments. * @param cSegs The number of segments. * @param cchDstPrepped The size of pszDst, excluding the terminator. */ static void kmk_cc_eval_strcpyv(char *pszDst, PCKMKCCEVALSTRCPYSEG paSegs, unsigned cSegs, size_t cchDstPrepped) { const char *pszDstStart = pszDst; unsigned iSeg = 0; while (iSeg < cSegs) { size_t cchToCopy; if (paSegs[iSeg].cchSrcAndPrependSpace >= 0) cchToCopy = paSegs[iSeg].cchSrcAndPrependSpace; else { cchToCopy = -paSegs[iSeg].cchSrcAndPrependSpace; *pszDst++ = ' '; } memcpy(pszDst, paSegs[iSeg].pchSrc, cchToCopy); pszDst += cchToCopy; iSeg++; } *pszDst = '\0'; KMK_CC_ASSERT(pszDst == &pszDstStart[cchDstPrepped]); K_NOREF(pszDstStart); K_NOREF(cchDstPrepped); } /** * Allocate a byte buffer and ocpy the prepared string segments into it. * * The caller must call kmk_cc_block_realign! * * @returns Pointer to the duplicated string. * @param pCompiler The compiler instance data. * @param cchPrepped The length of the prepped string segments. */ static char *kmk_cc_eval_strdup_prepped(PKMKCCEVALCOMPILER pCompiler, size_t cchPrepped) { char *pszCopy = kmk_cc_block_byte_alloc(pCompiler->ppBlockTail, cchPrepped + 1); kmk_cc_eval_strcpyv(pszCopy, pCompiler->paStrCopySegs, pCompiler->cStrCopySegs, cchPrepped); return pszCopy; } /** * Strip trailing spaces from prepped copy * * @param paSegs The segments to strip trailing chars from. * @param pcSegs The number of segments (in/out). * @param pcchDstPrepped The total number of chars prepped (in/out). */ static void kmk_cc_eval_strip_right_v(PKMKCCEVALSTRCPYSEG paSegs, unsigned *pcSegs, size_t *pcchDstPrepped) { /* * Work our way thru the segments, from the end obviously. */ size_t cchDstPrepped = *pcchDstPrepped; unsigned cSegs = *pcSegs; while (cSegs > 0) { unsigned iSeg = cSegs - 1; const char *pszSrc = paSegs[iSeg].pchSrc; size_t cchSrc = paSegs[iSeg].cchSrcAndPrependSpace >= 0 ? paSegs[iSeg].cchSrcAndPrependSpace : -paSegs[iSeg].cchSrcAndPrependSpace; if (cchSrc) { /* * Check for trailing spaces. */ size_t cchSrcOrg; if (!KMK_CC_EVAL_IS_SPACE(pszSrc[cchSrc - 1])) { /* Special case: No trailing spaces at all. No need to update input/output variables. */ if (cSegs == *pcSegs) return; break; } /* Skip the rest of the trailing spaces. */ cchSrcOrg = cchSrc; do cchSrc--; while (cchSrc > 0 && KMK_CC_EVAL_IS_SPACE(pszSrc[cchSrc - 1])); if (cchSrc > 0) { /* * There are non-space chars in this segment. So, update the * segment and total char count and we're done. */ cchDstPrepped -= cchSrcOrg - cchSrc; if (paSegs[iSeg].cchSrcAndPrependSpace < 0) paSegs[iSeg].cchSrcAndPrependSpace = -(ssize_t)cchSrc; else paSegs[iSeg].cchSrcAndPrependSpace = cchSrc; break; } /* * Skip the whole segment. */ cchDstPrepped -= cchSrcOrg + (paSegs[iSeg].cchSrcAndPrependSpace < 0); } cSegs--; } *pcchDstPrepped = cchDstPrepped; *pcSegs = cSegs; } /** * Helper for ensuring that we've got sufficient number of string copy segments. */ #define KMK_CC_EVAL_ENSURE_STRCOPY_SEGS(a_pCompiler, a_cRequiredSegs) \ do { \ if ((a_cRequiredSegs) < (a_pCompiler)->cStrCopySegsAllocated) \ { /* likely */ } \ else \ { \ unsigned cEnsureSegs = ((a_cRequiredSegs) + 3 /*15*/) & ~(unsigned)3/*15*/; \ KMK_CC_ASSERT((a_cRequiredSegs) < 0x8000); \ (a_pCompiler)->paStrCopySegs = (PKMKCCEVALSTRCPYSEG)xmalloc(cEnsureSegs * sizeof((a_pCompiler)->paStrCopySegs)[0]); \ } \ } while (0) /** * Prepares for copying a normal line, extended version. * * This does not assume that we start on a word, it can handle any starting * character. It can also prepare partial copies. * * In addition to the returned information, this will store instruction in * paEscEols for the following kmk_cc_eval_strcpyv() call. * * This will advance pCompiler->iEscEol, so that it's possible to use the common * macros and helpers for parsing what comes afterwards. * * @returns The number of chars that will be copied by kmk_cc_eval_strcpyv(). * @param pCompiler The compiler instance data. * @param pchWord Pointer to the first char to copy from the * current line. This must be the start of a * word. * @param cchLeft The number of chars left on the current line * starting at @a pchWord. */ static size_t kmk_cc_eval_prep_normal_line_ex(PKMKCCEVALCOMPILER pCompiler, const char * const pchWord, size_t cchLeft) { size_t cchRet; unsigned iEscEol = pCompiler->iEscEol; unsigned const cEscEols = pCompiler->cEscEols; KMK_CC_ASSERT(iEscEol <= cEscEols); if (cchLeft > 0) { /* * If there are no escaped EOLs left, just copy exactly * what was passed in. */ if (iEscEol >= cEscEols) { KMK_CC_EVAL_ENSURE_STRCOPY_SEGS(pCompiler, 1); pCompiler->cStrCopySegs = 1; pCompiler->paStrCopySegs[0].pchSrc = pchWord; pCompiler->paStrCopySegs[0].cchSrcAndPrependSpace = cchRet = cchLeft; } /* * Ok, we have to deal with escaped EOLs and do the proper * replacement of escaped newlines with space. The deal is that we * collaps all whitespace before and after one or more newlines into a * single space. (FreeBSD make does this differently, by the by.) */ else { const char * const pszContent = pCompiler->pszContent; size_t offWord = pchWord - pCompiler->pszContent; size_t const offLineEnd = offWord + cchLeft; /* Note! Not necessarily end of line.*/ size_t offEsc; size_t fPendingSpace = 0; unsigned cSegs = 0; size_t cchSeg; /* Go nuts checking our preconditions here. */ KMK_CC_ASSERT(offWord >= pCompiler->offLine); KMK_CC_ASSERT(offWord + cchLeft <= pCompiler->offLine + pCompiler->cchLine); KMK_CC_ASSERT(offWord + cchLeft <= pCompiler->cchContent); KMK_CC_ASSERT(offWord <= pCompiler->paEscEols[iEscEol].offEsc); KMK_CC_ASSERT(offWord >= (iEscEol ? pCompiler->paEscEols[cEscEols - 1].offEol + pCompiler->cchEolSeq : pCompiler->offLine)); KMK_CC_ASSERT(offWord < offLineEnd); /* Make sure we've got more than enough segments to fill in. */ KMK_CC_EVAL_ENSURE_STRCOPY_SEGS(pCompiler, cEscEols - iEscEol + 2); /* * All but the last line. */ cchRet = 0; do { KMK_CC_ASSERT(offWord < offLineEnd); offEsc = pCompiler->paEscEols[iEscEol].offEsc; if (offWord < offEsc) { /* Strip trailing spaces. */ while (offEsc > offWord && KMK_CC_EVAL_IS_SPACE(pszContent[offEsc - 1])) offEsc--; cchSeg = offEsc - offWord; if (cchSeg) { /* Add segment. */ pCompiler->paStrCopySegs[cSegs].pchSrc = &pszContent[offWord]; if (offEsc < offLineEnd) { pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = fPendingSpace ? -(ssize_t)cchSeg : (ssize_t)cchSeg; cchRet += cchSeg + fPendingSpace; cSegs += 1; fPendingSpace = 1; } else { cchSeg = offLineEnd - offWord; pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = fPendingSpace ? -(ssize_t)cchSeg : (ssize_t)cchSeg; pCompiler->cStrCopySegs = cSegs + 1; pCompiler->iEscEol = iEscEol; return cchRet + cchSeg + fPendingSpace; } } } else KMK_CC_ASSERT(offWord == offEsc); /* Next line. */ offWord = pCompiler->paEscEols[iEscEol].offEol + pCompiler->cchEolSeq; iEscEol++; /* Strip leading spaces. */ while (offWord < offLineEnd && KMK_CC_EVAL_IS_SPACE(pszContent[offWord])) offWord++; if (offWord >= offLineEnd) { pCompiler->cStrCopySegs = cSegs; pCompiler->iEscEol = iEscEol; return cchRet; } } while (iEscEol < cEscEols); /* * The last line. */ cchSeg = offLineEnd - offWord; cchRet += cchSeg; pCompiler->paStrCopySegs[cSegs].pchSrc = &pszContent[offWord]; pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = fPendingSpace ? -(ssize_t)cchSeg : (ssize_t)cchSeg; pCompiler->cStrCopySegs = cSegs + 1; pCompiler->iEscEol = iEscEol; } } /* * Odd case: Nothing to copy. */ else { cchRet = 0; pCompiler->cStrCopySegs = 0; } return cchRet; } /** * Prepares for copying a normal line, from the given position all the way to * the end. * * In addition to the returned information, this will store instruction in * paStrCopySegs and cSTrCopySeg for the following kmk_cc_eval_strcpyv() call. * * @returns The number of chars that will be copied by kmk_cc_eval_strcpyv(). * @param pCompiler The compiler instance data. * @param pchWord Pointer to the first char to copy from the * current line. This must be the start of a * word. * @param cchLeft The number of chars left on the current line * starting at @a pchWord. */ static size_t kmk_cc_eval_prep_normal_line(PKMKCCEVALCOMPILER pCompiler, const char * const pchWord, size_t cchLeft) { size_t cchRet; unsigned iEscEol = pCompiler->iEscEol; unsigned const cEscEols = pCompiler->cEscEols; KMK_CC_ASSERT(cchLeft > 0); KMK_CC_ASSERT(!KMK_CC_EVAL_IS_SPACE(*pchWord)); /* The fact that we're standing at a word, is exploited below. */ KMK_CC_ASSERT(iEscEol <= cEscEols); /* * If there are no escaped EOLs left, just copy what was specified, * optionally sans any trailing spaces. */ if (iEscEol >= cEscEols) { cchRet = cchLeft; KMK_CC_EVAL_ENSURE_STRCOPY_SEGS(pCompiler, 1); pCompiler->cStrCopySegs = 1; pCompiler->paStrCopySegs[0].pchSrc = pchWord; pCompiler->paStrCopySegs[0].cchSrcAndPrependSpace = cchRet; } /* * Ok, we have to deal with escaped EOLs and do the proper * replacement of escaped newlines with space. The deal is that we * collaps all whitespace before and after one or more newlines into a * single space. (FreeBSD make does this differently, by the by.) */ else { const char *pszContent = pCompiler->pszContent; size_t offWord = pchWord - pCompiler->pszContent; size_t offEsc; size_t fPendingSpace; size_t cchSeg; unsigned cSegs = 0; /* Go nuts checking our preconditions here. */ KMK_CC_ASSERT(offWord >= pCompiler->offLine); KMK_CC_ASSERT(offWord + cchLeft <= pCompiler->offLine + pCompiler->cchLine); KMK_CC_ASSERT(offWord + cchLeft <= pCompiler->cchContent); KMK_CC_ASSERT(offWord < pCompiler->paEscEols[iEscEol].offEsc); KMK_CC_ASSERT(offWord >= (iEscEol ? pCompiler->paEscEols[iEscEol - 1].offEol + pCompiler->cchEolSeq : pCompiler->offLine)); /* Make sure we've got more than enough segments to fill in. */ KMK_CC_EVAL_ENSURE_STRCOPY_SEGS(pCompiler, cEscEols - iEscEol + 2); /* * First line - We're at the start of a word, so no left stripping needed. */ offEsc = pCompiler->paEscEols[iEscEol].offEsc; KMK_CC_ASSERT(offEsc > offWord); while (KMK_CC_EVAL_IS_SPACE(pszContent[offEsc - 1])) offEsc--; KMK_CC_ASSERT(offEsc > offWord); fPendingSpace = 1; cchRet = offEsc - offWord; pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = cchRet; pCompiler->paStrCopySegs[cSegs].pchSrc = pchWord; cSegs++; offWord = pCompiler->paEscEols[iEscEol].offEol + pCompiler->cchEolSeq; iEscEol++; /* * All but the last line. */ while (iEscEol < cEscEols) { offEsc = pCompiler->paEscEols[iEscEol].offEsc; /* Strip leading spaces. */ while (offWord < offEsc && KMK_CC_EVAL_IS_SPACE(pszContent[offWord])) offWord++; if (offWord < offEsc) { /* Strip trailing spaces. */ while (KMK_CC_EVAL_IS_SPACE(pszContent[offEsc - 1])) offEsc--; cchSeg = offEsc - offWord; pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = fPendingSpace ? -(ssize_t)cchSeg : (ssize_t)cchSeg; cchRet += cchSeg + fPendingSpace; pCompiler->paStrCopySegs[cSegs].pchSrc = &pszContent[offWord]; cSegs += 1; fPendingSpace = 1; } /* Next. */ offWord = pCompiler->paEscEols[iEscEol].offEol + pCompiler->cchEolSeq; iEscEol++; } /* * Final line. We must calculate the end of line offset our selves here. */ offEsc = &pchWord[cchLeft] - pszContent; while (offWord < offEsc && KMK_CC_EVAL_IS_SPACE(pszContent[offWord])) offWord++; if (offWord < offEsc) { cchSeg = offEsc - offWord; pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = fPendingSpace ? -(ssize_t)cchSeg : (ssize_t)cchSeg; cchRet += cchSeg + fPendingSpace; pCompiler->paStrCopySegs[cSegs].pchSrc = &pszContent[offWord]; cSegs += 1; } pCompiler->cStrCopySegs = cSegs; } return cchRet; } /** * Common worker for all kmk_cc_eval_do_if*() functions. * * @param pCompiler The compiler state. * @param pIfCore The new IF statement. * @param fInElse Set if this is an 'else if' (rather than just 'if'). */ static void kmk_cc_eval_do_if_core(PKMKCCEVALCOMPILER pCompiler, PKMKCCEVALIFCORE pIfCore, int fInElse) { unsigned iIf = pCompiler->cIfs; if (!fInElse) { /* Push an IF statement. */ if (iIf < KMK_CC_EVAL_MAX_IF_DEPTH) { pCompiler->cIfs = iIf + 1; pCompiler->apIfs[iIf] = pIfCore; pIfCore->pPrevCond = NULL; } else kmk_cc_eval_fatal(pCompiler, NULL, "Too deep IF nesting"); } else if (iIf > 0) { /* Link an IF statement. */ iIf--; pIfCore->pPrevCond = pCompiler->apIfs[iIf]; pCompiler->apIfs[iIf] = pIfCore; } else kmk_cc_eval_fatal(pCompiler, NULL, "'else if' without 'if'"); pIfCore->pNextTrue = (PKMKCCEVALCORE)kmk_cc_block_get_next_ptr(*pCompiler->ppBlockTail); pIfCore->pNextFalse = NULL; /* This is set by else or endif. */ pIfCore->pTrueEndJump = NULL; /* This is set by else or endif. */ } /** * Deals with 'if expr' and 'else if expr' statements. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord First char after 'if'. * @param cchLeft The number of chars left to parse on this line. * @param fInElse Set if this is an 'else if' (rather than just 'if'). */ static int kmk_cc_eval_do_if(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, int fInElse) { KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (cchLeft) { PKMKCCEVALIFEXPR pInstr; size_t cchExpr = kmk_cc_eval_prep_normal_line(pCompiler, pchWord, cchLeft); kmk_cc_eval_strip_right_v(pCompiler->paStrCopySegs, &pCompiler->cStrCopySegs, &cchExpr); pInstr = (PKMKCCEVALIFEXPR)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, KMKCCEVALIFEXPR_SIZE(cchExpr)); kmk_cc_eval_strcpyv(pInstr->szExpr, pCompiler->paStrCopySegs, pCompiler->cStrCopySegs, cchExpr); pInstr->cchExpr = cchExpr; pInstr->IfCore.Core.enmOpcode = kKmkCcEvalInstr_if; pInstr->IfCore.Core.iLine = pCompiler->iLine; kmk_cc_eval_do_if_core(pCompiler, &pInstr->IfCore, fInElse); } else kmk_cc_eval_fatal(pCompiler, pchWord, "Expected expression after 'if' directive"); return 1; } /** * Deals with 'ifdef var', 'ifndef var', 'else ifdef var' and 'else ifndef var' * statements. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord First char after 'if[n]def'. * @param cchLeft The number of chars left to parse on this line. * @param fInElse Set if this is an 'else if' (rather than just 'if'). * @param fPositiveStmt Set if 'ifdef', clear if 'ifndef'. */ static int kmk_cc_eval_do_ifdef(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, int fInElse, int fPositiveStmt) { KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (cchLeft) { /* * Skip to the end of the variable name. * GNU make just does normal word parsing, so lets do that too. */ unsigned const iSavedEscEol = pCompiler->iEscEol; unsigned cWords = kmk_cc_eval_parse_words(pCompiler, pchWord, cchLeft); if (cWords == 0) { PCKMKCCEVALWORD pWord = pCompiler->paWords; if (pWord->enmToken == kKmkCcEvalToken_WordPlain) { PKMKCCEVALIFDEFPLAIN pInstr; pInstr = (PKMKCCEVALIFDEFPLAIN)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr)); pInstr->IfCore.Core.enmOpcode = fPositiveStmt ? kKmkCcEvalInstr_ifdef_plain : kKmkCcEvalInstr_ifndef_plain; pInstr->IfCore.Core.iLine = pCompiler->iLine; pInstr->pszName = strcache2_add(&variable_strcache, pWord->pchWord, pWord->cchWord); kmk_cc_eval_do_if_core(pCompiler, &pInstr->IfCore, fInElse); } else { PKMKCCEVALIFDEFDYNAMIC pInstr; size_t cchCopy; char const *pszCopy; pInstr = (PKMKCCEVALIFDEFDYNAMIC)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr)); /** @todo Make the subprogram embed necessary strings. */ if (pWord->enmToken != kKmkCcEvalToken_WordWithDollar) { pszCopy = kmk_cc_block_strdup(pCompiler->ppBlockTail, pWord->pchWord, pWord->cchWord); cchCopy = pWord->cchWord; } else { KMK_CC_ASSERT(pWord->enmToken == kKmkCcEvalToken_WordWithDollarAndEscEol); pCompiler->iEscEol = iSavedEscEol; cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pWord->pchWord, cchLeft); pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, cchCopy); } kmk_cc_block_realign(pCompiler->ppBlockTail); pInstr->IfCore.Core.enmOpcode = fPositiveStmt ? kKmkCcEvalInstr_ifdef_dynamic : kKmkCcEvalInstr_ifndef_dynamic; pInstr->IfCore.Core.iLine = pCompiler->iLine; pInstr->uPadding = 0; kmk_cc_eval_compile_string_exp_subprog(pCompiler, pszCopy, cchCopy, &pInstr->NameSubprog); kmk_cc_eval_do_if_core(pCompiler, &pInstr->IfCore, fInElse); } } else { KMK_CC_ASSERT(cWords > 1); kmk_cc_eval_fatal(pCompiler, pCompiler->paWords[1].pchWord, "Bogus stuff after 'if%sdef' variable name", fPositiveStmt ? "" : "n"); } } else kmk_cc_eval_fatal(pCompiler, pchWord, "Expected expression after 'if' directive"); return 1; } /** * Deals with 'ifeq (a,b)', 'ifeq "a" "b"', 'ifneq (a,b)', 'ifneq "a" "b"', * 'else ifeq (a,b)', 'else ifeq "a" "b"', 'else ifneq (a,b)' and * 'else ifneq "a" "b"' statements. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord First char after 'if[n]eq'. * @param cchLeft The number of chars left to parse on this line. * @param fInElse Set if this is an 'else if' (rather than just 'if'). * @param fPositiveStmt Set if 'ifeq', clear if 'ifneq'. */ static int kmk_cc_eval_do_ifeq(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, int fInElse, int fPositiveStmt) { KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (cchLeft) { /* * There are two forms: * * ifeq (string1, string2) * ifeq "string1" 'string2' * */ const char * const pchEnd = &pchWord[cchLeft]; PKMKCCEVALIFEQ pInstr = (PKMKCCEVALIFEQ)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr)); struct { char *pszCopy; size_t cchCopy; int fPlain; } Left, Right; char ch = *pchWord; if (ch == '(') { int cCounts; size_t off; /* * The left side ends with a comma. We respect parentheses, but * not curly brackets. */ /* Skip the parenthesis. */ pchWord++; cchLeft--; /* Find the comma, checking for non-plainness. */ cCounts = 0; Left.fPlain = 1; for (off = 0; off < cchLeft; off++) { ch = pchWord[off]; if (!KMK_CC_EVAL_IS_PAREN_COMMA_OR_DOLLAR(ch)) { /* likely */ } else if (ch == '$') Left.fPlain = 0; else if (ch == '(') cCounts++; else if (ch == ')') cCounts--; /** @todo warn if it goes negative. */ else if (ch == ',' && cCounts == 0) break; else KMK_CC_ASSERT(cCounts > 0); } if (ch == ',' && cCounts == 0) { /* likely */ } else kmk_cc_eval_fatal(pCompiler, &pchWord[off], "Expected ',' before end of line"); /* Copy out the string. */ Left.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, off); kmk_cc_eval_strip_right_v(pCompiler->paStrCopySegs, &pCompiler->cStrCopySegs, &Left.cchCopy); Left.pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, Left.cchCopy); /* Skip past the comma and any following spaces. */ pchWord += off + 1; cchLeft -= off + 1; if ( cchLeft /** @todo replace with straight 'isspace' that takes escaped EOLs into account. */ && KMK_CC_EVAL_IS_SPACE_AFTER_WORD(pCompiler, pchWord[0], pchWord[1], cchLeft)) KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); /* * Ditto for the right side, only it ends with a closing parenthesis. */ cCounts = 1; Right.fPlain = 1; for (off = 0; off < cchLeft; off++) { ch = pchWord[off]; if (!KMK_CC_EVAL_IS_PAREN_COMMA_OR_DOLLAR(ch)) { /* likely */ } else if (ch == '$') Right.fPlain = 0; else if (ch == '(') cCounts++; else if (ch == ')') { if (--cCounts == 0) break; } else KMK_CC_ASSERT(cCounts > 0 || ch == ','); } if (ch == ')' && cCounts == 0) { /* likely */ } else kmk_cc_eval_fatal(pCompiler, &pchWord[off], "Expected ')' before end of line"); /* Copy out the string. */ Right.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, off); kmk_cc_eval_strip_right_v(pCompiler->paStrCopySegs, &pCompiler->cStrCopySegs, &Right.cchCopy); Right.pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, Right.cchCopy); /* Skip past the parenthesis. */ pchWord += off + 1; cchLeft -= off + 1; } else if (ch == '"' || ch == '\'') { const char *pchTmp; /* * Quoted left side. */ /* Skip leading quote. */ pchWord++; cchLeft--; /* Locate the end quote. */ pchTmp = (const char *)memchr(pchWord, ch, cchLeft); if (pchTmp) { /* likely */ } else kmk_cc_eval_fatal(pCompiler, pchWord - 1, "Unbalanced quote in first if%seq string", fPositiveStmt ? "" : "n"); Left.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, pchTmp - pchWord); Left.pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, Left.cchCopy); Left.fPlain = memchr(Left.pszCopy, '$', Left.cchCopy) == NULL; /* skip end quote */ pchWord = pchTmp + 1; cchLeft = pchEnd - pchWord; /* Skip anything inbetween the left and right hand side (not mandatory). */ if ( cchLeft /** @todo replace with straight 'isspace' that takes escaped EOLs into account. */ && KMK_CC_EVAL_IS_SPACE_AFTER_WORD(pCompiler, pchWord[0], pchWord[1], cchLeft)) KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); /* * Quoted right side. */ if ( cchLeft > 0 && ( (ch = *pchWord) != '"' || ch == '\'') ) { /* Skip leading quote. */ pchWord++; cchLeft--; /* Locate the end quote. */ pchTmp = (const char *)memchr(pchWord, ch, cchLeft); if (pchTmp) { /* likely */ } else kmk_cc_eval_fatal(pCompiler, pchWord - 1, "Unbalanced quote in second if%seq string", fPositiveStmt ? "" : "n"); Right.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, pchTmp - pchWord); Right.pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, Right.cchCopy); Right.fPlain = memchr(Right.pszCopy, '$', Right.cchCopy) == NULL; /* skip end quote */ pchWord = pchTmp + 1; cchLeft = pchEnd - pchWord; } else kmk_cc_eval_fatal(pCompiler, pchWord, "Expected a second quoted string for 'if%seq'", fPositiveStmt ? "" : "n"); } else kmk_cc_eval_fatal(pCompiler, pchWord, "Expected parentheses or quoted string after 'if%seq'", fPositiveStmt ? "" : "n"); kmk_cc_block_realign(pCompiler->ppBlockTail); /* * Initialize the instruction. */ pInstr->IfCore.Core.enmOpcode = fPositiveStmt ? kKmkCcEvalInstr_ifeq : kKmkCcEvalInstr_ifneq; pInstr->IfCore.Core.iLine = pCompiler->iLine; kmk_cc_eval_init_subprogram_or_plain(pCompiler, &pInstr->Left, Left.pszCopy, Left.cchCopy, Left.fPlain); kmk_cc_eval_init_subprogram_or_plain(pCompiler, &pInstr->Right, Right.pszCopy, Right.cchCopy, Right.fPlain); kmk_cc_eval_do_if_core(pCompiler, &pInstr->IfCore, fInElse); /* * Make sure there is nothing following the variable name. */ KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (cchLeft) kmk_cc_eval_fatal(pCompiler, pchWord, "Bogus stuff after 'if%sdef' variable name", fPositiveStmt ? "" : "n"); } else kmk_cc_eval_fatal(pCompiler, pchWord, "Expected expression after 'if' directive"); return 1; } /** * Deals with 'if1of (set-a,set-b)', 'ifn1of (set-a,set-b)', * 'else if1of (set-a,set-b)' and 'else ifn1of (set-a,set-b)' statements. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord First char after 'if[n]1of'. * @param cchLeft The number of chars left to parse on this line. * @param fInElse Set if this is an 'else if' (rather than just 'if'). * @param fPositiveStmt Set if 'if1of', clear if 'ifn1of'. */ static int kmk_cc_eval_do_if1of(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, int fInElse, int fPositiveStmt) { KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (cchLeft) { /* * This code is (currently) very similar to kmk_cc_eval_do_ifeq. * However, we may want to add hashing optimizations of plain text, * and we don't want to support the quoted form as it is not necessary * and may interfere with support for quoted words later on. */ PKMKCCEVALIF1OF pInstr = (PKMKCCEVALIF1OF)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr)); struct { char *pszCopy; size_t cchCopy; int fPlain; } Left, Right; char ch = *pchWord; if (ch == '(') { int cCounts; size_t off; /* * The left side ends with a comma. We respect parentheses, but * not curly brackets. */ /* Skip the parenthesis. */ pchWord++; cchLeft--; /* Find the comma, checking for non-plainness. */ cCounts = 0; Left.fPlain = 1; for (off = 0; off < cchLeft; off++) { ch = pchWord[off]; if (!KMK_CC_EVAL_IS_PAREN_COMMA_OR_DOLLAR(ch)) { /* likely */ } else if (ch == '$') Left.fPlain = 0; else if (ch == '(') cCounts++; else if (ch == ')') cCounts--; /** @todo warn if it goes negative. */ else if (ch == ',' && cCounts == 0) break; else KMK_CC_ASSERT(cCounts > 0); } if (ch == ',' && cCounts == 0) { /* likely */ } else kmk_cc_eval_fatal(pCompiler, &pchWord[off], "Expected ',' before end of line"); /* Copy out the string. */ Left.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, off); kmk_cc_eval_strip_right_v(pCompiler->paStrCopySegs, &pCompiler->cStrCopySegs, &Left.cchCopy); Left.pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, Left.cchCopy); /* Skip past the comma and any following spaces. */ pchWord += off + 1; cchLeft -= off + 1; if ( cchLeft /** @todo replace with straight 'isspace' that takes escaped EOLs into account. */ && KMK_CC_EVAL_IS_SPACE_AFTER_WORD(pCompiler, pchWord[0], pchWord[1], cchLeft)) KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); /* * Ditto for the right side, only it ends with a closing parenthesis. */ cCounts = 1; Right.fPlain = 1; for (off = 0; off < cchLeft; off++) { ch = pchWord[off]; if (!KMK_CC_EVAL_IS_PAREN_COMMA_OR_DOLLAR(ch)) { /* likely */ } else if (ch == '$') Right.fPlain = 0; else if (ch == '(') cCounts++; else if (ch == ')') { if (--cCounts == 0) break; } else KMK_CC_ASSERT(cCounts > 0 || ch == ','); } if (ch == ')' && cCounts == 0) { /* likely */ } else kmk_cc_eval_fatal(pCompiler, &pchWord[off], "Expected ')' before end of line"); /* Copy out the string. */ Right.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, off); kmk_cc_eval_strip_right_v(pCompiler->paStrCopySegs, &pCompiler->cStrCopySegs, &Right.cchCopy); Right.pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, Right.cchCopy); /* Skip past the parenthesis. */ pchWord += off + 1; cchLeft -= off + 1; } else kmk_cc_eval_fatal(pCompiler, pchWord, "Expected parentheses after 'if%s1of'", fPositiveStmt ? "" : "n"); kmk_cc_block_realign(pCompiler->ppBlockTail); /* * Initialize the instruction. */ pInstr->IfCore.Core.enmOpcode = fPositiveStmt ? kKmkCcEvalInstr_if1of : kKmkCcEvalInstr_ifn1of; pInstr->IfCore.Core.iLine = pCompiler->iLine; kmk_cc_eval_init_subprogram_or_plain(pCompiler, &pInstr->Left, Left.pszCopy, Left.cchCopy, Left.fPlain); kmk_cc_eval_init_subprogram_or_plain(pCompiler, &pInstr->Right, Right.pszCopy, Right.cchCopy, Right.fPlain); kmk_cc_eval_do_if_core(pCompiler, &pInstr->IfCore, fInElse); /* * Make sure there is nothing following the variable name. */ KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (cchLeft) kmk_cc_eval_fatal(pCompiler, pchWord, "Bogus stuff after 'if%s1of' variable name", fPositiveStmt ? "" : "n"); } else kmk_cc_eval_fatal(pCompiler, pchWord, "Expected expression after 'if' directive"); return 1; } /** * Deals with 'else' and 'else ifxxx' statements. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord First char after 'define'. * @param cchLeft The number of chars left to parse on this line. */ static int kmk_cc_eval_do_else(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft) { /* * There must be an 'if' on the stack. */ unsigned iIf = pCompiler->cIfs; if (iIf > 0) { PKMKCCEVALIFCORE pIfCore = pCompiler->apIfs[--iIf]; if (!pIfCore->pTrueEndJump) { /* Emit a jump instruction that will take us from the 'True' block to the 'endif'. */ PKMKCCEVALJUMP pInstr = (PKMKCCEVALJUMP)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr)); pInstr->Core.enmOpcode = kKmkCcEvalInstr_jump; pInstr->Core.iLine = pCompiler->iLine; pInstr->pNext = NULL; pIfCore->pTrueEndJump = pInstr; /* The next instruction is the first in the 'False' block of the current 'if'. Should this be an 'else if', this will be the 'if' instruction emitted below. */ pIfCore->pNextFalse = (PKMKCCEVALCORE)kmk_cc_block_get_next_ptr(*pCompiler->ppBlockTail); } else if (iIf == 0) kmk_cc_eval_fatal(pCompiler, pchWord, "2nd 'else' for 'if' at line %u", pIfCore->Core.iLine); else kmk_cc_eval_fatal(pCompiler, pchWord, "2nd 'else' in a row - missing 'endif' for 'if' at line %u?", pIfCore->Core.iLine); } else kmk_cc_eval_fatal(pCompiler, pchWord, "'else' without 'if'"); /* * Check for 'else ifxxx'. There can be nothing else following an else. */ KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (cchLeft) { if ( cchLeft > 2 && KMK_CC_WORD_COMP_CONST_2(pchWord, "if")) { pchWord += 2; cchLeft -= 2; if (KMK_CC_EVAL_WORD_COMP_IS_EOL(pCompiler, pchWord, cchLeft)) return kmk_cc_eval_do_if(pCompiler, pchWord, cchLeft, 1 /* in else */); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "eq", 2)) return kmk_cc_eval_do_ifeq( pCompiler, pchWord + 2, cchLeft - 2, 1 /* in else */, 1 /* positive */); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "def", 3)) return kmk_cc_eval_do_ifdef(pCompiler, pchWord + 3, cchLeft - 3, 1 /* in else */, 1 /* positive */); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "neq", 3)) return kmk_cc_eval_do_ifeq( pCompiler, pchWord + 3, cchLeft - 3, 1 /* in else */, 0 /* positive */); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "1of", 3)) return kmk_cc_eval_do_if1of(pCompiler, pchWord + 3, cchLeft - 3, 1 /* in else */, 1 /* positive */); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "ndef", 4)) return kmk_cc_eval_do_ifdef(pCompiler, pchWord + 4, cchLeft - 4, 1 /* in else */, 0 /* positive */); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "n1of", 4)) return kmk_cc_eval_do_if1of(pCompiler, pchWord + 4, cchLeft - 4, 1 /* in else */, 0 /* positive */); pchWord -= 2; cchLeft += 2; } kmk_cc_eval_fatal(pCompiler, pchWord, "Bogus stuff after 'else'"); } return 1; } /** * Deals with the 'endif' statement. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord First char after 'define'. * @param cchLeft The number of chars left to parse on this line. */ static int kmk_cc_eval_do_endif(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft) { /* * There must be an 'if' on the stack. We'll POP it. */ unsigned iIf = pCompiler->cIfs; if (iIf > 0) { PKMKCCEVALCORE pNextInstr; PKMKCCEVALIFCORE pIfCore = pCompiler->apIfs[--iIf]; pCompiler->cIfs = iIf; /* POP! */ /* Update the jump targets for all IFs at this level. */ pNextInstr = (PKMKCCEVALCORE)kmk_cc_block_get_next_ptr(*pCompiler->ppBlockTail); do { if (pIfCore->pTrueEndJump) { /* Make the true block jump here, to the 'endif'. The false block is already here. */ pIfCore->pTrueEndJump->pNext = pNextInstr; KMK_CC_ASSERT(pIfCore->pNextFalse); } else { /* No 'else'. The false-case jump here, to the 'endif'. */ KMK_CC_ASSERT(!pIfCore->pNextFalse); pIfCore->pNextFalse = pNextInstr; } pIfCore = pIfCore->pPrevCond; } while (pIfCore); } else kmk_cc_eval_fatal(pCompiler, pchWord, "'endif' without 'if'"); /* * There shouldn't be anything trailing an 'endif'. */ KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (!cchLeft) { /* likely */ } else kmk_cc_eval_fatal(pCompiler, pchWord, "Bogus stuff after 'else'"); return 1; } /** * Parses a 'include file...', 'sinclude file...', '-include file...', * 'includedep file...', 'includedep-queue file...' and * 'includedep-flush file...' * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord First char after the include directive. * @param cchLeft The number of chars left to parse on this line. * @param enmOpcode The opcode for the include directive we're parsing. */ static int kmk_cc_eval_do_include(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, KMKCCEVALINSTR enmOpcode) { KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (cchLeft) { /* * Split what's left up into words. */ /** @todo GNU make supports escape sequences for spaces here (they confusingly refers to this as quoting). So, it's possible * to include C:/Program\ Files/kBuild/footer.kmk if we wanted to. It my intention to add support for double and/or single * quoted files names to offer an alternative way of addressing this. */ unsigned cWords = kmk_cc_eval_parse_words(pCompiler, pchWord, cchLeft); KMK_CC_EVAL_DPRINTF(("%s: cWords=%d\n", g_apszEvalInstrNms[enmOpcode], cWords)); if (cWords) { PKMKCCEVALINCLUDE pInstr = (PKMKCCEVALINCLUDE)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, KMKCCEVALINCLUDE_SIZE(cWords)); pInstr->Core.enmOpcode = enmOpcode; pInstr->Core.iLine = pCompiler->iLine; pInstr->cFiles = cWords; kmk_cc_eval_init_spp_array_from_duplicated_words(pCompiler, cWords, pCompiler->paWords, pInstr->aFiles); kmk_cc_block_realign(pCompiler->ppBlockTail); } else KMK_CC_ASSERT(0); } else KMK_CC_EVAL_DPRINTF(("%s: include without args\n", g_apszEvalInstrNms[enmOpcode])); return 1; } static int kmk_cc_eval_do_vpath(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft) { kmk_cc_eval_fatal(pCompiler, NULL, "vpath directive is not implemented\n"); return 1; } /** * Called when any previous recipe must have ended and can be finalized. * * This occurs when encountering an assignement, a new recipe or the end of the * complication unit. * * @param pCompiler The compiler state. */ static void kmk_cc_eval_end_of_recipe(PKMKCCEVALCOMPILER pCompiler, const char *pchWord) { if (pCompiler->pRecipe) { /** @todo do stuff here. */ kmk_cc_eval_fatal(pCompiler, pchWord, "end-of-recipe handling not implemented yet"); } } static void kmk_cc_eval_handle_command(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft) { kmk_cc_eval_fatal(pCompiler, pchWord, "command handling not implemented yet"); } /** * Pick up the recipe parsing at the colon. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord0 The first word. * @param cchWord0 The length of the first word. * @param enmToken0 The classification of the first word. * @param pchColon The colon. * @param cchLeft How much is left, starting at the colon. */ static int kmk_cc_eval_handle_recipe_cont_colon(PKMKCCEVALCOMPILER pCompiler, const char *pchWord0, size_t cchWord0, KMKCCEVALTOKEN enmToken0, const char *pchColon, size_t cchLeft) { kmk_cc_eval_fatal(pCompiler, pchWord0, "recipe handling not implemented yet (#1)"); return 1; } /** * Pick up the recipe parsing at the 2nd word (after it was determined not to be * an assignment operator after all). * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord0 The first word. * @param cchWord0 The length of the first word. * @param pchWord Where to continue parsing. * @param cchLeft How much is left to parse. */ static int kmk_cc_eval_handle_recipe_cont_2nd_word(PKMKCCEVALCOMPILER pCompiler, const char *pchWord0, size_t cchWord0, const char *pchWord, size_t cchLeft) { // const char *pchColon = memchr() kmk_cc_eval_fatal(pCompiler, pchWord, "recipe handling not implemented yet (#2)"); return 1; } static void kmk_cc_eval_handle_recipe(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft) { const char *pszColon = NULL;//memchr(pchWord, cchLeft); if (pszColon) { kmk_cc_eval_fatal(pCompiler, pchWord, "recipe handling not implemented yet (#3)"); } else if (pchWord[0] == '$') { } else kmk_cc_eval_fatal(pCompiler, pchWord, "Not variable assignment. Could be a complicated indirect recipe definition, however that's currently not supported."); } /** * Common worker for handling export (non-assign), undefine and unexport. * * For instructions using the KMKCCEVALVARIABLES structure. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord First non-space chare after the keyword. * @param cchLeft The number of chars left to parse on this line. * @param fQualifiers The qualifiers. */ static int kmk_cc_eval_do_with_variable_list(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, KMKCCEVALINSTR enmOpcode, unsigned fQualifiers) { if (cchLeft) { /* * Parse the variable name list. GNU make is using normal word * handling here, so we can share code with the include directives. */ unsigned cWords = kmk_cc_eval_parse_words(pCompiler, pchWord, cchLeft); #ifdef KMK_CC_EVAL_LOGGING_ENABLED unsigned iWord; KMK_CC_EVAL_DPRINTF(("%s: cWords=%d\n", g_apszEvalInstrNms[enmOpcode], cWords)); for (iWord = 0; iWord < cWords; iWord++) KMK_CC_EVAL_DPRINTF((" word[%u]: len=%#05x t=%d '%*.*s'\n", iWord, (int)pCompiler->paWords[iWord].cchWord, (int)pCompiler->paWords[iWord].enmToken, (int)pCompiler->paWords[iWord].cchWord, (int)pCompiler->paWords[iWord].cchWord, pCompiler->paWords[iWord].pchWord)); #endif if (cWords) { PKMKCCEVALVARIABLES pInstr = (PKMKCCEVALVARIABLES)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, KMKCCEVALVARIABLES_SIZE(cWords)); pInstr->Core.enmOpcode = enmOpcode; pInstr->Core.iLine = pCompiler->iLine; pInstr->cVars = cWords; kmk_cc_eval_init_spp_array_from_duplicated_words(pCompiler, cWords, pCompiler->paWords, pInstr->aVars); kmk_cc_block_realign(pCompiler->ppBlockTail); } else KMK_CC_ASSERT(0); } /* else: NOP */ return 1; } /** * Parses a '[qualifiers] undefine variable [..]' expression. * * A 'undefine' directive is final, any qualifiers must preceed it. So, we just * have to extract the variable names now. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord First char after 'define'. * @param cchLeft The number of chars left to parse on this line. * @param fQualifiers The qualifiers. */ static int kmk_cc_eval_do_var_undefine(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, unsigned fQualifiers) { KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (!cchLeft) kmk_cc_eval_fatal(pCompiler, pchWord, "undefine requires a variable name"); /** @todo GNU make doesn't actually do the list thing for undefine, it seems * to assume everything after it is a single variable... Going with * simple common code for now. */ return kmk_cc_eval_do_with_variable_list(pCompiler, pchWord, cchLeft, kKmkCcEvalInstr_undefine, fQualifiers); } /** * Parses a '[qualifiers] unexport variable [..]' expression. * * A 'unexport' directive is final, any qualifiers must preceed it. So, we just * have to extract the variable names now. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord First char after 'define'. * @param cchLeft The number of chars left to parse on this line. * @param fQualifiers The qualifiers. */ static int kmk_cc_eval_do_var_unexport(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, unsigned fQualifiers) { PKMKCCEVALCORE pInstr; /* * Join paths with undefine and export, unless it's an unexport all directive. */ KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (cchLeft) return kmk_cc_eval_do_with_variable_list(pCompiler, pchWord, cchLeft, kKmkCcEvalInstr_unexport, fQualifiers); /* * We're unexporting all variables. */ pInstr = kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr)); pInstr->enmOpcode = kKmkCcEvalInstr_unexport_all; pInstr->iLine = pCompiler->iLine; return 1; } /** * Parse the value of a 'define' at pCompiler->offNext. * * This will update 'offNext' to the start of the line following the 'endef' * matching the 'define' of the value. * * The value is prepared for kmk_cc_eval_strcpyv. * * @returns The value length that we've prepared for copying. * @param pCompiler The compiler state. * @param pfPlainValue Where to return whether this is a plain value or * one needing expansion. */ static size_t kmk_cc_eval_parse_define_value(PKMKCCEVALCOMPILER pCompiler, int *pfPlainValue) { /* * Now we need to find the matching 'endef', we support nested ones. * * We look for the lines starting with 'endef' and 'define', like GNU * make does even if we really should also be checking for variable * qualifiers too. * * As we go on looking, we prepare the value in paStrCopySegs. * * Note! We duplicate code/logic from the top level compile loop here. */ const char * const pszContent = pCompiler->pszContent; size_t cchContent = pCompiler->cchContent; int const chFirstEol = pCompiler->chFirstEol; size_t const cchEolSeq = pCompiler->cchEolSeq; unsigned cNestings = 1; size_t offNext = pCompiler->offNext; unsigned iLine = pCompiler->iLine; unsigned cSegs = 0; size_t cchValue = 0; int fPlainValue = 1; for (;;) { /* * Find end of line, preparing to copy it. */ if (offNext < cchContent) { unsigned const cSegsAtStartOfLine = cSegs; size_t const cchValueStartOfLine = cchValue; size_t offFirstWord = offNext; const char *pchLine = &pszContent[offNext]; size_t cchLine; const char *pchTmp; pCompiler->cEscEols = 0; pCompiler->iEscEol = 0; /* Add newline if necessary and make sure we've got a segment handy. */ KMK_CC_EVAL_ENSURE_STRCOPY_SEGS(pCompiler, cSegs + 2); if (cSegs) { cchValue++; pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = 1; pCompiler->paStrCopySegs[cSegs].pchSrc = "\n"; cSegs++; } /* Simple case: No escaped EOL, nor the end of the input. */ pchTmp = (const char *)memchr(&pszContent[offNext], chFirstEol, cchContent - offNext); if ( pchTmp && ( &pszContent[offNext] == pchTmp || pchTmp[-1] != '\\')) { if ( cchEolSeq == 1 || pchTmp[1] == pCompiler->chSecondEol) { offNext = pchTmp - pszContent; cchLine = pchTmp - pchLine; cchValue += cchLine; pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = cchLine; pCompiler->paStrCopySegs[cSegs].pchSrc = pchLine; cSegs++; while (offFirstWord < offNext && KMK_CC_EVAL_IS_SPACE(pszContent[offFirstWord])) offFirstWord++; offNext += cchEolSeq; } else kmk_cc_eval_fatal_eol(pCompiler, pchTmp, iLine, offNext); } /* The complicated, less common cases. */ else { size_t fPendingSpace = 0; for (;;) { /* Find the first non-space char on this line. We always need it. */ size_t offThisFirstWord = offNext; size_t offEol = pchTmp ? pchTmp - pszContent : cchContent; if (offFirstWord == offNext) { while (offFirstWord < offEol && KMK_CC_EVAL_IS_SPACE(pszContent[offFirstWord])) offFirstWord++; if (pCompiler->cEscEols > 0) offThisFirstWord = offFirstWord; } else while (offThisFirstWord < offEol && KMK_CC_EVAL_IS_SPACE(pszContent[offThisFirstWord])) offThisFirstWord++; /* We normally need one, so just make sure once. */ KMK_CC_EVAL_ENSURE_STRCOPY_SEGS(pCompiler, cSegs + 1); if (pchTmp) { if ( cchEolSeq == 1 || pchTmp[1] == pCompiler->chSecondEol) { size_t const offThis = offNext; size_t offEsc; int fDone; offNext = pchTmp - pszContent; /* Is it an escape sequence? */ if ( !offNext || pchTmp[-1] != '\\') fDone = 1; else if (offNext < 2 || pchTmp[-2] != '\\') { offEsc = offNext - 1; fDone = 0; } else { /* Count how many backslashes there are. Must be odd number to be an escape sequence. Normally we keep half of them, except for command lines. */ size_t cSlashes = 2; while (offNext >= cSlashes && pchTmp[0 - cSlashes] == '\\') cSlashes--; fDone = !(cSlashes & 1); offEsc = offNext - (cSlashes >> 1); } /* Anything to copy? */ /** @todo fixme tomorrow! */ cchLine = offThisFirstWord - offNext; if (cchLine) { pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = fPendingSpace ? -(ssize_t)cchLine : (ssize_t)cchLine; pCompiler->paStrCopySegs[cSegs].pchSrc = &pszContent[offThisFirstWord]; cSegs++; } if (fDone) { cchLine = &pszContent[offNext] - pchLine; offNext += cchEolSeq; break; } /* Record it. */ if (pCompiler->cEscEols < pCompiler->cEscEolsAllocated) { /* likely */ } else { KMK_CC_ASSERT(pCompiler->cEscEols == pCompiler->cEscEolsAllocated); pCompiler->cEscEolsAllocated = pCompiler->cEscEolsAllocated ? pCompiler->cEscEolsAllocated * 2 : 2; pCompiler->paEscEols = (PKMKCCEVALESCEOL)xrealloc(pCompiler->paEscEols, pCompiler->cEscEolsAllocated * sizeof(pCompiler->paEscEols[0])); } pCompiler->paEscEols[pCompiler->cEscEols].offEsc = offEsc; pCompiler->paEscEols[pCompiler->cEscEols].offEol = offNext; pCompiler->cEscEols++; /* Anything to copy? */ cchLine = offThisFirstWord - offNext; if (cchLine) { } /* Advance. */ offNext += cchEolSeq; if (offFirstWord == offEsc) { offFirstWord = offNext; pCompiler->iEscEol++; } } else kmk_cc_eval_fatal_eol(pCompiler, pchTmp, pCompiler->iLine, off); } else { /* End of input. Happens only once per compilation, nothing to optimize for. */ if (offFirstWord == offNext) while (offFirstWord < cchContent && KMK_CC_EVAL_IS_SPACE(pszContent[offFirstWord])) offFirstWord++; KMK_CC_EVAL_ENSURE_STRCOPY_SEGS(pCompiler, cSegs + 2); if (cSegs == cSegsAtStartOfLine) { /* No escaped EOLs. */ cchLine = &pszContent[cchContent] - pchLine; cchValue += cchLine; pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = cchLine; pCompiler->paStrCopySegs[cSegs].pchSrc = pchLine; cSegs++; } else { if (offFirstWordThisLine < cchContent) { cchLine = cchContent - offFirstWordThisLine; cchValue += cchLine; pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = fPendingSpace ? -(ssize_t)cchLine : (ssize_t)cchLine; pCompiler->paStrCopySegs[cSegs].pchSrc = &pszContent[offFirstWordThisLine]; cSegs++; } cchLine = &pszContent[cchContent] - pchLine; } offNext = cchContent; break; } pchTmp = (const char *)memchr(&pszContent[offNext], chFirstEol, cchContent - offNext); } } KMK_CC_ASSERT(offNext <= cchContent); KMK_CC_ASSERT(offNext >= off + cchLine); KMK_CC_ASSERT(off + cchLine <= cchContent && cchLine <= cchContent); KMK_CC_ASSERT(offFirstWord <= off + cchLine); KMK_CC_ASSERT(offFirstWord >= off); KMK_CC_ASSERT(pszContent[offFirstWord] != ' ' && pszContent[offFirstWord] != '\t'); KMK_CC_EVAL_DPRINTF(("#%03u: %*.*s\n", pCompiler->iLine, (int)cchLine, (int)cchLine, &pszContent[off])); /* * Look for 'endef' and 'define' directives. */ cchLine -= offFirstWord - off; if ( cchLine >= 5 /* shortest word is 5 chars ('endef', 'local') */ && pchLine[0] != pCompiler->chCmdPrefix) { pchTmp = &pszContent[offFirstWord]; if (!KMK_CC_EVAL_IS_1ST_IN_VARIABLE_KEYWORD(*pchTmp)) { /* Kind of likely (and saves one indent). */ } else if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchTmp, cchLine, "endef", 5)) { cNestings--; if (cNestings == 0) { cchValue = cchValueStartOfLine; cSegs = cSegsAtStartOfLine; break; } } else for (;;) { if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchTmp, cchLine, "define", 6)) { cNestings++; break; } /* GNU make doesn't do this, but I think it makes sense. */ if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchTmp, cchLine, "local", 5)) { pchTmp += 5; cchLine -= 5; } else if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchTmp, cchLine, "export", 6)) { pchTmp += 6; cchLine -= 6; } else if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchTmp, cchLine, "private", 7)) { pchTmp += 7; cchLine -= 7; } else if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchTmp, cchLine, "override", 8)) { pchTmp += 8; cchLine -= 8; } else break; KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchTmp, cchLine); } } /* * Advance to the next line. */ iLine += pCompiler->cEscEols + 1; } else kmk_cc_eval_fatal(pCompiler, NULL, ) } /* * Update globals and return values. */ pCompiler->offNext = offNext; pCompiler->iLine = iLine; pCompiler->cStrCopySegs = cSegs; *pfPlainValue = fPlainValue; return cchValue; } /** * Parses a 'define variable' expression. * * A 'define' directive is final, any qualifiers must preceed it. So, we just * have to extract the variable name now, well and find the corresponding * 'endef'. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord First char after 'define'. * @param cchLeft The number of chars left to parse on this line. * @param fQualifiers The qualifiers. */ static int kmk_cc_eval_do_var_define(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, unsigned fQualifiers) { /* * Now comes the variable name. It may optionally be followed by an * assignment operator to indicate what kind of variable is being defined. */ KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); unsigned cWords = cchLeft ? kmk_cc_eval_parse_words(pCompiler, pchWord, cchLeft) : 0; if (cWords >= 1) { /* * Check for variable assignment operator. Kind of tedious... */ KMKCCEVALINSTR enmOpcode; PKMKCCEVALWORD pVarWord = pCompiler->paWords; if ( cWords == 1 && ( pVarWord->cchWord == 0 || pVarWord->pchWord[pVarWord->cchWord - 1] != '=')) enmOpcode = kKmkCcEvalInstr_define_recursive; /* very likely */ else if ( pVarWord->cchWord > 0 && pVarWord->pchWord[pVarWord->cchWord - 1] == '=') { if (pVarWord->cchWord == 1) enmOpcode = kKmkCcEvalInstr_define_recursive; else { char chPenultimate = pVarWord->pchWord[pVarWord->cchWord - 2]; if (chPenultimate == '?') enmOpcode = kKmkCcEvalInstr_define_if_new; else if (chPenultimate == ':') enmOpcode = kKmkCcEvalInstr_assign_simple; else if (chPenultimate == '+') enmOpcode = kKmkCcEvalInstr_assign_append; else if (chPenultimate == '<') enmOpcode = kKmkCcEvalInstr_assign_prepend; else enmOpcode = kKmkCcEvalInstr_define_recursive; } pVarWord->cchWord -= enmOpcode == kKmkCcEvalInstr_define_recursive ? 1 : 2; if (cWords > 1) kmk_cc_eval_fatal(pCompiler, pCompiler->paWords[1].pchWord, "Bogus stuff after 'define' variable name and assignment operator"); } else { PCKMKCCEVALWORD pOpWord = &pCompiler->paWords[1]; KMK_CC_ASSERT(cWords > 1); if ( pOpWord->cchWord == 1 && pOpWord->pchWord[0] == '=') enmOpcode = kKmkCcEvalInstr_define_recursive; else if ( pOpWord->cchWord == 2 && pOpWord->pchWord[1] == '=') { char chFirst = pVarWord->pchWord[0]; if (chFirst == '?') enmOpcode = kKmkCcEvalInstr_define_if_new; else if (chFirst == ':') enmOpcode = kKmkCcEvalInstr_assign_simple; else if (chFirst == '+') enmOpcode = kKmkCcEvalInstr_assign_append; else if (chFirst == '<') enmOpcode = kKmkCcEvalInstr_assign_prepend; else kmk_cc_eval_fatal(pCompiler, pOpWord->pchWord, "Bogus stuff after 'define' variable name"); } else kmk_cc_eval_fatal(pCompiler, pOpWord->pchWord, "Bogus stuff after 'define' variable name"); if (cWords > 2) kmk_cc_eval_fatal(pCompiler, pCompiler->paWords[2].pchWord, "Bogus stuff after 'define' variable name and assignment operator"); } /* * The variable name must not be empty. */ if (pVarWord->cchWord) { int const fPlainVarNm = pVarWord->enmToken == kKmkCcEvalToken_WordPlain; const char * pchVarNm = pVarWord->pchWord; size_t cchVarNm = pVarWord->cchWord; PKMKCCEVALASSIGN pInstr; size_t cchValue; const char *pszValue; int fPlainValue; if ( enmOpcode == kKmkCcEvalInstr_define_recursive || enmOpcode == kKmkCcEvalInstr_define_if_new) { PKMKCCEVALASSIGNDEF pInstrDef; pInstrDef = (PKMKCCEVALASSIGNDEF)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstrDef)); pInstr = &pInstrDef->AssignCore; pInstrDef->pEvalProg = NULL; /** @todo consider this later at some point, need some trial and error approach. */ } else pInstr = (PKMKCCEVALASSIGN)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr)); pInstr->Core.enmOpcode = enmOpcode; pInstr->Core.iLine = pCompiler->iLine; pInstr->fExport = (fQualifiers & KMK_CC_EVAL_QUALIFIER_EXPORT) != 0; pInstr->fOverride = (fQualifiers & KMK_CC_EVAL_QUALIFIER_OVERRIDE) != 0; pInstr->fPrivate = (fQualifiers & KMK_CC_EVAL_QUALIFIER_PRIVATE) != 0; pInstr->fLocal = (fQualifiers & KMK_CC_EVAL_QUALIFIER_LOCAL) != 0; cchValue = kmk_cc_eval_parse_define_value(pCompiler, &fPlainValue); pszValue = kmk_cc_eval_strdup_prepped(pCompiler, cchValue); if (fPlainVarNm) pchVarNm = strcache2_add(&variable_strcache, pchVarNm, cchVarNm); else { /** @todo fix work copying. */ // pCompiler->iEscEol = iEscEolVarNm; cchVarNm = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchVarNm, cchVarNm); pchVarNm = kmk_cc_eval_strdup_prepped(pCompiler, cchVarNm); } kmk_cc_block_realign(pCompiler->ppBlockTail); KMK_CC_EVAL_DPRINTF(("%s: define '%s'\n%s\nendef\n", g_apszEvalInstrNms[enmOpcode], pchVarNm, pszValue)); kmk_cc_eval_init_subprogram_or_plain(pCompiler, &pInstr->Variable, pchVarNm, cchVarNm, fPlainVarNm); kmk_cc_eval_init_subprogram_or_plain(pCompiler, &pInstr->Value, pszValue, cchValue, fPlainValue); pInstr->pNext = (PKMKCCEVALCORE)kmk_cc_block_get_next_ptr(*pCompiler->ppBlockTail); } else kmk_cc_eval_fatal(pCompiler, pchWord, "Empty variable name after 'define'"); } else kmk_cc_eval_fatal(pCompiler, pchWord, "Expected variable name after 'define'"); return 1; } /** * Emits a 'expand(-and-eval)' instruction. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchSubprog The subprogram that needs expanding. * @param cchSubprog The length of the subprogram. * @param iEscEol The escaped EOL index corresponding to pchSubprog. */ static int kmk_cc_eval_emit_expand(PKMKCCEVALCOMPILER pCompiler, const char *pchSubprog, size_t cchSubprog, unsigned iEscEolVarNm) { /* * We're unexporting all variables. */ size_t cchCopy; char *pszCopy; PKMKCCEVALEXPAND pInstr; pCompiler->iEscEol = iEscEolVarNm; cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchSubprog, cchSubprog); pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, cchCopy); kmk_cc_block_realign(pCompiler->ppBlockTail); pInstr = (PKMKCCEVALEXPAND)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr)); pInstr->Core.enmOpcode = kKmkCcEvalInstr_expand; pInstr->Core.iLine = pCompiler->iLine; pInstr->uPadding = 0; /** @todo Make the subprogram embed necessary strings. */ kmk_cc_eval_compile_string_exp_subprog(pCompiler, pszCopy, cchCopy, &pInstr->Subprog); return 1; } static int kmk_cc_eval_handle_assignment_or_recipe(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, unsigned fQualifiers) { /* * We're currently at a word which may or may not be a variable name * followed by an assignment operator, alternatively it must be a recipe. * We need to figure this out and deal with it in the most efficient * manner as this is a very common occurence. */ unsigned const iEscEolVarNm = pCompiler->iEscEol; int fPlainVarNm = 1; const char *pchVarNm = pchWord; size_t cchVarNm; size_t cch = 0; size_t cchSubprog = 0; char ch; /* * The variable name. Complicate by there being no requirement of a space * preceeding the assignment operator, as well as that the variable name * may include variable references with spaces (function++) in them. */ for (;;) { if (cch < cchLeft) { /*likely*/ } else { /* Single word, join paths with word + whitespace. */ KMK_CC_ASSERT(cch == cchLeft); cchVarNm = cch; pchWord += cch; cchLeft -= cch; break; } ch = pchWord[cch]; if (!KMK_CC_EVAL_IS_SPACE_DOLLAR_SLASH_OR_ASSIGN(ch)) cch++; /* Space? */ else if (KMK_CC_EVAL_IS_SPACE(ch)) { cchVarNm = cch; pchWord += cch; cchLeft -= cch; KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); break; } /* Variable expansion may contain spaces, so handle specially. */ else if (ch == '$') { size_t const offStart = cch; cch = kmk_cc_eval_parse_var_exp(pCompiler, pchWord, cchLeft, cch); cchSubprog += cch - offStart; fPlainVarNm = 0; } /* Check out potential recipe, simple assignment or DOS drive letter separator. */ else if (ch == ':') { if ( cch + 1 < cchLeft && pchWord[cch + 1] != '=') { cchVarNm = cch; pchWord += cch; cchLeft -= cch; break; } #ifdef HAVE_DOS_PATHS /* Don't confuse the first colon in: C:/Windows/System32/Kernel32.dll: C:/Windows/System32/NtDll.dll for a recipe, it is only the second one which counts. */ if ( cch == 1 && isalpha((unsigned char)pchWord[0])) cch++; else #endif if (!fQualifiers) return kmk_cc_eval_handle_recipe_cont_colon(pCompiler, pchWord, cch, fPlainVarNm ? kKmkCcEvalToken_WordPlain : kKmkCcEvalToken_WordWithDollar, pchWord + cch, cchLeft - cch); /** @todo we may have words already preparsed here so restarting is easy... */ return 0; /* retry with preceeding keywords */ } /* Check out assignment operator. */ else if (ch == '=') { if (cch > 0) { char chPrev = pchWord[cch - 1]; if (chPrev == ':' || chPrev == '+' || chPrev == '?' || chPrev == '<') cch--; cchVarNm = cch; pchWord += cch; cchLeft -= cch; break; } kmk_cc_eval_fatal(pCompiler, pchWord, "Empty variable name."); } /* Check out potential escaped EOL sequence. */ else if (ch == '\\') { unsigned const iEscEol = pCompiler->iEscEol; if (iEscEol >= pCompiler->cEscEols) cch++; else { size_t offCur = &pchWord[cch] - pCompiler->pszContent; if (offCur < pCompiler->paEscEols[iEscEol].offEol) cch++; else { cchVarNm = cch; KMK_CC_ASSERT(offCur == pCompiler->paEscEols[iEscEol].offEol); cch = pCompiler->paEscEols[iEscEol].offEol + pCompiler->cchEolSeq - offCur; pCompiler->iEscEol = iEscEol + 1; pchWord += cch; cchLeft -= cch; KMK_CC_EVAL_SKIP_SPACES(pCompiler, pchWord, cchLeft); break; } } } else KMK_CC_ASSERT(0); } /* * Check for assignment operator. */ if (cchLeft) { size_t cchValue; PKMKCCEVALASSIGN pInstr; KMKCCEVALINSTR enmOpcode; int fPlainValue; char *pszValue; ch = *pchWord; if (ch == '=') { enmOpcode = kKmkCcEvalInstr_assign_recursive; pchWord++; cchLeft--; } else if (cchLeft >= 2 && pchWord[1] == '=') { if (ch == ':') enmOpcode = kKmkCcEvalInstr_assign_simple; else if (ch == '+') enmOpcode = kKmkCcEvalInstr_assign_append; else if (ch == '<') enmOpcode = kKmkCcEvalInstr_assign_prepend; else if (ch == '?') enmOpcode = kKmkCcEvalInstr_assign_if_new; else if (!fQualifiers) return kmk_cc_eval_handle_recipe_cont_2nd_word(pCompiler, pchVarNm, cchVarNm, pchWord, cchLeft); else return 0; /* retry without preceding keywords */ pchWord += 2; cchLeft -= 2; } else if (!fQualifiers) return kmk_cc_eval_handle_recipe_cont_2nd_word(pCompiler, pchVarNm, cchVarNm, pchWord, cchLeft); else return 0; /* retry without preceding keywords */ /* * Skip leading spaces, if any and prep the value for copying. */ KMK_CC_EVAL_SKIP_SPACES(pCompiler, pchWord, cchLeft); cchValue = kmk_cc_eval_prep_normal_line(pCompiler, pchWord, cchLeft); fPlainValue = memchr(pchWord, '$', cchLeft) == NULL; /* * Emit the instruction. */ kmk_cc_eval_end_of_recipe(pCompiler, pchWord); pInstr = (PKMKCCEVALASSIGN)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr)); pInstr->Core.enmOpcode = enmOpcode; pInstr->Core.iLine = pCompiler->iLine; pInstr->fExport = (fQualifiers & KMK_CC_EVAL_QUALIFIER_EXPORT) != 0; pInstr->fOverride = (fQualifiers & KMK_CC_EVAL_QUALIFIER_OVERRIDE) != 0; pInstr->fPrivate = (fQualifiers & KMK_CC_EVAL_QUALIFIER_PRIVATE) != 0; pInstr->fLocal = (fQualifiers & KMK_CC_EVAL_QUALIFIER_LOCAL) != 0; /* We copy the value before messing around with the variable name since we have to do more iEolEsc saves & restores the other way around. */ pszValue = kmk_cc_eval_strdup_prepped(pCompiler, cchValue); if (fPlainVarNm) pchVarNm = strcache2_add(&variable_strcache, pchVarNm, cchVarNm); else { pCompiler->iEscEol = iEscEolVarNm; cchVarNm = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchVarNm, cchVarNm); pchVarNm = kmk_cc_eval_strdup_prepped(pCompiler, cchVarNm); } kmk_cc_block_realign(pCompiler->ppBlockTail); KMK_CC_EVAL_DPRINTF(("%s: '%s' '%s'\n", g_apszEvalInstrNms[enmOpcode], pchVarNm, pszValue)); kmk_cc_eval_init_subprogram_or_plain(pCompiler, &pInstr->Variable, pchVarNm, cchVarNm, fPlainVarNm); kmk_cc_eval_init_subprogram_or_plain(pCompiler, &pInstr->Value, pszValue, cchValue, fPlainValue); pInstr->pNext = (PKMKCCEVALCORE)kmk_cc_block_get_next_ptr(*pCompiler->ppBlockTail); } /* * This could be one or more function calls. */ else if (!fPlainVarNm && cchVarNm == cchSubprog && fQualifiers == 0) return kmk_cc_eval_emit_expand(pCompiler, pchVarNm, cchVarNm, iEscEolVarNm); else if (!fPlainVarNm) kmk_cc_eval_fatal(pCompiler, pchWord, "Not variable assignment. Could be a complicated indirect recipe definition, however that's currently not supported."); else kmk_cc_eval_fatal(pCompiler, pchWord, "Neither recipe nor variable assignment"); return 1; } /** * Parses a 'local [override] variable = value', 'local define variable', and * 'local undefine variable [...]' expressions. * * The 'local' directive must be first and it does not permit any qualifiers at * the moment. Should any be added later, they will have to come after 'local'. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord First char after 'local'. * @param cchLeft The number of chars left to parse on this line. * @param fQualifiers The qualifiers. */ static int kmk_cc_eval_do_var_local(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft) { KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (cchLeft) { /* * Check for 'local define' and 'local undefine' */ if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "define", 6)) /* final */ return kmk_cc_eval_do_var_define(pCompiler, pchWord + 6, cchLeft + 6, KMK_CC_EVAL_QUALIFIER_LOCAL); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "undefine", 8)) /* final */ return kmk_cc_eval_do_var_undefine(pCompiler, pchWord + 8, cchLeft + 8, KMK_CC_EVAL_QUALIFIER_LOCAL); /* * Simpler to just join paths with the rest here, even if we could * probably optimize the parsing a little if we liked. */ return kmk_cc_eval_handle_assignment_or_recipe(pCompiler, pchWord, cchLeft, KMK_CC_EVAL_QUALIFIER_LOCAL); } kmk_cc_eval_fatal(pCompiler, pchWord, "Expected variable name, assignment operator and value after 'local'"); return 1; } /** * We've found one variable qualification keyword, now continue parsing and see * if this is some kind of variable assignment expression or not. * * @returns 1 if variable assignment, 0 if not. * @param pCompiler The compiler state. * @param pchWord First char after the first qualifier. * @param cchLeft The number of chars left to parse on this line. * @param fQualifiers The qualifier. */ static int kmk_cc_eval_try_handle_var_with_keywords(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, unsigned fQualifiers) { for (;;) { KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (cchLeft) { char ch = *pchWord; if (KMK_CC_EVAL_IS_1ST_IN_VARIABLE_KEYWORD(ch)) { if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "define", 6)) /* final */ return kmk_cc_eval_do_var_define(pCompiler, pchWord + 6, cchLeft - 6, fQualifiers); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "undefine", 8)) /* final */ return kmk_cc_eval_do_var_undefine(pCompiler, pchWord + 8, cchLeft -86, fQualifiers); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "unexport", 8)) /* final */ return kmk_cc_eval_do_var_unexport(pCompiler, pchWord + 8, cchLeft - 8, fQualifiers); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "export", 6)) { if (!(fQualifiers & KMK_CC_EVAL_QUALIFIER_EXPORT)) fQualifiers |= KMK_CC_EVAL_QUALIFIER_EXPORT; else kmk_cc_eval_warn(pCompiler, pchWord, "'export' qualifier repeated"); pchWord += 6; cchLeft -= 6; continue; } if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "override", 8)) { if (!(fQualifiers & KMK_CC_EVAL_QUALIFIER_OVERRIDE)) fQualifiers |= KMK_CC_EVAL_QUALIFIER_OVERRIDE; else kmk_cc_eval_warn(pCompiler, pchWord, "'override' qualifier repeated"); pchWord += 8; cchLeft -= 8; continue; } if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "private", 7)) { if (!(fQualifiers & KMK_CC_EVAL_QUALIFIER_PRIVATE)) fQualifiers |= KMK_CC_EVAL_QUALIFIER_PRIVATE; else kmk_cc_eval_warn(pCompiler, pchWord, "'private' qualifier repeated"); pchWord += 7; cchLeft -= 7; continue; } } /* * Not a keyword, likely variable name followed by an assignment * operator and a value. Do a rough check for the assignment operator * and join paths with the unqualified assignment handling code. */ { const char *pchEqual = (const char *)memchr(pchWord, '=', cchLeft); if (pchEqual) return kmk_cc_eval_handle_assignment_or_recipe(pCompiler, pchWord, cchLeft, fQualifiers); } return 0; } else kmk_cc_eval_fatal(pCompiler, NULL, "Expected assignment operator or variable directive after variable qualifier(s)\n"); } } /** * Parses 'export [variable]' and 'export [qualifiers] variable = value' * expressions. * * When we find the 'export' directive at the start of a line, we need to * continue parsing with till we can tell the difference between the two forms. * * @returns 1 to indicate we've handled a keyword (see * kmk_cc_eval_try_handle_keyword). * @param pCompiler The compiler state. * @param pchWord First char after 'define'. * @param cchLeft The number of chars left to parse on this line. */ static int kmk_cc_eval_handle_var_export(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft) { KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); if (cchLeft) { unsigned iSavedEscEol; unsigned cWords; /* * We need to figure out whether this is an assignment or a export statement, * in the latter case join paths with 'export' and 'undefine'. */ const char *pchEqual = (const char *)memchr(pchWord, '=', cchLeft); if (!pchEqual) return kmk_cc_eval_do_with_variable_list(pCompiler, pchWord, cchLeft, kKmkCcEvalInstr_export, 0 /*fQualifiers*/); /* * Found an '=', could be an assignment. Let's take the easy way out * and just parse the whole statement into words like we would do if * it wasn't an assignment, and then check the words out for * assignment keywords and operators. */ iSavedEscEol = pCompiler->iEscEol; cWords = kmk_cc_eval_parse_words(pCompiler, pchWord, cchLeft); if (cWords) { PKMKCCEVALVARIABLES pInstr; PKMKCCEVALWORD pWord = pCompiler->paWords; unsigned iWord = 0; while (iWord < cWords) { /* Trailing assignment operator or terminal assignment directive ('undefine' and 'unexport' makes no sense here but GNU make ignores that). */ if ( ( pWord->cchWord > 1 && pWord->pchWord[pWord->cchWord - 1] == '=') || KMK_CC_STRCMP_CONST(pWord->pchWord, pWord->cchWord, "define", 6) || KMK_CC_STRCMP_CONST(pWord->pchWord, pWord->cchWord, "undefine", 8) || KMK_CC_STRCMP_CONST(pWord->pchWord, pWord->cchWord, "unexport", 8) ) { pCompiler->iEscEol = iSavedEscEol; return kmk_cc_eval_try_handle_var_with_keywords(pCompiler, pchWord, cchLeft, KMK_CC_EVAL_QUALIFIER_EXPORT); } /* If not a variable assignment qualifier, it must be a variable name followed by an assignment operator. */ if (iWord + 1 < cWords) { if ( !KMK_CC_STRCMP_CONST(pWord->pchWord, pWord->cchWord, "export", 6) && !KMK_CC_STRCMP_CONST(pWord->pchWord, pWord->cchWord, "private", 7) && !KMK_CC_STRCMP_CONST(pWord->pchWord, pWord->cchWord, "override", 8)) { pWord++; if ( pWord->cchWord > 0 && ( pWord->pchWord[0] == '=' || ( pWord->cchWord > 1 && pWord->pchWord[1] == '=' && ( pWord->pchWord[0] == ':' || pWord->pchWord[0] == '+' || pWord->pchWord[0] == '?' || pWord->pchWord[0] == '<') ) ) ) { pCompiler->iEscEol = iSavedEscEol; return kmk_cc_eval_try_handle_var_with_keywords(pCompiler, pchWord, cchLeft, KMK_CC_EVAL_QUALIFIER_EXPORT); } break; } } else break; /* next */ pWord++; iWord++; } /* * It's not an assignment. * (This is the same as kmk_cc_eval_do_with_variable_list does.) */ pInstr = (PKMKCCEVALVARIABLES)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, KMKCCEVALVARIABLES_SIZE(cWords)); pInstr->Core.enmOpcode = kKmkCcEvalInstr_export; pInstr->Core.iLine = pCompiler->iLine; pInstr->cVars = cWords; kmk_cc_eval_init_spp_array_from_duplicated_words(pCompiler, cWords, pCompiler->paWords, pInstr->aVars); kmk_cc_block_realign(pCompiler->ppBlockTail); } else KMK_CC_ASSERT(0); } else { /* * We're exporting all variables. */ PKMKCCEVALCORE pInstr = kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr)); pInstr->enmOpcode = kKmkCcEvalInstr_export_all; pInstr->iLine = pCompiler->iLine; } return 1; } /** * When entering this function we know that the first two character in the first * word both independently occurs in keywords. * * @returns 1 if make directive or qualified variable assignment, 0 if neither. * @param pCompiler The compiler state. * @param ch The first char. * @param pchWord Pointer to the first word. * @param cchLeft Number of characters left to parse starting at * @a cchLeft. */ int kmk_cc_eval_try_handle_keyword(PKMKCCEVALCOMPILER pCompiler, char ch, const char *pchWord, size_t cchLeft) { unsigned iSavedEscEol = pCompiler->iEscEol; KMK_CC_ASSERT(cchLeft >= 2); KMK_CC_ASSERT(ch == pchWord[0]); KMK_CC_ASSERT(KMK_CC_EVAL_IS_1ST_IN_KEYWORD(pchWord[0])); KMK_CC_ASSERT(KMK_CC_EVAL_IS_2ND_IN_KEYWORD(pchWord[1])); /* * If it's potentially a variable related keyword, check that out first. */ if (KMK_CC_EVAL_IS_1ST_IN_VARIABLE_KEYWORD(ch)) { if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "local", 5)) return kmk_cc_eval_do_var_local(pCompiler, pchWord + 5, cchLeft - 5); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "define", 6)) return kmk_cc_eval_do_var_define(pCompiler, pchWord + 6, cchLeft - 6, 0); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "export", 6)) return kmk_cc_eval_handle_var_export(pCompiler, pchWord + 6, cchLeft - 6); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "undefine", 8)) return kmk_cc_eval_do_var_undefine(pCompiler, pchWord + 8, cchLeft - 8, 0); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "unexport", 8)) return kmk_cc_eval_do_var_unexport(pCompiler, pchWord + 8, cchLeft - 8, 0); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "override", 8)) { if (kmk_cc_eval_try_handle_var_with_keywords(pCompiler, pchWord + 8, cchLeft - 8, KMK_CC_EVAL_QUALIFIER_OVERRIDE)) return 1; pCompiler->iEscEol = iSavedEscEol; } else if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "private", 7)) { if (kmk_cc_eval_try_handle_var_with_keywords(pCompiler, pchWord + 7, cchLeft - 7, KMK_CC_EVAL_QUALIFIER_PRIVATE)) return 1; pCompiler->iEscEol = iSavedEscEol; } } /* * Check out the other keywords. */ if (ch == 'i') /* Lots of directives starting with 'i'. */ { char ch2 = pchWord[1]; pchWord += 2; cchLeft -= 2; /* 'if...' */ if (ch2 == 'f') { if (KMK_CC_EVAL_WORD_COMP_IS_EOL(pCompiler, pchWord, cchLeft)) return kmk_cc_eval_do_if(pCompiler, pchWord, cchLeft, 0 /* in else */); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "eq", 2)) return kmk_cc_eval_do_ifeq( pCompiler, pchWord + 2, cchLeft - 2, 0 /* in else */, 1 /* positive */); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "def", 3)) return kmk_cc_eval_do_ifdef(pCompiler, pchWord + 3, cchLeft - 3, 0 /* in else */, 1 /* positive */); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "neq", 3)) return kmk_cc_eval_do_ifeq( pCompiler, pchWord + 3, cchLeft - 3, 0 /* in else */, 0 /* positive */); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "1of", 3)) return kmk_cc_eval_do_if1of(pCompiler, pchWord + 3, cchLeft - 3, 0 /* in else */, 1 /* positive */); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "ndef", 4)) return kmk_cc_eval_do_ifdef(pCompiler, pchWord + 4, cchLeft - 4, 0 /* in else */, 0 /* positive */); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "n1of", 4)) return kmk_cc_eval_do_if1of(pCompiler, pchWord + 4, cchLeft - 4, 0 /* in else */, 0 /* positive */); } /* include... */ else if (ch2 == 'n' && cchLeft >= 5 && KMK_CC_WORD_COMP_CONST_5(pchWord, "clude") ) /* 'in...' */ { pchWord += 5; cchLeft -= 5; if (KMK_CC_EVAL_WORD_COMP_IS_EOL(pCompiler, pchWord, cchLeft)) return kmk_cc_eval_do_include(pCompiler, pchWord, cchLeft, kKmkCcEvalInstr_include); if (cchLeft >= 3 && KMK_CC_WORD_COMP_CONST_3(pchWord, "dep")) { pchWord += 3; cchLeft -= 3; if (KMK_CC_EVAL_WORD_COMP_IS_EOL(pCompiler, pchWord, cchLeft)) return kmk_cc_eval_do_include(pCompiler, pchWord, cchLeft, kKmkCcEvalInstr_includedep); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "-queue", 6)) return kmk_cc_eval_do_include(pCompiler, pchWord + 6, cchLeft - 6, kKmkCcEvalInstr_includedep_queue); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "-flush", 6)) return kmk_cc_eval_do_include(pCompiler, pchWord + 6, cchLeft - 6, kKmkCcEvalInstr_includedep_flush); } } } else if (ch == 'e') /* A few directives starts with 'e'. */ { if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "else", 4)) return kmk_cc_eval_do_else(pCompiler, pchWord + 4, cchLeft - 4); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "endif", 5)) return kmk_cc_eval_do_endif(pCompiler, pchWord + 5, cchLeft - 5); /* export and endef are handled elsewhere, though stray endef's may end up here... */ KMK_CC_ASSERT(!KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "export", 6)); } else /* the rest. */ { if ( KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "sinclude", 8) || KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "-include", 8)) return kmk_cc_eval_do_include(pCompiler, pchWord + 8, cchLeft - 8, kKmkCcEvalInstr_include_silent); if (KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "vpath", 5)) return kmk_cc_eval_do_vpath(pCompiler, pchWord + 5, cchLeft - 5); KMK_CC_ASSERT(!KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "local", 5)); KMK_CC_ASSERT(!KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "define", 6)); KMK_CC_ASSERT(!KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "private", 7)); KMK_CC_ASSERT(!KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "override", 8)); KMK_CC_ASSERT(!KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "unexport", 8)); KMK_CC_ASSERT(!KMK_CC_EVAL_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "undefine", 8)); } pCompiler->iEscEol = iSavedEscEol; return 0; } static int kmk_cc_eval_compile_worker(PKMKCCEVALPROG pEvalProg, const char *pszContent, size_t cchContent, unsigned iLine) { const char *pchTmp; /* * Compiler state. */ KMKCCEVALCOMPILER Compiler; kmk_cc_eval_init_compiler(&Compiler, pEvalProg, iLine, pszContent, cchContent); KMK_CC_EVAL_DPRINTF(("\nkmk_cc_eval_compile_worker - begin (%s/%s/%d)\n", pEvalProg->pszFilename, pEvalProg->pszVarName, iLine)); { /* * Line state. */ size_t cchLine; /* The length of the current line (w/o comments). */ size_t offNext = 0; /* The offset of the next line. */ size_t off = 0; /* The offset into pszContent of the current line. */ /* Try for some register/whatever optimzations. */ int const chFirstEol = Compiler.chFirstEol; size_t const cchEolSeq = Compiler.cchEolSeq; /* * Process input lines. * * The code here concerns itself with getting the next line in an efficient * manner, very basic classification and trying out corresponding handlers. * The real work is done in the handlers. */ while (offNext < cchContent) { size_t offFirstWord; /* * Find the end of the next line. */ KMK_CC_ASSERT(off == offNext); /* Simple case: No escaped EOL, nor the end of the input. */ pchTmp = (const char *)memchr(&pszContent[offNext], chFirstEol, cchContent - offNext); if ( pchTmp && ( &pszContent[offNext] == pchTmp || pchTmp[-1] != '\\') ) { if ( cchEolSeq == 1 || pchTmp[1] == Compiler.chSecondEol) { /* Frequent: Blank line. */ if (&pszContent[offNext] == pchTmp) { KMK_CC_EVAL_DPRINTF(("#%03u: \n", Compiler.iLine)); Compiler.iLine++; off = offNext += cchEolSeq; continue; } if (pszContent[offNext] == '#') { KMK_CC_EVAL_DPRINTF(("#%03u: \n", Compiler.iLine)); Compiler.iLine++; offNext = pchTmp - pszContent; off = offNext += cchEolSeq; continue; } offNext = pchTmp - pszContent; cchLine = offNext - off; offFirstWord = off; while (offFirstWord < offNext && KMK_CC_EVAL_IS_SPACE(pszContent[offFirstWord])) offFirstWord++; offNext += cchEolSeq; Compiler.cEscEols = 0; Compiler.iEscEol = 0; } else kmk_cc_eval_fatal_eol(&Compiler, pchTmp, Compiler.iLine, off); } /* The complicated, less common cases. */ else { Compiler.cEscEols = 0; Compiler.iEscEol = 0; offFirstWord = offNext; for (;;) { if (pchTmp) { if ( cchEolSeq == 1 || pchTmp[1] == Compiler.chSecondEol) { size_t offEsc; if (offFirstWord != offNext) offNext = pchTmp - pszContent; else { offNext = pchTmp - pszContent; while (offFirstWord < offNext && KMK_CC_EVAL_IS_SPACE(pszContent[offFirstWord])) offFirstWord++; } /* Is it an escape sequence? */ if ( !offNext || pchTmp[-1] != '\\') { cchLine = offNext - off; offNext += cchEolSeq; break; } if (offNext < 2 || pchTmp[-2] != '\\') offEsc = offNext - 1; else { /* Count how many backslashes there are. Must be odd number to be an escape sequence. Normally we keep half of them, except for command lines. */ size_t cSlashes = 2; while (offNext >= cSlashes && pchTmp[0 - cSlashes] == '\\') cSlashes--; if (!(cSlashes & 1)) { cchLine = offNext - off; offNext += cchEolSeq; break; } offEsc = offNext - (cSlashes >> 1); } /* Record it. */ if (Compiler.cEscEols < Compiler.cEscEolsAllocated) { /* likely */ } else { KMK_CC_ASSERT(Compiler.cEscEols == Compiler.cEscEolsAllocated); Compiler.cEscEolsAllocated = Compiler.cEscEolsAllocated ? Compiler.cEscEolsAllocated * 2 : 2; Compiler.paEscEols = (PKMKCCEVALESCEOL)xrealloc(Compiler.paEscEols, Compiler.cEscEolsAllocated * sizeof(Compiler.paEscEols[0])); } Compiler.paEscEols[Compiler.cEscEols].offEsc = offEsc; Compiler.paEscEols[Compiler.cEscEols].offEol = offNext; Compiler.cEscEols++; /* Advance. */ offNext += cchEolSeq; if (offFirstWord == offEsc) { offFirstWord = offNext; Compiler.iEscEol++; } } else kmk_cc_eval_fatal_eol(&Compiler, pchTmp, Compiler.iLine, off); } else { /* End of input. Happens only once per compilation, nothing to optimize for. */ if (offFirstWord == offNext) while (offFirstWord < cchContent && KMK_CC_EVAL_IS_SPACE(pszContent[offFirstWord])) offFirstWord++; offNext = cchContent; cchLine = cchContent - off; break; } pchTmp = (const char *)memchr(&pszContent[offNext], chFirstEol, cchContent - offNext); } } KMK_CC_ASSERT(offNext <= cchContent); KMK_CC_ASSERT(offNext >= off + cchLine); KMK_CC_ASSERT(off + cchLine <= cchContent && cchLine <= cchContent); KMK_CC_ASSERT(offFirstWord <= off + cchLine); KMK_CC_ASSERT(offFirstWord >= off); KMK_CC_ASSERT(pszContent[offFirstWord] != ' ' && pszContent[offFirstWord] != '\t'); KMK_CC_EVAL_DPRINTF(("#%03u: %*.*s\n", Compiler.iLine, (int)cchLine, (int)cchLine, &pszContent[off])); /* * Skip blank lines. */ if (offFirstWord < off + cchLine) { /* * Command? Ignore command prefix if no open recipe (SunOS 4 behavior). */ if ( pszContent[off] == Compiler.chCmdPrefix && (Compiler.pRecipe || Compiler.fNoTargetRecipe)) { if (!Compiler.fNoTargetRecipe) kmk_cc_eval_handle_command(&Compiler, &pszContent[off], cchLine); } /* * Since it's not a command line, we can now skip comment lines * even with a tab indentation. If it's not a comment line, we * tentatively strip any trailing comment. */ else if (pszContent[offFirstWord] != '#') { const char *pchWord = &pszContent[offFirstWord]; size_t cchLeft = off + cchLine - offFirstWord; char ch; Compiler.cchLineWithComments = cchLine; pchTmp = (const char *)memchr(pchWord, '#', cchLeft); if (pchTmp) { cchLeft = pchTmp - pchWord; cchLine = pchTmp - &pszContent[off]; } Compiler.cchLine = cchLine; /** @todo only used by assertions. */ Compiler.offLine = off; /** @todo only used by fatal errors. */ #ifdef KMK_CC_STRICT Compiler.cWords = 0x424242; #endif /* * If not a directive or variable qualifier, it's either a variable * assignment or a recipe. */ ch = *pchWord; if ( !KMK_CC_EVAL_IS_1ST_IN_KEYWORD(ch) || !KMK_CC_EVAL_IS_2ND_IN_KEYWORD(pchWord[1])) { if (memchr(pchWord, '=', cchLeft)) kmk_cc_eval_handle_assignment_or_recipe(&Compiler, pchWord, cchLeft, 0 /*fQualifiers*/); else kmk_cc_eval_handle_recipe(&Compiler, pchWord, cchLeft); } else { /* Possible directive or variable qualifier. */ Compiler.offNext = offNext; if (kmk_cc_eval_try_handle_keyword(&Compiler, ch, pchWord, cchLeft)) offNext = Compiler.offNext; /* No, that wasn't it... */ else if (memchr(pchWord, '=', cchLeft)) kmk_cc_eval_handle_assignment_or_recipe(&Compiler, pchWord, cchLeft, 0 /*fQualifiers*/); else kmk_cc_eval_handle_recipe(&Compiler, pchTmp, pchWord, cchLeft); } } } /* * Advance to the next line. */ off = offNext; Compiler.iLine += Compiler.cEscEols + 1; } } /* * Check whether */ kmk_cc_eval_delete_compiler(&Compiler); KMK_CC_EVAL_DPRINTF(("kmk_cc_eval_compile_worker - done (%s/%s)\n\n", pEvalProg->pszFilename, pEvalProg->pszVarName)); return 0; } static PKMKCCEVALPROG kmk_cc_eval_compile(const char *pszContent, size_t cchContent, const char *pszFilename, unsigned iLine, const char *pszVarName) { /* * Estimate block size, allocate one and initialize it. */ PKMKCCEVALPROG pEvalProg; PKMKCCBLOCK pBlock; pEvalProg = kmk_cc_block_alloc_first(&pBlock, sizeof(*pEvalProg), cchContent / 32); /** @todo adjust */ if (pEvalProg) { pEvalProg->pBlockTail = pBlock; pEvalProg->pFirstInstr = (PKMKCCEVALCORE)kmk_cc_block_get_next_ptr(pBlock); pEvalProg->pszFilename = pszFilename ? pszFilename : ""; pEvalProg->pszVarName = pszVarName; pEvalProg->cRefs = 1; #ifdef KMK_CC_STRICT pEvalProg->uInputHash = kmk_cc_debug_string_hash_n(0, pszContent, cchContent); #endif /* * Do the actual compiling. */ #ifdef CONFIG_WITH_EVAL_COMPILER if (kmk_cc_eval_compile_worker(pEvalProg, pszContent, cchContent, iLine) == 0) #else if (0) #endif { #ifdef KMK_CC_WITH_STATS pBlock = pEvalProg->pBlockTail; if (!pBlock->pNext) g_cSingleBlockEvalProgs++; else if (!pBlock->pNext->pNext) g_cTwoBlockEvalProgs++; else g_cMultiBlockEvalProgs++; for (; pBlock; pBlock = pBlock->pNext) { g_cBlocksAllocatedEvalProgs++; g_cbAllocatedEvalProgs += pBlock->cbBlock; g_cbUnusedMemEvalProgs += pBlock->cbBlock - pBlock->offNext; } #endif return pEvalProg; } kmk_cc_block_free_list(pEvalProg->pBlockTail); } return NULL; } /** * Compiles a variable direct evaluation as is, setting v->evalprog on success. * * @returns Pointer to the program on success, NULL if no program was created. * @param pVar Pointer to the variable. */ struct kmk_cc_evalprog *kmk_cc_compile_variable_for_eval(struct variable *pVar) { PKMKCCEVALPROG pEvalProg = pVar->evalprog; if (!pEvalProg) { #ifdef CONFIG_WITH_EVAL_COMPILER pEvalProg = kmk_cc_eval_compile(pVar->value, pVar->value_length, pVar->fileinfo.filenm, pVar->fileinfo.lineno, pVar->name); pVar->evalprog = pEvalProg; #endif g_cVarForEvalCompilations++; } return pEvalProg; } /** * Compiles a makefile for * * @returns Pointer to the program on success, NULL if no program was created. * @param pVar Pointer to the variable. */ struct kmk_cc_evalprog *kmk_cc_compile_file_for_eval(FILE *pFile, const char *pszFilename) { PKMKCCEVALPROG pEvalProg; /* * Read the entire file into a zero terminate memory buffer. */ size_t cchContent = 0; char *pszContent = NULL; struct stat st; if (!fstat(fileno(pFile), &st)) { if ( st.st_size > (off_t)KMK_CC_EVAL_MAX_COMPILE_SIZE && st.st_size < 0) fatal(NULL, _("Makefile too large to compile: %ld bytes (%#lx) - max %uMB"), (long)st.st_size, (long)st.st_size, KMK_CC_EVAL_MAX_COMPILE_SIZE / 1024 / 1024); cchContent = (size_t)st.st_size; pszContent = (char *)xmalloc(cchContent + 1); cchContent = fread(pszContent, 1, cchContent, pFile); if (ferror(pFile)) fatal(NULL, _("Read error: %s"), strerror(errno)); } else { size_t cbAllocated = 2048; do { cbAllocated *= 2; if (cbAllocated > KMK_CC_EVAL_MAX_COMPILE_SIZE) fatal(NULL, _("Makefile too large to compile: max %uMB"), KMK_CC_EVAL_MAX_COMPILE_SIZE / 1024 / 1024); pszContent = (char *)xrealloc(pszContent, cbAllocated); cchContent += fread(&pszContent[cchContent], 1, cbAllocated - 1 - cchContent, pFile); if (ferror(pFile)) fatal(NULL, _("Read error: %s"), strerror(errno)); } while (!feof(pFile)); } pszContent[cchContent] = '\0'; /* * Call common function to do the compilation. */ pEvalProg = kmk_cc_eval_compile(pszContent, cchContent, pszFilename, 1, NULL /*pszVarName*/); g_cFileForEvalCompilations++; free(pszContent); if (!pEvalProg) fseek(pFile, 0, SEEK_SET); return pEvalProg; } /** * Equivalent of eval_buffer, only it's using the evalprog of the variable. * * @param pVar Pointer to the variable. Must have a program. */ void kmk_exec_eval_variable(struct variable *pVar) { KMK_CC_ASSERT(pVar->evalprog); assert(0); } /** * Worker for eval_makefile. * * @param pEvalProg The program pointer. */ void kmk_exec_eval_file(struct kmk_cc_evalprog *pEvalProg) { KMK_CC_ASSERT(pEvalProg); assert(0); } /* * * Program destruction hooks. * Program destruction hooks. * Program destruction hooks. * */ /** * Called when a variable with expandprog or/and evalprog changes. * * @param pVar Pointer to the variable. */ void kmk_cc_variable_changed(struct variable *pVar) { PKMKCCEXPPROG pProg = pVar->expandprog; KMK_CC_ASSERT(pVar->evalprog || pProg); if (pVar->evalprog) { kmk_cc_block_free_list(pVar->evalprog->pBlockTail); pVar->evalprog = NULL; } if (pProg) { if (pProg->cRefs == 1) kmk_cc_block_free_list(pProg->pBlockTail); else fatal(NULL, _("Modifying a variable (%s) while its expansion program is running is not supported"), pVar->name); pVar->expandprog = NULL; } } /** * Called when a variable with expandprog or/and evalprog is deleted. * * @param pVar Pointer to the variable. */ void kmk_cc_variable_deleted(struct variable *pVar) { PKMKCCEXPPROG pProg = pVar->expandprog; KMK_CC_ASSERT(pVar->evalprog || pProg); if (pVar->evalprog) { kmk_cc_block_free_list(pVar->evalprog->pBlockTail); pVar->evalprog = NULL; } if (pProg) { if (pProg->cRefs == 1) kmk_cc_block_free_list(pProg->pBlockTail); else fatal(NULL, _("Deleting a variable (%s) while its expansion program is running is not supported"), pVar->name); pVar->expandprog = NULL; } } #endif /* CONFIG_WITH_COMPILER */ kbuild-3686/src/kmk/config.h.solaris0000664000175000017500000003063015053010075017354 0ustar locutuslocutus/* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.in by autoheader. */ /* Define to 1 if the `closedir' function returns void instead of `int'. */ /* #undef CLOSEDIR_VOID */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if using `getloadavg.c'. */ /* #undef C_GETLOADAVG */ /* Define to 1 for DGUX with . */ /* #undef DGUX */ /* Use high resolution file timestamps if nonzero. */ #define FILE_TIMESTAMP_HI_RES 1 /* Define to 1 if the `getloadavg' function needs to be run setuid or setgid. */ /* #undef GETLOADAVG_PRIVILEGED */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ #define HAVE_ALLOCA_H 1 /* Define to 1 if your compiler conforms to the ANSI C standard. */ #define HAVE_ANSI_COMPILER 1 /* Define to 1 if you have the `atexit' function. */ #define HAVE_ATEXIT 1 /* Define to 1 if you have the `bsd_signal' function. */ #define HAVE_BSD_SIGNAL 1 #define HAVE_DECL_BSD_SIGNAL 1 /* Use case insensitive file names */ /* #undef HAVE_CASE_INSENSITIVE_FS */ /* Define to 1 if you have the clock_gettime function. */ #define HAVE_CLOCK_GETTIME 1 /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you don't. */ #define HAVE_DECL_SYS_SIGLIST 0 /* Define to 1 if you have the declaration of `_sys_siglist', and to 0 if you don't. */ #define HAVE_DECL__SYS_SIGLIST 1 /* Define to 1 if you have the declaration of `__sys_siglist', and to 0 if you don't. */ #define HAVE_DECL___SYS_SIGLIST 0 /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #define HAVE_DOPRNT 1 /* Use platform specific coding */ /* #undef HAVE_DOS_PATHS */ /* Define to 1 if you have the `dup2' function. */ #define HAVE_DUP2 1 /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define to 1 if you have the `fdopen' function. */ #define HAVE_FDOPEN 1 /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getgroups' function. */ #define HAVE_GETGROUPS 1 /* Define to 1 if you have the `gethostbyname' function. */ /* #undef HAVE_GETHOSTBYNAME */ /* Define to 1 if you have the `gethostname' function. */ /* #undef HAVE_GETHOSTNAME */ /* Define to 1 if you have the `getloadavg' function. */ #define HAVE_GETLOADAVG 1 /* Define to 1 if you have the `getrlimit' function. */ #define HAVE_GETRLIMIT 1 /* Define to 1 if you have a standard gettimeofday function */ #define HAVE_GETTIMEOFDAY 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the `dgc' library (-ldgc). */ /* #undef HAVE_LIBDGC */ /* Define to 1 if you have the `kstat' library (-lkstat). */ #define HAVE_LIBKSTAT 1 /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you have the `lstat' function. */ #define HAVE_LSTAT 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MACH_MACH_H */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have the `mktemp' function. */ #define HAVE_MKTEMP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NLIST_H */ /* Define to 1 if you have the `pipe' function. */ #define HAVE_PIPE 1 /* Define to 1 if you have the `pselect' function. */ #define HAVE_PSELECT 1 /* Define to 1 if you have the `pstat_getdynamic' function. */ /* #undef HAVE_PSTAT_GETDYNAMIC */ /* Define to 1 if you have the `readlink' function. */ #define HAVE_READLINK 1 /* Define to 1 if you have the `realpath' function. */ #define HAVE_REALPATH 1 /* Define to 1 if defines the SA_RESTART constant. */ #define HAVE_SA_RESTART 1 /* Define to 1 if you have the `setegid' function. */ #define HAVE_SETEGID 1 /* Define to 1 if you have the `seteuid' function. */ #define HAVE_SETEUID 1 /* Define to 1 if you have the `setlinebuf' function. */ #define HAVE_SETLINEBUF 1 /* Define to 1 if you have the `setlocale' function. */ /* #undef HAVE_SETLOCALE */ /* Define to 1 if you have the `setregid' function. */ #define HAVE_SETREGID 1 /* Define to 1 if you have the `setreuid' function. */ #define HAVE_SETREUID 1 /* Define to 1 if you have the `setrlimit' function. */ #define HAVE_SETRLIMIT 1 /* Define to 1 if you have the `setvbuf' function. */ #define HAVE_SETVBUF 1 /* Define to 1 if you have the `sigaction' function. */ #define HAVE_SIGACTION 1 /* Define to 1 if you have the `sigsetmask' function. */ /* #undef HAVE_SIGSETMASK */ /* Define to 1 if you have the `socket' function. */ /* #undef HAVE_SOCKET */ /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 /* Define to 1 if you have the `strcmpi' function. */ /* #undef HAVE_STRCMPI */ /* Define to 1 if you have the `strncasecmp' function. */ #define HAVE_STRNCASECMP 1 /* Define to 1 if you have the `strncmpi' function. */ /* #undef HAVE_STRNCMPI */ /* Define to 1 if you have the `strncmp' function. */ /* #undef HAVE_STRNICMP */ /* Define to 1 if you have the `strcoll' function and it is properly defined. */ #define HAVE_STRCOLL 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the `stricmp' function. */ /* #undef HAVE_STRICMP */ /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strsignal' function. */ #define HAVE_STRSIGNAL 1 /* Define to 1 if `n_un.n_name' is member of `struct nlist'. */ /* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* 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, and it defines `DIR'. */ /* #undef HAVE_SYS_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_RESOURCE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIMEB_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_WAIT_H 1 /* Define to 1 if you have the \`union wait' type in . */ /* #undef HAVE_UNION_WAIT */ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VARARGS_H */ /* Define to 1 if you have the `vfork' function. */ #define HAVE_VFORK 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VFORK_H */ /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the `wait3' function. */ #define HAVE_WAIT3 1 /* Define to 1 if you have the `waitpid' function. */ #define HAVE_WAITPID 1 /* Define to 1 if `fork' works. */ #define HAVE_WORKING_FORK 1 /* Define to 1 if `vfork' works. */ #define HAVE_WORKING_VFORK 1 /* Build host information. (not used by kmk) */ #define MAKE_HOST "i386-pc-solaris2.11" /* Define to 1 to enable job server support in GNU make. */ #define MAKE_JOBSERVER 1 /* Define to 1 to enable symbolic link timestamp checking. */ #define MAKE_SYMLINKS 1 /* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend on `HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* #undef NLIST_NAME_UNION */ /* Define to 1 if struct nlist.n_name is a pointer rather than an array. */ /* #undef NLIST_STRUCT */ /* Define to 1 if your C compiler doesn't accept -c and -o together. */ /* #undef NO_MINUS_C_MINUS_O */ /* Name of package */ #define PACKAGE "make" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bug-make@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "GNU make" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "GNU make 3.82" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "make" /* Define to the version of this package. */ #define PACKAGE_VERSION "3.82" /* Define to the character that separates directories in PATH. */ #define PATH_SEPARATOR_CHAR ':' /* Define to 1 if the C compiler supports function prototypes. */ #define PROTOTYPES 1 /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* Define to the name of the SCCS 'get' command. */ #define SCCS_GET "get" /* Define to 1 if the SCCS 'get' command understands the '-G' option. */ #define SCCS_GET_MINUS_G 1 /* Define to 1 if the `setvbuf' function takes the buffering type as its second argument and the buffer pointer as the third, as on System V before release 3. */ /* #undef SETVBUF_REVERSED */ /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if the `S_IS*' macros in do not work properly. */ /* #undef STAT_MACROS_BROKEN */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define if struct stat contains a nanoseconds field */ #define ST_MTIM_NSEC st_mtim.tv_nsec #define ST_ATIM_NSEC st_atim.tv_nsec /* Define to 1 on System V Release 4. */ /* #undef SVR4 */ /* Define to 1 if you can safely include both and . */ #define TIME_WITH_SYS_TIME 1 /* Define to 1 for Encore UMAX. */ /* #undef UMAX */ /* Define to 1 for Encore UMAX 4.3 that has instead of . */ /* #undef UMAX4_3 */ /* Version number of package */ #define VERSION "3.82" /* Use platform specific coding */ /* #undef WINDOWS32 */ /* Define if using the dmalloc debugging malloc package */ /* #undef WITH_DMALLOC */ /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* # undef _ALL_SOURCE */ #endif /* Number of bits in a file offset, on hosts where this is settable. */ #define _FILE_OFFSET_BITS 64 /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Define like PROTOTYPES; this can be used by system headers. */ #define __PROTOTYPES 1 /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `int' if doesn't define. */ /* #undef gid_t */ /* Define to `int' if does not define. */ /* #undef pid_t */ /* Define to `int' if doesn't define. */ /* #undef uid_t */ /* Define uintmax_t if not defined in or . */ /* #undef uintmax_t */ /* Define as `fork' if `vfork' does not work. */ /* #undef vfork */ #include "inlined_memchr.h" kbuild-3686/src/kmk/amiga.h0000664000175000017500000000146015053010075015511 0ustar locutuslocutus/* Definitions for amiga specific things Copyright (C) 1995-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ int MyExecute (char ** argv); char * wildcard_expansion (char * wc, char * o); kbuild-3686/src/kmk/variable.c0000664000175000017500000033031315053010075016215 0ustar locutuslocutus/* Internals of variables for GNU Make. Copyright (C) 1988-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include "makeint.h" #include #include "filedef.h" #include "dep.h" #include "job.h" #include "commands.h" #include "variable.h" #include "rule.h" #ifdef WINDOWS32 #include "pathstuff.h" #endif #include "hash.h" #ifdef KMK # include "kbuild.h" # ifdef WINDOWS32 # include # else # include # endif #endif #ifdef CONFIG_WITH_STRCACHE2 # include #endif #ifdef CONFIG_WITH_COMPILER # include "kmk_cc_exec.h" #endif #ifdef KMK /** Gets the real variable if alias. For use when looking up variables. */ # define RESOLVE_ALIAS_VARIABLE(v) \ do { \ if ((v) != NULL && (v)->alias) \ { \ (v) = (struct variable *)(v)->value; \ assert ((v)->aliased); \ assert (!(v)->alias); \ } \ } while (0) #endif #ifdef KMK /* Incremented every time a variable is modified, so that target_environment knows when to regenerate the table of exported global variables. */ static size_t global_variable_generation = 0; #endif /* Incremented every time we add or remove a global variable. */ static unsigned long variable_changenum; /* Chain of all pattern-specific variables. */ static struct pattern_var *pattern_vars; /* Pointer to the last struct in the pack of a specific size, from 1 to 255.*/ static struct pattern_var *last_pattern_vars[256]; /* Create a new pattern-specific variable struct. The new variable is inserted into the PATTERN_VARS list in the shortest patterns first order to support the shortest stem matching (the variables are matched in the reverse order so the ones with the longest pattern will be considered first). Variables with the same pattern length are inserted in the definition order. */ struct pattern_var * create_pattern_var (const char *target, const char *suffix) { register unsigned int len = strlen (target); register struct pattern_var *p = xmalloc (sizeof (struct pattern_var)); if (pattern_vars != 0) { if (len < 256 && last_pattern_vars[len] != 0) { p->next = last_pattern_vars[len]->next; last_pattern_vars[len]->next = p; } else { /* Find the position where we can insert this variable. */ register struct pattern_var **v; for (v = &pattern_vars; ; v = &(*v)->next) { /* Insert at the end of the pack so that patterns with the same length appear in the order they were defined .*/ if (*v == 0 || (*v)->len > len) { p->next = *v; *v = p; break; } } } } else { pattern_vars = p; p->next = 0; } p->target = target; p->len = len; p->suffix = suffix + 1; if (len < 256) last_pattern_vars[len] = p; return p; } /* Look up a target in the pattern-specific variable list. */ static struct pattern_var * lookup_pattern_var (struct pattern_var *start, const char *target) { struct pattern_var *p; unsigned int targlen = strlen (target); for (p = start ? start->next : pattern_vars; p != 0; p = p->next) { const char *stem; unsigned int stemlen; if (p->len > targlen) /* It can't possibly match. */ continue; /* From the lengths of the filename and the pattern parts, find the stem: the part of the filename that matches the %. */ stem = target + (p->suffix - p->target - 1); stemlen = targlen - p->len + 1; /* Compare the text in the pattern before the stem, if any. */ if (stem > target && !strneq (p->target, target, stem - target)) continue; /* Compare the text in the pattern after the stem, if any. We could test simply using streq, but this way we compare the first two characters immediately. This saves time in the very common case where the first character matches because it is a period. */ if (*p->suffix == stem[stemlen] && (*p->suffix == '\0' || streq (&p->suffix[1], &stem[stemlen+1]))) break; } return p; } #ifdef CONFIG_WITH_STRCACHE2 struct strcache2 variable_strcache; #endif /* Hash table of all global variable definitions. */ #ifndef CONFIG_WITH_STRCACHE2 static unsigned long variable_hash_1 (const void *keyv) { struct variable const *key = (struct variable const *) keyv; return_STRING_N_HASH_1 (key->name, key->length); } static unsigned long variable_hash_2 (const void *keyv) { struct variable const *key = (struct variable const *) keyv; return_STRING_N_HASH_2 (key->name, key->length); } static int variable_hash_cmp (const void *xv, const void *yv) { struct variable const *x = (struct variable const *) xv; struct variable const *y = (struct variable const *) yv; int result = x->length - y->length; if (result) return result; return_STRING_N_COMPARE (x->name, y->name, x->length); } #endif /* !CONFIG_WITH_STRCACHE2 */ #ifndef VARIABLE_BUCKETS # ifdef KMK /* Move to Makefile.kmk? (insanely high, but wtf, it gets the collitions down) */ # define VARIABLE_BUCKETS 65535 # else /*!KMK*/ #define VARIABLE_BUCKETS 523 # endif /*!KMK*/ #endif #ifndef PERFILE_VARIABLE_BUCKETS # ifdef KMK /* Move to Makefile.kmk? */ # define PERFILE_VARIABLE_BUCKETS 127 # else #define PERFILE_VARIABLE_BUCKETS 23 # endif #endif #ifndef SMALL_SCOPE_VARIABLE_BUCKETS # ifdef KMK /* Move to Makefile.kmk? */ # define SMALL_SCOPE_VARIABLE_BUCKETS 63 # else #define SMALL_SCOPE_VARIABLE_BUCKETS 13 # endif #endif #ifndef ENVIRONMENT_VARIABLE_BUCKETS /* added by bird. */ # define ENVIRONMENT_VARIABLE_BUCKETS 256 #endif #ifdef KMK /* Drop the 'static' */ struct variable_set global_variable_set; struct variable_set_list global_setlist #else static struct variable_set global_variable_set; static struct variable_set_list global_setlist #endif = { 0, &global_variable_set, 0 }; struct variable_set_list *current_variable_set_list = &global_setlist; /* Implement variables. */ void init_hash_global_variable_set (void) { #ifndef CONFIG_WITH_STRCACHE2 hash_init (&global_variable_set.table, VARIABLE_BUCKETS, variable_hash_1, variable_hash_2, variable_hash_cmp); #else /* CONFIG_WITH_STRCACHE2 */ strcache2_init (&variable_strcache, "variable", 262144, 0, 0, 0); hash_init_strcached (&global_variable_set.table, VARIABLE_BUCKETS, &variable_strcache, offsetof (struct variable, name)); #endif /* CONFIG_WITH_STRCACHE2 */ } /* Define variable named NAME with value VALUE in SET. VALUE is copied. LENGTH is the length of NAME, which does not need to be null-terminated. ORIGIN specifies the origin of the variable (makefile, command line or environment). If RECURSIVE is nonzero a flag is set in the variable saying that it should be recursively re-expanded. */ #ifdef CONFIG_WITH_VALUE_LENGTH struct variable * define_variable_in_set (const char *name, unsigned int length, const char *value, unsigned int value_len, int duplicate_value, enum variable_origin origin, int recursive, struct variable_set *set, const floc *flocp) #else struct variable * define_variable_in_set (const char *name, unsigned int length, const char *value, enum variable_origin origin, int recursive, struct variable_set *set, const floc *flocp) #endif { struct variable *v; struct variable **var_slot; struct variable var_key; #ifdef KMK if (set == NULL || set == &global_variable_set) global_variable_generation++; #endif if (env_overrides && origin == o_env) origin = o_env_override; #ifndef KMK if (set == NULL) set = &global_variable_set; #else /* KMK */ /* Intercept kBuild object variable definitions. */ if (name[0] == '[' && length > 3) { v = try_define_kbuild_object_variable_via_accessor (name, length, value, value_len, duplicate_value, origin, recursive, flocp); if (v != VAR_NOT_KBUILD_ACCESSOR) return v; } if (set == NULL) { if (g_pTopKbEvalData) return define_kbuild_object_variable_in_top_obj (name, length, value, value_len, duplicate_value, origin, recursive, flocp); set = &global_variable_set; } #endif /* KMK */ #ifndef CONFIG_WITH_STRCACHE2 var_key.name = (char *) name; var_key.length = length; var_slot = (struct variable **) hash_find_slot (&set->table, &var_key); v = *var_slot; #ifdef VMS /* VMS does not populate envp[] with DCL symbols and logical names which historically are mapped to environent variables. If the variable is not yet defined, then we need to check if getenv() can find it. Do not do this for origin == o_env to avoid infinte recursion */ if (HASH_VACANT (v) && (origin != o_env)) { struct variable * vms_variable; char * vname = alloca (length + 1); char * vvalue; strncpy (vname, name, length); vvalue = getenv(vname); /* Values starting with '$' are probably foreign commands. We want to treat them as Shell aliases and not look them up here */ if ((vvalue != NULL) && (vvalue[0] != '$')) { vms_variable = lookup_variable(name, length); /* Refresh the slot */ var_slot = (struct variable **) hash_find_slot (&set->table, &var_key); v = *var_slot; } } #endif /* if (env_overrides && origin == o_env) origin = o_env_override; - bird moved this up */ #else /* CONFIG_WITH_STRCACHE2 */ name = strcache2_add (&variable_strcache, name, length); if ( set != &global_variable_set || !(v = strcache2_get_user_val (&variable_strcache, name))) { var_key.name = name; var_key.length = length; var_slot = (struct variable **) hash_find_slot_strcached (&set->table, &var_key); v = *var_slot; } else { assert (!v || (v->name == name && !HASH_VACANT (v))); var_slot = 0; } #endif /* CONFIG_WITH_STRCACHE2 */ if (! HASH_VACANT (v)) { #ifdef KMK RESOLVE_ALIAS_VARIABLE(v); #endif if (env_overrides && v->origin == o_env) /* V came from in the environment. Since it was defined before the switches were parsed, it wasn't affected by -e. */ v->origin = o_env_override; /* A variable of this name is already defined. If the old definition is from a stronger source than this one, don't redefine it. */ if ((int) origin >= (int) v->origin) { #ifdef CONFIG_WITH_VALUE_LENGTH if (value_len == ~0U) value_len = strlen (value); else assert (value_len == strlen (value)); if (!duplicate_value || duplicate_value == -1) { # ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE if (v->value != 0 && !v->rdonly_val) free (v->value); v->rdonly_val = duplicate_value == -1; v->value = (char *) value; v->value_alloc_len = 0; # else if (v->value != 0) free (v->value); v->value = (char *) value; v->value_alloc_len = value_len + 1; # endif } else { if (v->value_alloc_len <= value_len) { # ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE if (v->rdonly_val) v->rdonly_val = 0; else # endif free (v->value); v->value_alloc_len = VAR_ALIGN_VALUE_ALLOC (value_len + 1); v->value = xmalloc (v->value_alloc_len); MAKE_STATS_2(v->reallocs++); } memcpy (v->value, value, value_len + 1); } v->value_length = value_len; #else /* !CONFIG_WITH_VALUE_LENGTH */ free (v->value); v->value = xstrdup (value); #endif /* !CONFIG_WITH_VALUE_LENGTH */ if (flocp != 0) v->fileinfo = *flocp; else v->fileinfo.filenm = 0; v->origin = origin; v->recursive = recursive; VARIABLE_CHANGED (v); } return v; } /* Create a new variable definition and add it to the hash table. */ #ifndef CONFIG_WITH_ALLOC_CACHES v = xmalloc (sizeof (struct variable)); #else v = alloccache_alloc (&variable_cache); #endif #ifndef CONFIG_WITH_STRCACHE2 v->name = xstrndup (name, length); #else v->name = name; /* already cached. */ #endif v->length = length; hash_insert_at (&set->table, v, var_slot); if (set == &global_variable_set) ++variable_changenum; #ifdef CONFIG_WITH_VALUE_LENGTH if (value_len == ~0U) value_len = strlen (value); else assert (value_len == strlen (value)); v->value_length = value_len; if (!duplicate_value || duplicate_value == -1) { # ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE v->rdonly_val = duplicate_value == -1; v->value_alloc_len = v->rdonly_val ? 0 : value_len + 1; # endif v->value = (char *)value; } else { # ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE v->rdonly_val = 0; # endif v->value_alloc_len = VAR_ALIGN_VALUE_ALLOC (value_len + 1); v->value = xmalloc (v->value_alloc_len); memcpy (v->value, value, value_len + 1); } #else /* !CONFIG_WITH_VALUE_LENGTH */ v->value = xstrdup (value); #endif /* !CONFIG_WITH_VALUE_LENGTH */ if (flocp != 0) v->fileinfo = *flocp; else v->fileinfo.filenm = 0; v->origin = origin; v->recursive = recursive; v->special = 0; v->expanding = 0; v->exp_count = 0; v->per_target = 0; v->append = 0; v->private_var = 0; #ifdef KMK v->alias = 0; v->aliased = 0; #endif v->export = v_default; #ifdef CONFIG_WITH_COMPILER v->recursive_without_dollar = 0; v->evalprog = 0; v->expandprog = 0; v->evalval_count = 0; v->expand_count = 0; #else MAKE_STATS_2(v->expand_count = 0); MAKE_STATS_2(v->evalval_count = 0); #endif MAKE_STATS_2(v->changes = 0); MAKE_STATS_2(v->reallocs = 0); MAKE_STATS_2(v->references = 0); MAKE_STATS_2(v->cTicksEvalVal = 0); v->exportable = 1; if (*name != '_' && (*name < 'A' || *name > 'Z') && (*name < 'a' || *name > 'z')) v->exportable = 0; else { for (++name; *name != '\0'; ++name) if (*name != '_' && (*name < 'a' || *name > 'z') && (*name < 'A' || *name > 'Z') && !ISDIGIT(*name)) break; if (*name != '\0') v->exportable = 0; } #ifdef CONFIG_WITH_STRCACHE2 /* If it's the global set, remember the variable. */ if (set == &global_variable_set) strcache2_set_user_val (&variable_strcache, v->name, v); #endif return v; } /* Undefine variable named NAME in SET. LENGTH is the length of NAME, which does not need to be null-terminated. ORIGIN specifies the origin of the variable (makefile, command line or environment). */ static void free_variable_name_and_value (const void *item) { struct variable *v = (struct variable *) item; #ifndef CONFIG_WITH_STRCACHE2 free (v->name); #endif #ifdef CONFIG_WITH_COMPILER if (v->evalprog || v->expandprog) kmk_cc_variable_deleted (v); #endif #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE if (!v->rdonly_val) #endif free (v->value); } void free_variable_set (struct variable_set_list *list) { hash_map (&list->set->table, free_variable_name_and_value); #ifndef CONFIG_WITH_ALLOC_CACHES hash_free (&list->set->table, 1); free (list->set); free (list); #else hash_free_cached (&list->set->table, 1, &variable_cache); alloccache_free (&variable_set_cache, list->set); alloccache_free (&variable_set_list_cache, list); #endif } void undefine_variable_in_set (const char *name, unsigned int length, enum variable_origin origin, struct variable_set *set) { struct variable *v; struct variable **var_slot; struct variable var_key; if (set == NULL) set = &global_variable_set; #ifndef CONFIG_WITH_STRCACHE2 var_key.name = (char *) name; var_key.length = length; var_slot = (struct variable **) hash_find_slot (&set->table, &var_key); #else var_key.name = strcache2_lookup(&variable_strcache, name, length); if (!var_key.name) return; var_key.length = length; var_slot = (struct variable **) hash_find_slot_strcached (&set->table, &var_key); #endif #ifdef KMK if (set == &global_variable_set) global_variable_generation++; #endif if (env_overrides && origin == o_env) origin = o_env_override; v = *var_slot; if (! HASH_VACANT (v)) { #ifdef KMK if (v->aliased || v->alias) { if (v->aliased) OS (error, NULL, _("Cannot undefine the aliased variable '%s'"), v->name); else OS (error, NULL, _("Cannot undefine the variable alias '%s'"), v->name); return; } #endif if (env_overrides && v->origin == o_env) /* V came from in the environment. Since it was defined before the switches were parsed, it wasn't affected by -e. */ v->origin = o_env_override; /* Undefine only if this undefinition is from an equal or stronger source than the variable definition. */ if ((int) origin >= (int) v->origin) { hash_delete_at (&set->table, var_slot); #ifdef CONFIG_WITH_STRCACHE2 if (set == &global_variable_set) strcache2_set_user_val (&variable_strcache, v->name, NULL); #endif free_variable_name_and_value (v); #ifndef CONFIG_WITH_ALLOC_CACHES free (v); #else alloccache_free (&variable_cache, v); #endif if (set == &global_variable_set) ++variable_changenum; } } } #ifdef KMK /* Define variable named NAME as an alias of the variable TARGET. SET defaults to the global set if NULL. FLOCP is just for completeness. */ struct variable * define_variable_alias_in_set (const char *name, unsigned int length, struct variable *target, enum variable_origin origin, struct variable_set *set, const floc *flocp) { struct variable *v; struct variable **var_slot; #ifdef KMK if (set == NULL || set == &global_variable_set) global_variable_generation++; #endif /* Look it up the hash table slot for it. */ name = strcache2_add (&variable_strcache, name, length); if ( set != &global_variable_set || !(v = strcache2_get_user_val (&variable_strcache, name))) { struct variable var_key; var_key.name = name; var_key.length = length; var_slot = (struct variable **) hash_find_slot_strcached (&set->table, &var_key); v = *var_slot; } else { assert (!v || (v->name == name && !HASH_VACANT (v))); var_slot = 0; } if (! HASH_VACANT (v)) { /* A variable of this name is already defined. If the old definition is from a stronger source than this one, don't redefine it. */ if (env_overrides && v->origin == o_env) /* V came from in the environment. Since it was defined before the switches were parsed, it wasn't affected by -e. */ v->origin = o_env_override; if ((int) origin < (int) v->origin) return v; if (v->value != 0 && !v->rdonly_val) free (v->value); VARIABLE_CHANGED (v); } else { /* Create a new variable definition and add it to the hash table. */ v = alloccache_alloc (&variable_cache); v->name = name; /* already cached. */ v->length = length; hash_insert_at (&set->table, v, var_slot); v->special = 0; v->expanding = 0; v->exp_count = 0; v->per_target = 0; v->append = 0; v->private_var = 0; v->aliased = 0; v->export = v_default; #ifdef CONFIG_WITH_COMPILER v->recursive_without_dollar = 0; v->evalprog = 0; v->expandprog = 0; v->evalval_count = 0; v->expand_count = 0; #else MAKE_STATS_2(v->expand_count = 0); MAKE_STATS_2(v->evalval_count = 0); #endif MAKE_STATS_2(v->changes = 0); MAKE_STATS_2(v->reallocs = 0); MAKE_STATS_2(v->references = 0); MAKE_STATS_2(v->cTicksEvalVal = 0); v->exportable = 1; if (*name != '_' && (*name < 'A' || *name > 'Z') && (*name < 'a' || *name > 'z')) v->exportable = 0; else { for (++name; *name != '\0'; ++name) if (*name != '_' && (*name < 'a' || *name > 'z') && (*name < 'A' || *name > 'Z') && !ISDIGIT(*name)) break; if (*name != '\0') v->exportable = 0; } /* If it's the global set, remember the variable. */ if (set == &global_variable_set) strcache2_set_user_val (&variable_strcache, v->name, v); } /* Common variable setup. */ v->alias = 1; v->rdonly_val = 1; v->value = (char *)target; v->value_length = sizeof(*target); /* Non-zero to provoke trouble. */ v->value_alloc_len = sizeof(*target); if (flocp != 0) v->fileinfo = *flocp; else v->fileinfo.filenm = 0; v->origin = origin; v->recursive = 0; /* Mark the target as aliased. */ target->aliased = 1; return v; } #endif /* KMK */ /* If the variable passed in is "special", handle its special nature. Currently there are two such variables, both used for introspection: .VARIABLES expands to a list of all the variables defined in this instance of make. .TARGETS expands to a list of all the targets defined in this instance of make. Returns the variable reference passed in. */ #define EXPANSION_INCREMENT(_l) ((((_l) / 500) + 1) * 500) static struct variable * lookup_special_var (struct variable *var) { static unsigned long last_changenum = 0; /* This one actually turns out to be very hard, due to the way the parser records targets. The way it works is that target information is collected internally until make knows the target is completely specified. It unitl it sees that some new construct (a new target or variable) is defined that it knows the previous one is done. In short, this means that if you do this: all: TARGS := $(.TARGETS) then $(TARGS) won't contain "all", because it's not until after the variable is created that the previous target is completed. Changing this would be a major pain. I think a less complex way to do it would be to pre-define the target files as soon as the first line is parsed, then come back and do the rest of the definition as now. That would allow $(.TARGETS) to be correct without a major change to the way the parser works. if (streq (var->name, ".TARGETS")) var->value = build_target_list (var->value); else */ if (variable_changenum != last_changenum && streq (var->name, ".VARIABLES")) { #ifndef CONFIG_WITH_VALUE_LENGTH unsigned long max = EXPANSION_INCREMENT (strlen (var->value)); #else unsigned long max = EXPANSION_INCREMENT (var->value_length); #endif unsigned long len; char *p; struct variable **vp = (struct variable **) global_variable_set.table.ht_vec; struct variable **end = &vp[global_variable_set.table.ht_size]; /* Make sure we have at least MAX bytes in the allocated buffer. */ var->value = xrealloc (var->value, max); MAKE_STATS_2(var->reallocs++); /* Walk through the hash of variables, constructing a list of names. */ p = var->value; len = 0; for (; vp < end; ++vp) if (!HASH_VACANT (*vp)) { struct variable *v = *vp; int l = v->length; len += l + 1; if (len > max) { unsigned long off = p - var->value; max += EXPANSION_INCREMENT (l + 1); var->value = xrealloc (var->value, max); p = &var->value[off]; MAKE_STATS_2(var->reallocs++); } memcpy (p, v->name, l); p += l; *(p++) = ' '; } *(p-1) = '\0'; #ifdef CONFIG_WITH_VALUE_LENGTH var->value_length = p - var->value - 1; var->value_alloc_len = max; #endif VARIABLE_CHANGED (var); /* Remember the current variable change number. */ last_changenum = variable_changenum; } return var; } #if 0 /*FIX THIS - def KMK*/ /* bird: speed */ MY_INLINE struct variable * lookup_cached_variable (const char *name) { const struct variable_set_list *setlist = current_variable_set_list; struct hash_table *ht; unsigned int hash_1; unsigned int hash_2; unsigned int idx; struct variable *v; /* first set, first entry, both unrolled. */ if (setlist->set == &global_variable_set) { v = (struct variable *) strcache2_get_user_val (&variable_strcache, name); if (MY_PREDICT_TRUE (v)) return MY_PREDICT_FALSE (v->special) ? lookup_special_var (v) : v; assert (setlist->next == 0); return 0; } hash_1 = strcache2_calc_ptr_hash (&variable_strcache, name); ht = &setlist->set->table; MAKE_STATS (ht->ht_lookups++); idx = hash_1 & (ht->ht_size - 1); v = ht->ht_vec[idx]; if (v != 0) { if ( (void *)v != hash_deleted_item && v->name == name) return MY_PREDICT_FALSE (v->special) ? lookup_special_var (v) : v; /* the rest of the loop */ hash_2 = strcache2_get_hash (&variable_strcache, name) | 1; for (;;) { idx += hash_2; idx &= (ht->ht_size - 1); v = (struct variable *) ht->ht_vec[idx]; MAKE_STATS (ht->ht_collisions++); /* there are hardly any deletions, so don't bother with not counting deleted clashes. */ if (v == 0) break; if ( (void *)v != hash_deleted_item && v->name == name) return MY_PREDICT_FALSE (v->special) ? lookup_special_var (v) : v; } /* inner collision loop */ } else hash_2 = strcache2_get_hash (&variable_strcache, name) | 1; /* The other sets, if any. */ setlist = setlist->next; while (setlist) { if (setlist->set == &global_variable_set) { v = (struct variable *) strcache2_get_user_val (&variable_strcache, name); if (MY_PREDICT_TRUE (v)) return MY_PREDICT_FALSE (v->special) ? lookup_special_var (v) : v; assert (setlist->next == 0); return 0; } /* first iteration unrolled */ ht = &setlist->set->table; MAKE_STATS (ht->ht_lookups++); idx = hash_1 & (ht->ht_size - 1); v = ht->ht_vec[idx]; if (v != 0) { if ( (void *)v != hash_deleted_item && v->name == name) return MY_PREDICT_FALSE (v->special) ? lookup_special_var (v) : v; /* the rest of the loop */ for (;;) { idx += hash_2; idx &= (ht->ht_size - 1); v = (struct variable *) ht->ht_vec[idx]; MAKE_STATS (ht->ht_collisions++); /* see reason above */ if (v == 0) break; if ( (void *)v != hash_deleted_item && v->name == name) return MY_PREDICT_FALSE (v->special) ? lookup_special_var (v) : v; } /* inner collision loop */ } /* next */ setlist = setlist->next; } return 0; } # ifndef NDEBUG struct variable * lookup_variable_for_assert (const char *name, unsigned int length) { const struct variable_set_list *setlist; struct variable var_key; var_key.name = name; var_key.length = length; for (setlist = current_variable_set_list; setlist != 0; setlist = setlist->next) { struct variable *v; v = (struct variable *) hash_find_item_strcached (&setlist->set->table, &var_key); if (v) return MY_PREDICT_FALSE (v->special) ? lookup_special_var (v) : v; } return 0; } # endif /* !NDEBUG */ #endif /* KMK - need for speed */ /* Lookup a variable whose name is a string starting at NAME and with LENGTH chars. NAME need not be null-terminated. Returns address of the 'struct variable' containing all info on the variable, or nil if no such variable is defined. */ struct variable * lookup_variable (const char *name, unsigned int length) { #if 1 /*FIX THIS - ndef KMK*/ const struct variable_set_list *setlist; struct variable var_key; #else /* KMK */ struct variable *v; #endif /* KMK */ int is_parent = 0; #ifdef CONFIG_WITH_STRCACHE2 const char *cached_name; #endif # ifdef KMK /* Check for kBuild-define- local variable accesses and handle these first. */ if (length > 3 && name[0] == '[') { struct variable *v = lookup_kbuild_object_variable_accessor(name, length); if (v != VAR_NOT_KBUILD_ACCESSOR) { MAKE_STATS_2 (v->references++); return v; } } # endif #ifdef CONFIG_WITH_STRCACHE2 /* lookup the name in the string case, if it's not there it won't be in any of the sets either. */ cached_name = strcache2_lookup (&variable_strcache, name, length); if (!cached_name) return NULL; name = cached_name; #endif /* CONFIG_WITH_STRCACHE2 */ #if 1 /*FIX THIS - ndef KMK */ var_key.name = (char *) name; var_key.length = length; for (setlist = current_variable_set_list; setlist != 0; setlist = setlist->next) { const struct variable_set *set = setlist->set; struct variable *v; # ifndef CONFIG_WITH_STRCACHE2 v = (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key); # else /* CONFIG_WITH_STRCACHE2 */ v = (struct variable *) hash_find_item_strcached ((struct hash_table *) &set->table, &var_key); # endif /* CONFIG_WITH_STRCACHE2 */ if (v && (!is_parent || !v->private_var)) { # ifdef KMK RESOLVE_ALIAS_VARIABLE(v); # endif MAKE_STATS_2 (v->references++); return v->special ? lookup_special_var (v) : v; } is_parent |= setlist->next_is_parent; } #else /* KMK - need for speed */ v = lookup_cached_variable (name); assert (lookup_variable_for_assert(name, length) == v); #ifdef VMS if (v) #endif return v; #endif /* KMK - need for speed */ #ifdef VMS /* VMS does not populate envp[] with DCL symbols and logical names which historically are mapped to enviroment varables and returned by getenv() */ { char *vname = alloca (length + 1); char *value; strncpy (vname, name, length); vname[length] = 0; value = getenv (vname); if (value != 0) { char *sptr; int scnt; sptr = value; scnt = 0; while ((sptr = strchr (sptr, '$'))) { scnt++; sptr++; } if (scnt > 0) { char *nvalue; char *nptr; nvalue = alloca (strlen (value) + scnt + 1); sptr = value; nptr = nvalue; while (*sptr) { if (*sptr == '$') { *nptr++ = '$'; *nptr++ = '$'; } else { *nptr++ = *sptr; } sptr++; } *nptr = '\0'; return define_variable (vname, length, nvalue, o_env, 1); } return define_variable (vname, length, value, o_env, 1); } } #endif /* VMS */ return 0; } #ifdef CONFIG_WITH_STRCACHE2 /* Alternative version of lookup_variable that takes a name that's already in the variable string cache. */ struct variable * lookup_variable_strcached (const char *name) { struct variable *v; #if 1 /*FIX THIS - ndef KMK*/ const struct variable_set_list *setlist; struct variable var_key; #endif /* KMK */ int is_parent = 0; #ifndef NDEBUG strcache2_verify_entry (&variable_strcache, name); #endif #ifdef KMK /* Check for kBuild-define- local variable accesses and handle these first. */ if (strcache2_get_len(&variable_strcache, name) > 3 && name[0] == '[') { v = lookup_kbuild_object_variable_accessor(name, strcache2_get_len(&variable_strcache, name)); if (v != VAR_NOT_KBUILD_ACCESSOR) { MAKE_STATS_2 (v->references++); return v; } } #endif #if 1 /*FIX THIS - ndef KMK */ var_key.name = (char *) name; var_key.length = strcache2_get_len(&variable_strcache, name); for (setlist = current_variable_set_list; setlist != 0; setlist = setlist->next) { const struct variable_set *set = setlist->set; v = (struct variable *) hash_find_item_strcached ((struct hash_table *) &set->table, &var_key); if (v && (!is_parent || !v->private_var)) { # ifdef KMK RESOLVE_ALIAS_VARIABLE(v); # endif MAKE_STATS_2 (v->references++); return v->special ? lookup_special_var (v) : v; } is_parent |= setlist->next_is_parent; } #else /* KMK - need for speed */ v = lookup_cached_variable (name); assert (lookup_variable_for_assert(name, length) == v); #ifdef VMS if (v) #endif return v; #endif /* KMK - need for speed */ #ifdef VMS # error "Port me (split out the relevant code from lookup_varaible and call it)" #endif return 0; } #endif /* Lookup a variable whose name is a string starting at NAME and with LENGTH chars in set SET. NAME need not be null-terminated. Returns address of the 'struct variable' containing all info on the variable, or nil if no such variable is defined. */ struct variable * lookup_variable_in_set (const char *name, unsigned int length, const struct variable_set *set) { struct variable var_key; #ifndef CONFIG_WITH_STRCACHE2 var_key.name = (char *) name; var_key.length = length; return (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key); #else /* CONFIG_WITH_STRCACHE2 */ const char *cached_name; struct variable *v; # ifdef KMK /* Check for kBuild-define- local variable accesses and handle these first. */ if (length > 3 && name[0] == '[' && set == &global_variable_set) { v = lookup_kbuild_object_variable_accessor(name, length); if (v != VAR_NOT_KBUILD_ACCESSOR) { RESOLVE_ALIAS_VARIABLE(v); MAKE_STATS_2 (v->references++); return v; } } # endif /* lookup the name in the string case, if it's not there it won't be in any of the sets either. Optimize lookups in the global set. */ cached_name = strcache2_lookup(&variable_strcache, name, length); if (!cached_name) return NULL; if (set == &global_variable_set) { v = strcache2_get_user_val (&variable_strcache, cached_name); assert (!v || v->name == cached_name); } else { var_key.name = cached_name; var_key.length = length; v = (struct variable *) hash_find_item_strcached ( (struct hash_table *) &set->table, &var_key); } # ifdef KMK RESOLVE_ALIAS_VARIABLE(v); # endif MAKE_STATS_2 (if (v) v->references++); return v; #endif /* CONFIG_WITH_STRCACHE2 */ } /* Initialize FILE's variable set list. If FILE already has a variable set list, the topmost variable set is left intact, but the the rest of the chain is replaced with FILE->parent's setlist. If FILE is a double-colon rule, then we will use the "root" double-colon target's variable set as the parent of FILE's variable set. If we're READING a makefile, don't do the pattern variable search now, since the pattern variable might not have been defined yet. */ void initialize_file_variables (struct file *file, int reading) { struct variable_set_list *l = file->variables; if (l == 0) { #ifndef CONFIG_WITH_ALLOC_CACHES l = (struct variable_set_list *) xmalloc (sizeof (struct variable_set_list)); l->set = xmalloc (sizeof (struct variable_set)); #else /* CONFIG_WITH_ALLOC_CACHES */ l = (struct variable_set_list *) alloccache_alloc (&variable_set_list_cache); l->set = (struct variable_set *) alloccache_alloc (&variable_set_cache); #endif /* CONFIG_WITH_ALLOC_CACHES */ #ifndef CONFIG_WITH_STRCACHE2 hash_init (&l->set->table, PERFILE_VARIABLE_BUCKETS, variable_hash_1, variable_hash_2, variable_hash_cmp); #else /* CONFIG_WITH_STRCACHE2 */ hash_init_strcached (&l->set->table, PERFILE_VARIABLE_BUCKETS, &variable_strcache, offsetof (struct variable, name)); #endif /* CONFIG_WITH_STRCACHE2 */ file->variables = l; } /* If this is a double-colon, then our "parent" is the "root" target for this double-colon rule. Since that rule has the same name, parent, etc. we can just use its variables as the "next" for ours. */ if (file->double_colon && file->double_colon != file) { initialize_file_variables (file->double_colon, reading); l->next = file->double_colon->variables; l->next_is_parent = 0; return; } if (file->parent == 0) l->next = &global_setlist; else { initialize_file_variables (file->parent, reading); l->next = file->parent->variables; } l->next_is_parent = 1; /* If we're not reading makefiles and we haven't looked yet, see if we can find pattern variables for this target. */ if (!reading && !file->pat_searched) { struct pattern_var *p; p = lookup_pattern_var (0, file->name); if (p != 0) { struct variable_set_list *global = current_variable_set_list; /* We found at least one. Set up a new variable set to accumulate all the pattern variables that match this target. */ file->pat_variables = create_new_variable_set (); current_variable_set_list = file->pat_variables; do { /* We found one, so insert it into the set. */ struct variable *v; if (p->variable.flavor == f_simple) { v = define_variable_loc ( p->variable.name, strlen (p->variable.name), p->variable.value, p->variable.origin, 0, &p->variable.fileinfo); v->flavor = f_simple; } else { #ifndef CONFIG_WITH_VALUE_LENGTH v = do_variable_definition ( &p->variable.fileinfo, p->variable.name, p->variable.value, p->variable.origin, p->variable.flavor, 1); #else v = do_variable_definition_2 ( &p->variable.fileinfo, p->variable.name, p->variable.value, p->variable.value_length, 0, 0, p->variable.origin, p->variable.flavor, 1); #endif } /* Also mark it as a per-target and copy export status. */ v->per_target = p->variable.per_target; v->export = p->variable.export; v->private_var = p->variable.private_var; } while ((p = lookup_pattern_var (p, file->name)) != 0); current_variable_set_list = global; } file->pat_searched = 1; } /* If we have a pattern variable match, set it up. */ if (file->pat_variables != 0) { file->pat_variables->next = l->next; file->pat_variables->next_is_parent = l->next_is_parent; l->next = file->pat_variables; l->next_is_parent = 0; } } /* Pop the top set off the current variable set list, and free all its storage. */ struct variable_set_list * create_new_variable_set (void) { register struct variable_set_list *setlist; register struct variable_set *set; #ifndef CONFIG_WITH_ALLOC_CACHES set = xmalloc (sizeof (struct variable_set)); #else set = (struct variable_set *) alloccache_alloc (&variable_set_cache); #endif #ifndef CONFIG_WITH_STRCACHE2 hash_init (&set->table, SMALL_SCOPE_VARIABLE_BUCKETS, variable_hash_1, variable_hash_2, variable_hash_cmp); #else /* CONFIG_WITH_STRCACHE2 */ hash_init_strcached (&set->table, SMALL_SCOPE_VARIABLE_BUCKETS, &variable_strcache, offsetof (struct variable, name)); #endif /* CONFIG_WITH_STRCACHE2 */ #ifndef CONFIG_WITH_ALLOC_CACHES setlist = (struct variable_set_list *) xmalloc (sizeof (struct variable_set_list)); #else setlist = (struct variable_set_list *) alloccache_alloc (&variable_set_list_cache); #endif setlist->set = set; setlist->next = current_variable_set_list; setlist->next_is_parent = 0; return setlist; } /* Create a new variable set and push it on the current setlist. If we're pushing a global scope (that is, the current scope is the global scope) then we need to "push" it the other way: file variable sets point directly to the global_setlist so we need to replace that with the new one. */ struct variable_set_list * push_new_variable_scope (void) { current_variable_set_list = create_new_variable_set (); if (current_variable_set_list->next == &global_setlist) { /* It was the global, so instead of new -> &global we want to replace &global with the new one and have &global -> new, with current still pointing to &global */ struct variable_set *set = current_variable_set_list->set; current_variable_set_list->set = global_setlist.set; global_setlist.set = set; current_variable_set_list->next = global_setlist.next; global_setlist.next = current_variable_set_list; current_variable_set_list = &global_setlist; } return (current_variable_set_list); } void pop_variable_scope (void) { struct variable_set_list *setlist; struct variable_set *set; /* Can't call this if there's no scope to pop! */ assert (current_variable_set_list->next != NULL); if (current_variable_set_list != &global_setlist) { /* We're not pointing to the global setlist, so pop this one. */ setlist = current_variable_set_list; set = setlist->set; current_variable_set_list = setlist->next; } else { /* This set is the one in the global_setlist, but there is another global set beyond that. We want to copy that set to global_setlist, then delete what used to be in global_setlist. */ setlist = global_setlist.next; set = global_setlist.set; global_setlist.set = setlist->set; global_setlist.next = setlist->next; global_setlist.next_is_parent = setlist->next_is_parent; } /* Free the one we no longer need. */ #ifndef CONFIG_WITH_ALLOC_CACHES free (setlist); hash_map (&set->table, free_variable_name_and_value); hash_free (&set->table, 1); free (set); #else alloccache_free (&variable_set_list_cache, setlist); hash_map (&set->table, free_variable_name_and_value); hash_free_cached (&set->table, 1, &variable_cache); alloccache_free (&variable_set_cache, set); #endif } /* Merge FROM_SET into TO_SET, freeing unused storage in FROM_SET. */ static void merge_variable_sets (struct variable_set *to_set, struct variable_set *from_set) { struct variable **from_var_slot = (struct variable **) from_set->table.ht_vec; struct variable **from_var_end = from_var_slot + from_set->table.ht_size; int inc = to_set == &global_variable_set ? 1 : 0; for ( ; from_var_slot < from_var_end; from_var_slot++) if (! HASH_VACANT (*from_var_slot)) { struct variable *from_var = *from_var_slot; struct variable **to_var_slot #ifndef CONFIG_WITH_STRCACHE2 = (struct variable **) hash_find_slot (&to_set->table, *from_var_slot); #else /* CONFIG_WITH_STRCACHE2 */ = (struct variable **) hash_find_slot_strcached (&to_set->table, *from_var_slot); #endif /* CONFIG_WITH_STRCACHE2 */ if (HASH_VACANT (*to_var_slot)) { hash_insert_at (&to_set->table, from_var, to_var_slot); variable_changenum += inc; } else { /* GKM FIXME: delete in from_set->table */ #ifdef KMK if (from_var->aliased) OS (fatal, NULL, ("Attempting to delete aliased variable '%s'"), from_var->name); if (from_var->alias) OS (fatal, NULL, ("Attempting to delete variable aliased '%s'"), from_var->name); #endif #ifdef CONFIG_WITH_COMPILER if (from_var->evalprog || from_var->expandprog) kmk_cc_variable_deleted (from_var); #endif #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE if (!from_var->rdonly_val) #endif free (from_var->value); free (from_var); } } } /* Merge SETLIST1 into SETLIST0, freeing unused storage in SETLIST1. */ void merge_variable_set_lists (struct variable_set_list **setlist0, struct variable_set_list *setlist1) { struct variable_set_list *to = *setlist0; struct variable_set_list *last0 = 0; /* If there's nothing to merge, stop now. */ if (!setlist1) return; /* This loop relies on the fact that all setlists terminate with the global setlist (before NULL). If that's not true, arguably we SHOULD die. */ if (to) while (setlist1 != &global_setlist && to != &global_setlist) { struct variable_set_list *from = setlist1; setlist1 = setlist1->next; merge_variable_sets (to->set, from->set); last0 = to; to = to->next; } if (setlist1 != &global_setlist) { if (last0 == 0) *setlist0 = setlist1; else last0->next = setlist1; } } #if defined(KMK) && !defined(WINDOWS32) /* Parses out the next number from the uname release level string. Fast forwards to the end of the string when encountering some non-conforming chars. */ static unsigned long parse_release_number (const char **ppsz) { unsigned long ul; char *psz = (char *)*ppsz; if (ISDIGIT (*psz)) { ul = strtoul (psz, &psz, 10); if (psz != NULL && *psz == '.') psz++; else psz = strchr (*ppsz, '\0'); *ppsz = psz; } else ul = 0; return ul; } #endif /* Define the automatic variables, and record the addresses of their structures so we can change their values quickly. */ void define_automatic_variables (void) { struct variable *v; #ifndef KMK char buf[200]; #else char buf[1024]; const char *val; struct variable *envvar1; struct variable *envvar2; # ifndef WINDOWS32 struct utsname uts; # endif unsigned long ulMajor = 0, ulMinor = 0, ulPatch = 0, ul4th = 0; #endif sprintf (buf, "%u", makelevel); define_variable_cname (MAKELEVEL_NAME, buf, o_env, 0); sprintf (buf, "%s%s%s", version_string, (remote_description == 0 || remote_description[0] == '\0') ? "" : "-", (remote_description == 0 || remote_description[0] == '\0') ? "" : remote_description); #ifndef KMK define_variable_cname ("MAKE_VERSION", buf, o_default, 0); define_variable_cname ("MAKE_HOST", make_host, o_default, 0); #else /* KMK */ /* Define KMK_VERSION to indicate kMk. */ define_variable_cname ("KMK_VERSION", buf, o_default, 0); /* Define KBUILD_VERSION* */ sprintf (buf, "%d", KBUILD_VERSION_MAJOR); define_variable_cname ("KBUILD_VERSION_MAJOR", buf, o_default, 0); sprintf (buf, "%d", KBUILD_VERSION_MINOR); define_variable_cname ("KBUILD_VERSION_MINOR", buf, o_default, 0); sprintf (buf, "%d", KBUILD_VERSION_PATCH); define_variable_cname ("KBUILD_VERSION_PATCH", buf, o_default, 0); sprintf (buf, "%d", KBUILD_SVN_REV); define_variable_cname ("KBUILD_KMK_REVISION", buf, o_default, 0); sprintf (buf, "%d.%d.%d-r%d", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, KBUILD_SVN_REV); define_variable_cname ("KBUILD_VERSION", buf, o_default, 0); /* The host defaults. The BUILD_* stuff will be replaced by KBUILD_* soon. */ envvar1 = lookup_variable (STRING_SIZE_TUPLE ("KBUILD_HOST")); envvar2 = lookup_variable (STRING_SIZE_TUPLE ("BUILD_PLATFORM")); val = envvar1 ? envvar1->value : envvar2 ? envvar2->value : KBUILD_HOST; if (envvar1 && envvar2 && strcmp (envvar1->value, envvar2->value)) OS (error, NULL, _("KBUILD_HOST and BUILD_PLATFORM differs, using KBUILD_HOST=%s."), val); if (!envvar1) define_variable_cname ("KBUILD_HOST", val, o_default, 0); if (!envvar2) define_variable_cname ("BUILD_PLATFORM", "$(KBUILD_HOST)", o_default, 1); envvar1 = lookup_variable (STRING_SIZE_TUPLE ("KBUILD_HOST_ARCH")); envvar2 = lookup_variable (STRING_SIZE_TUPLE ("BUILD_PLATFORM_ARCH")); val = envvar1 ? envvar1->value : envvar2 ? envvar2->value : KBUILD_HOST_ARCH; if (envvar1 && envvar2 && strcmp (envvar1->value, envvar2->value)) OS (error, NULL, _("KBUILD_HOST_ARCH and BUILD_PLATFORM_ARCH differs, using KBUILD_HOST_ARCH=%s."), val); if (!envvar1) define_variable_cname ("KBUILD_HOST_ARCH", val, o_default, 0); if (!envvar2) define_variable_cname ("BUILD_PLATFORM_ARCH", "$(KBUILD_HOST_ARCH)", o_default, 1); envvar1 = lookup_variable (STRING_SIZE_TUPLE ("KBUILD_HOST_CPU")); envvar2 = lookup_variable (STRING_SIZE_TUPLE ("BUILD_PLATFORM_CPU")); val = envvar1 ? envvar1->value : envvar2 ? envvar2->value : KBUILD_HOST_CPU; if (envvar1 && envvar2 && strcmp (envvar1->value, envvar2->value)) OS (error, NULL, _("KBUILD_HOST_CPU and BUILD_PLATFORM_CPU differs, using KBUILD_HOST_CPU=%s."), val); if (!envvar1) define_variable_cname ("KBUILD_HOST_CPU", val, o_default, 0); if (!envvar2) define_variable_cname ("BUILD_PLATFORM_CPU", "$(KBUILD_HOST_CPU)", o_default, 1); /* The host kernel version. */ # if defined(WINDOWS32) { OSVERSIONINFOEXW oix; NTSTATUS (WINAPI *pfnRtlGetVersion)(OSVERSIONINFOEXW *); *(FARPROC *)&pfnRtlGetVersion = GetProcAddress (GetModuleHandleW (L"NTDLL.DLL"), "RtlGetVersion"); /* GetVersionEx lies */ memset (&oix, '\0', sizeof (oix)); oix.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); if (!pfnRtlGetVersion || pfnRtlGetVersion (&oix) < 0) { memset (&oix, '\0', sizeof (oix)); oix.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); if (!GetVersionExW((LPOSVERSIONINFOW)&oix)) { memset (&oix, '\0', sizeof (oix)); oix.dwOSVersionInfoSize = sizeof (OSVERSIONINFOW); GetVersionExW ((LPOSVERSIONINFOW)&oix); } } if (oix.dwPlatformId == VER_PLATFORM_WIN32_NT) { ulMajor = oix.dwMajorVersion; ulMinor = oix.dwMinorVersion; ulPatch = oix.wServicePackMajor; ul4th = oix.wServicePackMinor; } else { ulMajor = oix.dwPlatformId == 1 ? 0 /*Win95/98/ME*/ : oix.dwPlatformId == 3 ? 1 /*WinCE*/ : 2; /*??*/ ulMinor = oix.dwMajorVersion; ulPatch = oix.dwMinorVersion; ul4th = oix.wServicePackMajor; } oix.dwBuildNumber &= 0x3fffffff; sprintf (buf, "%lu", oix.dwBuildNumber); define_variable_cname ("KBUILD_HOST_VERSION_BUILD", buf, o_default, 0); sprintf (buf, "%lu.%lu.%lu.%lu.%lu", ulMajor, ulMinor, ulPatch, ul4th, oix.dwBuildNumber); define_variable_cname ("KBUILD_HOST_VERSION", buf, o_default, 0); } # else memset (&uts, 0, sizeof(uts)); uname (&uts); val = uts.release; ulMajor = parse_release_number (&val); ulMinor = parse_release_number (&val); ulPatch = parse_release_number (&val); ul4th = parse_release_number (&val); define_variable_cname ("KBUILD_HOST_UNAME_SYSNAME", uts.sysname, o_default, 0); define_variable_cname ("KBUILD_HOST_UNAME_RELEASE", uts.release, o_default, 0); define_variable_cname ("KBUILD_HOST_UNAME_VERSION", uts.version, o_default, 0); define_variable_cname ("KBUILD_HOST_UNAME_MACHINE", uts.machine, o_default, 0); define_variable_cname ("KBUILD_HOST_UNAME_NODENAME", uts.nodename, o_default, 0); sprintf (buf, "%lu.%lu.%lu.%lu", ulMajor, ulMinor, ulPatch, ul4th); define_variable_cname ("KBUILD_HOST_VERSION", buf, o_default, 0); # endif sprintf (buf, "%lu", ulMajor); define_variable_cname ("KBUILD_HOST_VERSION_MAJOR", buf, o_default, 0); sprintf (buf, "%lu", ulMinor); define_variable_cname ("KBUILD_HOST_VERSION_MINOR", buf, o_default, 0); sprintf (buf, "%lu", ulPatch); define_variable_cname ("KBUILD_HOST_VERSION_PATCH", buf, o_default, 0); /* The kBuild locations. */ define_variable_cname ("KBUILD_PATH", get_kbuild_path (), o_default, 0); define_variable_cname ("KBUILD_BIN_PATH", get_kbuild_bin_path (), o_default, 0); define_variable_cname ("PATH_KBUILD", "$(KBUILD_PATH)", o_default, 1); define_variable_cname ("PATH_KBUILD_BIN", "$(KBUILD_BIN_PATH)", o_default, 1); /* Define KMK_FEATURES to indicate various working KMK features. */ # if defined (CONFIG_WITH_RSORT) \ && defined (CONFIG_WITH_ABSPATHEX) \ && defined (CONFIG_WITH_TOUPPER_TOLOWER) \ && defined (CONFIG_WITH_DEFINED) \ && defined (CONFIG_WITH_VALUE_LENGTH) \ && defined (CONFIG_WITH_COMPARE) \ && defined (CONFIG_WITH_STACK) \ && defined (CONFIG_WITH_MATH) \ && defined (CONFIG_WITH_XARGS) \ && defined (CONFIG_WITH_EXPLICIT_MULTITARGET) \ && defined (CONFIG_WITH_DOT_MUST_MAKE) \ && defined (CONFIG_WITH_PREPEND_ASSIGNMENT) \ && defined (CONFIG_WITH_SET_CONDITIONALS) \ && defined (CONFIG_WITH_DATE) \ && defined (CONFIG_WITH_FILE_SIZE) \ && defined (CONFIG_WITH_WHERE_FUNCTION) \ && defined (CONFIG_WITH_WHICH) \ && defined (CONFIG_WITH_EVALPLUS) \ && (defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS)) \ && defined (CONFIG_WITH_COMMANDS_FUNC) \ && defined (CONFIG_WITH_PRINTF) \ && defined (CONFIG_WITH_LOOP_FUNCTIONS) \ && defined (CONFIG_WITH_ROOT_FUNC) \ && defined (CONFIG_WITH_STRING_FUNCTIONS) \ && defined (CONFIG_WITH_DEFINED_FUNCTIONS) \ && defined (KMK_HELPERS) define_variable_cname ("KMK_FEATURES", "append-dash-n abspath includedep-queue install-hard-linking umask quote versort" " kBuild-define" " rsort" " abspathex" " toupper tolower" " defined" " comp-vars comp-cmds comp-cmds-ex" " stack" " math-int" " xargs" " explicit-multitarget" " dot-must-make" " prepend-assignment" " set-conditionals intersects" " date" " file-size" " expr if-expr select" " where" " which" " evalctx evalval evalvalctx evalcall evalcall2 eval-opt-var" " make-stats" " commands" " printf" " for while" " root" " length insert pos lastpos substr translate" " kb-src-tool kb-obj-base kb-obj-suff kb-src-prop kb-src-one kb-exp-tmpl" " firstdefined lastdefined" , o_default, 0); # else /* MSC can't deal with strings mixed with #if/#endif, thus the slow way. */ # error "All features should be enabled by default!" strcpy (buf, "append-dash-n abspath includedep-queue install-hard-linking umask quote versort" " kBuild-define"); # if defined (CONFIG_WITH_RSORT) strcat (buf, " rsort"); # endif # if defined (CONFIG_WITH_ABSPATHEX) strcat (buf, " abspathex"); # endif # if defined (CONFIG_WITH_TOUPPER_TOLOWER) strcat (buf, " toupper tolower"); # endif # if defined (CONFIG_WITH_DEFINED) strcat (buf, " defined"); # endif # if defined (CONFIG_WITH_VALUE_LENGTH) && defined(CONFIG_WITH_COMPARE) strcat (buf, " comp-vars comp-cmds comp-cmds-ex"); # endif # if defined (CONFIG_WITH_STACK) strcat (buf, " stack"); # endif # if defined (CONFIG_WITH_MATH) strcat (buf, " math-int"); # endif # if defined (CONFIG_WITH_XARGS) strcat (buf, " xargs"); # endif # if defined (CONFIG_WITH_EXPLICIT_MULTITARGET) strcat (buf, " explicit-multitarget"); # endif # if defined (CONFIG_WITH_DOT_MUST_MAKE) strcat (buf, " dot-must-make"); # endif # if defined (CONFIG_WITH_PREPEND_ASSIGNMENT) strcat (buf, " prepend-assignment"); # endif # if defined (CONFIG_WITH_SET_CONDITIONALS) strcat (buf, " set-conditionals intersects"); # endif # if defined (CONFIG_WITH_DATE) strcat (buf, " date"); # endif # if defined (CONFIG_WITH_FILE_SIZE) strcat (buf, " file-size"); # endif # if defined (CONFIG_WITH_IF_CONDITIONALS) strcat (buf, " expr if-expr select"); # endif # if defined (CONFIG_WITH_WHERE_FUNCTION) strcat (buf, " where"); # endif # if defined (CONFIG_WITH_WHICH) strcat (buf, " which"); # endif # if defined (CONFIG_WITH_EVALPLUS) strcat (buf, " evalctx evalval evalvalctx evalcall evalcall2 eval-opt-var"); # endif # if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS) strcat (buf, " make-stats"); # endif # if defined (CONFIG_WITH_COMMANDS_FUNC) strcat (buf, " commands"); # endif # if defined (CONFIG_WITH_PRINTF) strcat (buf, " printf"); # endif # if defined (CONFIG_WITH_LOOP_FUNCTIONS) strcat (buf, " for while"); # endif # if defined (CONFIG_WITH_ROOT_FUNC) strcat (buf, " root"); # endif # if defined (CONFIG_WITH_STRING_FUNCTIONS) strcat (buf, " length insert pos lastpos substr translate"); # endif # if defined (CONFIG_WITH_DEFINED_FUNCTIONS) strcat (buf, " firstdefined lastdefined"); # endif # if defined (KMK_HELPERS) strcat (buf, " kb-src-tool kb-obj-base kb-obj-suff kb-src-prop kb-src-one kb-exp-tmpl"); # endif define_variable_cname ("KMK_FEATURES", buf, o_default, 0); # endif #endif /* KMK */ #ifdef CONFIG_WITH_KMK_BUILTIN /* The supported kMk Builtin commands. */ define_variable_cname ("KMK_BUILTIN", "append cat chmod cp cmp echo expr install kDepIDB ln md5sum mkdir mv printf rm rmdir sleep test", o_default, 0); #endif #ifdef __MSDOS__ /* Allow to specify a special shell just for Make, and use $COMSPEC as the default $SHELL when appropriate. */ { static char shell_str[] = "SHELL"; const int shlen = sizeof (shell_str) - 1; struct variable *mshp = lookup_variable ("MAKESHELL", 9); struct variable *comp = lookup_variable ("COMSPEC", 7); /* $(MAKESHELL) overrides $(SHELL) even if -e is in effect. */ if (mshp) (void) define_variable (shell_str, shlen, mshp->value, o_env_override, 0); else if (comp) { /* $(COMSPEC) shouldn't override $(SHELL). */ struct variable *shp = lookup_variable (shell_str, shlen); if (!shp) (void) define_variable (shell_str, shlen, comp->value, o_env, 0); } } #elif defined(__EMX__) { static char shell_str[] = "SHELL"; const int shlen = sizeof (shell_str) - 1; struct variable *shell = lookup_variable (shell_str, shlen); struct variable *replace = lookup_variable ("MAKESHELL", 9); /* if $MAKESHELL is defined in the environment assume o_env_override */ if (replace && *replace->value && replace->origin == o_env) replace->origin = o_env_override; /* if $MAKESHELL is not defined use $SHELL but only if the variable did not come from the environment */ if (!replace || !*replace->value) if (shell && *shell->value && (shell->origin == o_env || shell->origin == o_env_override)) { /* overwrite whatever we got from the environment */ free (shell->value); shell->value = xstrdup (default_shell); shell->origin = o_default; } /* Some people do not like cmd to be used as the default if $SHELL is not defined in the Makefile. With -DNO_CMD_DEFAULT you can turn off this behaviour */ # ifndef NO_CMD_DEFAULT /* otherwise use $COMSPEC */ if (!replace || !*replace->value) replace = lookup_variable ("COMSPEC", 7); /* otherwise use $OS2_SHELL */ if (!replace || !*replace->value) replace = lookup_variable ("OS2_SHELL", 9); # else # warning NO_CMD_DEFAULT: GNU make will not use CMD.EXE as default shell # endif if (replace && *replace->value) /* overwrite $SHELL */ (void) define_variable (shell_str, shlen, replace->value, replace->origin, 0); else /* provide a definition if there is none */ (void) define_variable (shell_str, shlen, default_shell, o_default, 0); } #endif /* This won't override any definition, but it will provide one if there isn't one there. */ v = define_variable_cname ("SHELL", default_shell, o_default, 0); #ifdef __MSDOS__ v->export = v_export; /* Export always SHELL. */ #endif /* On MSDOS we do use SHELL from environment, since it isn't a standard environment variable on MSDOS, so whoever sets it, does that on purpose. On OS/2 we do not use SHELL from environment but we have already handled that problem above. */ #if !defined(__MSDOS__) && !defined(__EMX__) /* Don't let SHELL come from the environment. */ if (*v->value == '\0' || v->origin == o_env || v->origin == o_env_override) { # ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE if (v->rdonly_val) v->rdonly_val = 0; else # endif free (v->value); v->origin = o_file; v->value = xstrdup (default_shell); # ifdef CONFIG_WITH_VALUE_LENGTH v->value_length = strlen (v->value); v->value_alloc_len = v->value_length + 1; # endif } #endif /* Make sure MAKEFILES gets exported if it is set. */ v = define_variable_cname ("MAKEFILES", "", o_default, 0); v->export = v_ifset; /* Define the magic D and F variables in terms of the automatic variables they are variations of. */ #if defined(__MSDOS__) || defined(WINDOWS32) /* For consistency, remove the trailing backslash as well as slash. */ define_variable_cname ("@D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $@)))", o_automatic, 1); define_variable_cname ("%D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $%)))", o_automatic, 1); define_variable_cname ("*D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $*)))", o_automatic, 1); define_variable_cname ("export) { case v_default: if (v->origin == o_default || v->origin == o_automatic) /* Only export default variables by explicit request. */ continue; /* The variable doesn't have a name that can be exported. */ if (! v->exportable) continue; if (! export_all_variables && v->origin != o_command && v->origin != o_env && v->origin != o_env_override) continue; break; case v_export: break; case v_noexport: { /* If this is the SHELL variable and it's not exported, then add the value from our original environment, if the original environment defined a value for SHELL. */ extern struct variable shell_var; if (streq (v->name, "SHELL") && shell_var.value) { v = &shell_var; break; } continue; } case v_ifset: if (v->origin == o_default) continue; break; } assert (strcache2_is_cached (&variable_strcache, v->name)); new_slot = (struct variable **) hash_find_slot_strcached (&global_variable_set_exports, v); if (HASH_VACANT (*new_slot)) hash_insert_at (&global_variable_set_exports, v, new_slot); } /* done */ global_variable_set_exports_generation = global_variable_generation; } #endif /* Create a new environment for FILE's commands. If FILE is nil, this is for the 'shell' function. The child's MAKELEVEL variable is incremented. */ char ** target_environment (struct file *file) { struct variable_set_list *set_list; register struct variable_set_list *s; struct hash_table table; struct variable **v_slot; struct variable **v_end; struct variable makelevel_key; char **result_0; char **result; #ifdef CONFIG_WITH_STRCACHE2 const char *cached_name; #endif #ifdef KMK if (global_variable_set_exports_generation != global_variable_generation) update_global_variable_set_exports(); #endif if (file == 0) set_list = current_variable_set_list; else set_list = file->variables; #ifndef CONFIG_WITH_STRCACHE2 hash_init (&table, ENVIRONMENT_VARIABLE_BUCKETS, variable_hash_1, variable_hash_2, variable_hash_cmp); #else /* CONFIG_WITH_STRCACHE2 */ hash_init_strcached (&table, ENVIRONMENT_VARIABLE_BUCKETS, &variable_strcache, offsetof (struct variable, name)); #endif /* CONFIG_WITH_STRCACHE2 */ /* Run through all the variable sets in the list, accumulating variables in TABLE. */ for (s = set_list; s != 0; s = s->next) { struct variable_set *set = s->set; #ifdef KMK if (set == &global_variable_set) { assert(s->next == NULL); break; } #endif v_slot = (struct variable **) set->table.ht_vec; v_end = v_slot + set->table.ht_size; for ( ; v_slot < v_end; v_slot++) if (! HASH_VACANT (*v_slot)) { struct variable **new_slot; struct variable *v = *v_slot; /* If this is a per-target variable and it hasn't been touched already then look up the global version and take its export value. */ if (v->per_target && v->export == v_default) { struct variable *gv; #ifndef CONFIG_WITH_VALUE_LENGTH gv = lookup_variable_in_set (v->name, strlen (v->name), &global_variable_set); #else assert ((int)strlen(v->name) == v->length); gv = lookup_variable_in_set (v->name, v->length, &global_variable_set); #endif if (gv) v->export = gv->export; } switch (v->export) { case v_default: if (v->origin == o_default || v->origin == o_automatic) /* Only export default variables by explicit request. */ continue; /* The variable doesn't have a name that can be exported. */ if (! v->exportable) continue; if (! export_all_variables && v->origin != o_command && v->origin != o_env && v->origin != o_env_override) continue; break; case v_export: break; case v_noexport: { /* If this is the SHELL variable and it's not exported, then add the value from our original environment, if the original environment defined a value for SHELL. */ if (streq (v->name, "SHELL") && shell_var.value) { v = &shell_var; break; } continue; } case v_ifset: if (v->origin == o_default) continue; break; } #ifndef CONFIG_WITH_STRCACHE2 new_slot = (struct variable **) hash_find_slot (&table, v); #else /* CONFIG_WITH_STRCACHE2 */ assert (strcache2_is_cached (&variable_strcache, v->name)); new_slot = (struct variable **) hash_find_slot_strcached (&table, v); #endif /* CONFIG_WITH_STRCACHE2 */ if (HASH_VACANT (*new_slot)) hash_insert_at (&table, v, new_slot); } } #ifdef KMK /* Add the global exports to table. */ v_slot = (struct variable **) global_variable_set_exports.ht_vec; v_end = v_slot + global_variable_set_exports.ht_size; for ( ; v_slot < v_end; v_slot++) if (! HASH_VACANT (*v_slot)) { struct variable **new_slot; struct variable *v = *v_slot; assert (strcache2_is_cached (&variable_strcache, v->name)); new_slot = (struct variable **) hash_find_slot_strcached (&table, v); if (HASH_VACANT (*new_slot)) hash_insert_at (&table, v, new_slot); } #endif #ifndef CONFIG_WITH_STRCACHE2 makelevel_key.name = (char *)MAKELEVEL_NAME; makelevel_key.length = MAKELEVEL_LENGTH; hash_delete (&table, &makelevel_key); #else /* CONFIG_WITH_STRCACHE2 */ /* lookup the name in the string case, if it's not there it won't be in any of the sets either. */ cached_name = strcache2_lookup (&variable_strcache, MAKELEVEL_NAME, MAKELEVEL_LENGTH); if (cached_name) { makelevel_key.name = cached_name; makelevel_key.length = MAKELEVEL_LENGTH; hash_delete_strcached (&table, &makelevel_key); } #endif /* CONFIG_WITH_STRCACHE2 */ result = result_0 = xmalloc ((table.ht_fill + 2) * sizeof (char *)); v_slot = (struct variable **) table.ht_vec; v_end = v_slot + table.ht_size; for ( ; v_slot < v_end; v_slot++) if (! HASH_VACANT (*v_slot)) { struct variable *v = *v_slot; /* If V is recursively expanded and didn't come from the environment, expand its value. If it came from the environment, it should go back into the environment unchanged. */ if (v->recursive && v->origin != o_env && v->origin != o_env_override) { #ifndef CONFIG_WITH_VALUE_LENGTH char *value = recursively_expand_for_file (v, file); #else char *value = recursively_expand_for_file (v, file, NULL); #endif #ifdef WINDOWS32 if (strcmp (v->name, "Path") == 0 || strcmp (v->name, "PATH") == 0) convert_Path_to_windows32 (value, ';'); #endif *result++ = xstrdup (concat (3, v->name, "=", value)); free (value); } else { #ifdef WINDOWS32 if (strcmp (v->name, "Path") == 0 || strcmp (v->name, "PATH") == 0) convert_Path_to_windows32 (v->value, ';'); #endif *result++ = xstrdup (concat (3, v->name, "=", v->value)); } } *result = xmalloc (100); sprintf (*result, "%s=%u", MAKELEVEL_NAME, makelevel + 1); *++result = 0; hash_free (&table, 0); return result_0; } #ifdef CONFIG_WITH_VALUE_LENGTH /* Worker function for do_variable_definition_append() and append_expanded_string_to_variable(). The APPEND argument indicates whether it's an append or prepend operation. */ void append_string_to_variable (struct variable *v, const char *value, unsigned int value_len, int append) { /* The previous definition of the variable was recursive. The new value is the unexpanded old and new values. */ unsigned int new_value_len = value_len + (v->value_length != 0 ? 1 + v->value_length : 0); int done_1st_prepend_copy = 0; #ifdef KMK assert (!v->alias); #endif /* Drop empty strings. Use $(NO_SUCH_VARIABLE) if a space is wanted. */ if (!value_len) return; /* adjust the size. */ if (v->value_alloc_len <= new_value_len + 1) { if (v->value_alloc_len < 256) v->value_alloc_len = 256; else v->value_alloc_len *= 2; if (v->value_alloc_len < new_value_len + 1) v->value_alloc_len = VAR_ALIGN_VALUE_ALLOC (new_value_len + 1 + value_len /*future*/ ); # ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE if ((append || !v->value_length) && !v->rdonly_val) # else if (append || !v->value_length) # endif v->value = xrealloc (v->value, v->value_alloc_len); else { /* avoid the extra memcpy the xrealloc may have to do */ char *new_buf = xmalloc (v->value_alloc_len); memcpy (&new_buf[value_len + 1], v->value, v->value_length + 1); done_1st_prepend_copy = 1; # ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE if (v->rdonly_val) v->rdonly_val = 0; else # endif free (v->value); v->value = new_buf; } MAKE_STATS_2(v->reallocs++); } /* insert the new bits */ if (v->value_length != 0) { if (append) { v->value[v->value_length] = ' '; memcpy (&v->value[v->value_length + 1], value, value_len + 1); } else { if (!done_1st_prepend_copy) memmove (&v->value[value_len + 1], v->value, v->value_length + 1); v->value[value_len] = ' '; memcpy (v->value, value, value_len); } } else memcpy (v->value, value, value_len + 1); v->value_length = new_value_len; VARIABLE_CHANGED (v); } struct variable * do_variable_definition_append (const floc *flocp, struct variable *v, const char *value, unsigned int value_len, int simple_value, enum variable_origin origin, int append) { if (env_overrides && origin == o_env) origin = o_env_override; if (env_overrides && v->origin == o_env) /* V came from in the environment. Since it was defined before the switches were parsed, it wasn't affected by -e. */ v->origin = o_env_override; /* A variable of this name is already defined. If the old definition is from a stronger source than this one, don't redefine it. */ if ((int) origin < (int) v->origin) return v; v->origin = origin; /* location */ if (flocp != 0) v->fileinfo = *flocp; /* The juicy bits, append the specified value to the variable This is a heavily exercised code path in kBuild. */ if (value_len == ~0U) value_len = strlen (value); if (v->recursive || simple_value) append_string_to_variable (v, value, value_len, append); else /* The previous definition of the variable was simple. The new value comes from the old value, which was expanded when it was set; and from the expanded new value. */ append_expanded_string_to_variable (v, value, value_len, append); /* update the variable */ return v; } #endif /* CONFIG_WITH_VALUE_LENGTH */ static struct variable * set_special_var (struct variable *var) { if (streq (var->name, RECIPEPREFIX_NAME)) { /* The user is resetting the command introduction prefix. This has to happen immediately, so that subsequent rules are interpreted properly. */ cmd_prefix = var->value[0]=='\0' ? RECIPEPREFIX_DEFAULT : var->value[0]; } return var; } /* Given a string, shell-execute it and return a malloc'ed string of the * result. This removes only ONE newline (if any) at the end, for maximum * compatibility with the *BSD makes. If it fails, returns NULL. */ static char * shell_result (const char *p) { char *buf; unsigned int len; char *args[2]; char *result; install_variable_buffer (&buf, &len); args[0] = (char *) p; args[1] = NULL; variable_buffer_output (func_shell_base (variable_buffer, args, 0), "\0", 1); result = strdup (variable_buffer); restore_variable_buffer (buf, len); return result; } /* Given a variable, a value, and a flavor, define the variable. See the try_variable_definition() function for details on the parameters. */ struct variable * #ifndef CONFIG_WITH_VALUE_LENGTH do_variable_definition (const floc *flocp, const char *varname, const char *value, enum variable_origin origin, enum variable_flavor flavor, int target_var) #else /* CONFIG_WITH_VALUE_LENGTH */ do_variable_definition_2 (const floc *flocp, const char *varname, const char *value, unsigned int value_len, int simple_value, char *free_value, enum variable_origin origin, enum variable_flavor flavor, int target_var) #endif /* CONFIG_WITH_VALUE_LENGTH */ { const char *p; char *alloc_value = NULL; struct variable *v; int append = 0; int conditional = 0; const size_t varname_len = strlen (varname); /* bird */ #ifdef CONFIG_WITH_VALUE_LENGTH if (value_len == ~0U) value_len = strlen (value); else assert (value_len == strlen (value)); #endif /* Calculate the variable's new value in VALUE. */ switch (flavor) { default: case f_bogus: /* Should not be possible. */ abort (); case f_simple: /* A simple variable definition "var := value". Expand the value. We have to allocate memory since otherwise it'll clobber the variable buffer, and we may still need that if we're looking at a target-specific variable. */ #ifndef CONFIG_WITH_VALUE_LENGTH p = alloc_value = allocated_variable_expand (value); #else /* CONFIG_WITH_VALUE_LENGTH */ if (!simple_value) p = alloc_value = allocated_variable_expand_2 (value, value_len, &value_len); else { if (value_len == ~0U) value_len = strlen (value); if (!free_value) p = alloc_value = xstrndup (value, value_len); else { assert (value == free_value); p = alloc_value = free_value; free_value = 0; } } #endif /* CONFIG_WITH_VALUE_LENGTH */ break; case f_shell: { /* A shell definition "var != value". Expand value, pass it to the shell, and store the result in recursively-expanded var. */ char *q = allocated_variable_expand (value); p = alloc_value = shell_result (q); free (q); flavor = f_recursive; break; } case f_conditional: /* A conditional variable definition "var ?= value". The value is set IFF the variable is not defined yet. */ v = lookup_variable (varname, varname_len); if (v) #ifndef CONFIG_WITH_VALUE_LENGTH return v->special ? set_special_var (v) : v; #else /* CONFIG_WITH_VALUE_LENGTH */ { if (free_value) free (free_value); return v->special ? set_special_var (v) : v; } #endif /* CONFIG_WITH_VALUE_LENGTH */ conditional = 1; flavor = f_recursive; /* FALLTHROUGH */ case f_recursive: /* A recursive variable definition "var = value". The value is used verbatim. */ p = value; break; #ifdef CONFIG_WITH_PREPEND_ASSIGNMENT case f_append: case f_prepend: { const enum variable_flavor org_flavor = flavor; #else case f_append: { #endif /* If we have += but we're in a target variable context, we want to append only with other variables in the context of this target. */ if (target_var) { append = 1; v = lookup_variable_in_set (varname, varname_len, current_variable_set_list->set); /* Don't append from the global set if a previous non-appending target-specific variable definition exists. */ if (v && !v->append) append = 0; } #ifdef KMK else if ( g_pTopKbEvalData || ( varname_len > 3 && varname[0] == '[' && is_kbuild_object_variable_accessor (varname, varname_len)) ) { v = kbuild_object_variable_pre_append (varname, varname_len, value, value_len, simple_value, origin, org_flavor == f_append, flocp); if (free_value) free (free_value); return v; } #endif #ifdef CONFIG_WITH_LOCAL_VARIABLES /* If 'local', restrict it to the current variable context. */ else if (origin == o_local) v = lookup_variable_in_set (varname, varname_len, current_variable_set_list->set); #endif else v = lookup_variable (varname, varname_len); if (v == 0) { /* There was no old value. This becomes a normal recursive definition. */ p = value; flavor = f_recursive; } else { #ifdef CONFIG_WITH_VALUE_LENGTH v->append = append; v = do_variable_definition_append (flocp, v, value, value_len, simple_value, origin, # ifdef CONFIG_WITH_PREPEND_ASSIGNMENT org_flavor == f_append); # else 1); # endif if (free_value) free (free_value); return v; #else /* !CONFIG_WITH_VALUE_LENGTH */ /* Paste the old and new values together in VALUE. */ unsigned int oldlen, vallen; const char *val; char *tp = NULL; val = value; if (v->recursive) /* The previous definition of the variable was recursive. The new value is the unexpanded old and new values. */ flavor = f_recursive; else /* The previous definition of the variable was simple. The new value comes from the old value, which was expanded when it was set; and from the expanded new value. Allocate memory for the expansion as we may still need the rest of the buffer if we're looking at a target-specific variable. */ val = tp = allocated_variable_expand (val); oldlen = strlen (v->value); vallen = strlen (val); p = alloc_value = xmalloc (oldlen + 1 + vallen + 1); # ifdef CONFIG_WITH_PREPEND_ASSIGNMENT if (org_flavor == f_prepend) { memcpy (alloc_value, val, vallen); alloc_value[oldlen] = ' '; memcpy (&alloc_value[oldlen + 1], v->value, oldlen + 1); } else # endif /* CONFIG_WITH_PREPEND_ASSIGNMENT */ { memcpy (alloc_value, v->value, oldlen); alloc_value[oldlen] = ' '; memcpy (&alloc_value[oldlen + 1], val, vallen + 1); } free (tp); #endif /* !CONFIG_WITH_VALUE_LENGTH */ } } } #ifdef __MSDOS__ /* Many Unix Makefiles include a line saying "SHELL=/bin/sh", but non-Unix systems don't conform to this default configuration (in fact, most of them don't even have '/bin'). On the other hand, $SHELL in the environment, if set, points to the real pathname of the shell. Therefore, we generally won't let lines like "SHELL=/bin/sh" from the Makefile override $SHELL from the environment. But first, we look for the basename of the shell in the directory where SHELL= points, and along the $PATH; if it is found in any of these places, we define $SHELL to be the actual pathname of the shell. Thus, if you have bash.exe installed as d:/unix/bash.exe, and d:/unix is on your $PATH, then SHELL=/usr/local/bin/bash will have the effect of defining SHELL to be "d:/unix/bash.exe". */ if ((origin == o_file || origin == o_override) && strcmp (varname, "SHELL") == 0) { PATH_VAR (shellpath); extern char * __dosexec_find_on_path (const char *, char *[], char *); /* See if we can find "/bin/sh.exe", "/bin/sh.com", etc. */ if (__dosexec_find_on_path (p, NULL, shellpath)) { char *tp; for (tp = shellpath; *tp; tp++) if (*tp == '\\') *tp = '/'; v = define_variable_loc (varname, varname_len, shellpath, origin, flavor == f_recursive, flocp); } else { const char *shellbase, *bslash; struct variable *pathv = lookup_variable ("PATH", 4); char *path_string; char *fake_env[2]; size_t pathlen = 0; shellbase = strrchr (p, '/'); bslash = strrchr (p, '\\'); if (!shellbase || bslash > shellbase) shellbase = bslash; if (!shellbase && p[1] == ':') shellbase = p + 1; if (shellbase) shellbase++; else shellbase = p; /* Search for the basename of the shell (with standard executable extensions) along the $PATH. */ if (pathv) pathlen = strlen (pathv->value); path_string = xmalloc (5 + pathlen + 2 + 1); /* On MSDOS, current directory is considered as part of $PATH. */ sprintf (path_string, "PATH=.;%s", pathv ? pathv->value : ""); fake_env[0] = path_string; fake_env[1] = 0; if (__dosexec_find_on_path (shellbase, fake_env, shellpath)) { char *tp; for (tp = shellpath; *tp; tp++) if (*tp == '\\') *tp = '/'; v = define_variable_loc (varname, varname_len, shellpath, origin, flavor == f_recursive, flocp); } else v = lookup_variable (varname, varname_len); free (path_string); } } else #endif /* __MSDOS__ */ #ifdef WINDOWS32 if ( varname_len == sizeof("SHELL") - 1 /* bird */ && (origin == o_file || origin == o_override || origin == o_command) && streq (varname, "SHELL")) { extern const char *default_shell; /* Call shell locator function. If it returns TRUE, then set no_default_sh_exe to indicate sh was found and set new value for SHELL variable. */ if (find_and_set_default_shell (p)) { v = define_variable_in_set (varname, varname_len, default_shell, # ifdef CONFIG_WITH_VALUE_LENGTH ~0U, 1 /* duplicate_value */, # endif origin, flavor == f_recursive, (target_var ? current_variable_set_list->set : NULL), flocp); no_default_sh_exe = 0; } else { char *tp = alloc_value; alloc_value = allocated_variable_expand (p); if (find_and_set_default_shell (alloc_value)) { v = define_variable_in_set (varname, varname_len, p, #ifdef CONFIG_WITH_VALUE_LENGTH ~0U, 1 /* duplicate_value */, #endif origin, flavor == f_recursive, (target_var ? current_variable_set_list->set : NULL), flocp); no_default_sh_exe = 0; } else v = lookup_variable (varname, varname_len); free (tp); } } else #endif /* If we are defining variables inside an $(eval ...), we might have a different variable context pushed, not the global context (maybe we're inside a $(call ...) or something. Since this function is only ever invoked in places where we want to define globally visible variables, make sure we define this variable in the global set. */ v = define_variable_in_set (varname, varname_len, p, #ifdef CONFIG_WITH_VALUE_LENGTH value_len, !alloc_value, #endif origin, flavor == f_recursive, #ifdef CONFIG_WITH_LOCAL_VARIABLES (target_var || origin == o_local #else (target_var #endif ? current_variable_set_list->set : NULL), flocp); v->append = append; v->conditional = conditional; #ifndef CONFIG_WITH_VALUE_LENGTH free (alloc_value); #else if (free_value) free (free_value); #endif return v->special ? set_special_var (v) : v; } /* Parse P (a null-terminated string) as a variable definition. If it is not a variable definition, return NULL and the contents of *VAR are undefined, except NAME is set to the first non-space character or NIL. If it is a variable definition, return a pointer to the char after the assignment token and set the following fields (only) of *VAR: name : name of the variable (ALWAYS SET) (NOT NUL-TERMINATED!) length : length of the variable name value : value of the variable (nul-terminated) flavor : flavor of the variable Other values in *VAR are unchanged. */ char * parse_variable_definition (const char *p, struct variable *var) { int wspace = 0; const char *e = NULL; /** @todo merge 4.2.1: parse_variable_definition does more now */ NEXT_TOKEN (p); var->name = (char *)p; var->length = 0; while (1) { int c = *p++; /* If we find a comment or EOS, it's not a variable definition. */ if (STOP_SET (c, MAP_COMMENT|MAP_NUL)) return NULL; if (c == '$') { /* This begins a variable expansion reference. Make sure we don't treat chars inside the reference as assignment tokens. */ char closeparen; unsigned int count; c = *p++; if (c == '(') closeparen = ')'; else if (c == '{') closeparen = '}'; else if (c == '\0') return NULL; else /* '$$' or '$X'. Either way, nothing special to do here. */ continue; /* P now points past the opening paren or brace. Count parens or braces until it is matched. */ for (count = 1; *p != '\0'; ++p) { if (*p == closeparen && --count == 0) { ++p; break; } if (*p == c) ++count; } continue; } /* If we find whitespace skip it, and remember we found it. */ if (ISBLANK (c)) { wspace = 1; e = p - 1; NEXT_TOKEN (p); c = *p; if (c == '\0') return NULL; ++p; } if (c == '=') { var->flavor = f_recursive; if (! e) e = p - 1; break; } /* Match assignment variants (:=, +=, ?=, !=) */ if (*p == '=') { switch (c) { case ':': var->flavor = f_simple; break; case '+': var->flavor = f_append; break; #ifdef CONFIG_WITH_PREPEND_ASSIGNMENT case '<': var->flavor = f_prepend; break; #endif case '?': var->flavor = f_conditional; break; case '!': var->flavor = f_shell; break; default: /* If we skipped whitespace, non-assignments means no var. */ if (wspace) return NULL; /* Might be assignment, or might be $= or #=. Check. */ continue; } if (! e) e = p - 1; ++p; break; } /* Check for POSIX ::= syntax */ if (c == ':') { /* A colon other than :=/::= is not a variable defn. */ if (*p != ':' || p[1] != '=') return NULL; /* POSIX allows ::= to be the same as GNU make's := */ var->flavor = f_simple; if (! e) e = p - 1; p += 2; break; } /* If we skipped whitespace, non-assignments means no var. */ if (wspace) return NULL; } var->length = e - var->name; var->value = next_token (p); #ifdef CONFIG_WITH_VALUE_LENGTH var->value_alloc_len = ~(unsigned int)0; var->value_length = -1; # ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE var->rdonly_val = 0; # endif #endif return (char *)p; } /* Try to interpret LINE (a null-terminated string) as a variable definition. If LINE was recognized as a variable definition, a pointer to its 'struct variable' is returned. If LINE is not a variable definition, NULL is returned. */ struct variable * assign_variable_definition (struct variable *v, const char *line IF_WITH_VALUE_LENGTH_PARAM(char *eos)) { #ifndef CONFIG_WITH_VALUE_LENGTH char *name; #endif if (!parse_variable_definition (line, v)) return NULL; #ifdef CONFIG_WITH_VALUE_LENGTH if (eos) { v->value_length = eos - v->value; assert (strchr (v->value, '\0') == eos); } #endif /* Expand the name, so "$(foo)bar = baz" works. */ #ifndef CONFIG_WITH_VALUE_LENGTH name = alloca (v->length + 1); memcpy (name, v->name, v->length); name[v->length] = '\0'; v->name = allocated_variable_expand (name); #else /* CONFIG_WITH_VALUE_LENGTH */ v->name = allocated_variable_expand_2 (v->name, v->length, NULL); #endif /* CONFIG_WITH_VALUE_LENGTH */ if (v->name[0] == '\0') O (fatal, &v->fileinfo, _("empty variable name")); return v; } /* Try to interpret LINE (a null-terminated string) as a variable definition. ORIGIN may be o_file, o_override, o_env, o_env_override, o_local, or o_command specifying that the variable definition comes from a makefile, an override directive, the environment with or without the -e switch, or the command line. See the comments for assign_variable_definition(). If LINE was recognized as a variable definition, a pointer to its 'struct variable' is returned. If LINE is not a variable definition, NULL is returned. */ struct variable * try_variable_definition (const floc *flocp, const char *line IF_WITH_VALUE_LENGTH_PARAM(char *eos), enum variable_origin origin, int target_var) { struct variable v; struct variable *vp; if (flocp != 0) v.fileinfo = *flocp; else v.fileinfo.filenm = 0; #ifndef CONFIG_WITH_VALUE_LENGTH if (!assign_variable_definition (&v, line)) return 0; vp = do_variable_definition (flocp, v.name, v.value, origin, v.flavor, target_var); #else if (!assign_variable_definition (&v, line, eos)) return 0; vp = do_variable_definition_2 (flocp, v.name, v.value, v.value_length, 0, NULL, origin, v.flavor, target_var); #endif #ifndef CONFIG_WITH_STRCACHE2 free (v.name); #else free ((char *)v.name); #endif return vp; } #if defined (CONFIG_WITH_COMPILER) || defined (CONFIG_WITH_MAKE_STATS) static unsigned long var_stats_evalvals, var_stats_evalvaled; static unsigned long var_stats_expands, var_stats_expanded; #endif #ifdef CONFIG_WITH_COMPILER static unsigned long var_stats_expandprogs, var_stats_evalprogs; #endif #ifdef CONFIG_WITH_MAKE_STATS static unsigned long var_stats_changes, var_stats_changed; static unsigned long var_stats_reallocs, var_stats_realloced; static unsigned long var_stats_references, var_stats_referenced; static unsigned long var_stats_val_len, var_stats_val_alloc_len; static unsigned long var_stats_val_rdonly_len; #endif /* Print information for variable V, prefixing it with PREFIX. */ static void print_variable (const void *item, void *arg) { const struct variable *v = item; const char *prefix = arg; const char *origin; #ifdef KMK const struct variable *alias = v; RESOLVE_ALIAS_VARIABLE(v); #endif switch (v->origin) { case o_automatic: origin = _("automatic"); break; case o_default: origin = _("default"); break; case o_env: origin = _("environment"); break; case o_file: origin = _("makefile"); break; case o_env_override: origin = _("environment under -e"); break; case o_command: origin = _("command line"); break; case o_override: origin = _("'override' directive"); break; #ifdef CONFIG_WITH_LOCAL_VARIABLES case o_local: origin = _("`local' directive"); break; #endif case o_invalid: default: abort (); } fputs ("# ", stdout); fputs (origin, stdout); if (v->private_var) fputs (" private", stdout); #ifndef KMK if (v->fileinfo.filenm) printf (_(" (from '%s', line %lu)"), v->fileinfo.filenm, v->fileinfo.lineno + v->fileinfo.offset); #else /* KMK */ if (alias->fileinfo.filenm) printf (_(" (from '%s', line %lu)"), alias->fileinfo.filenm, alias->fileinfo.lineno); if (alias->aliased) fputs (" aliased", stdout); if (alias->alias) printf (_(", alias for '%s'"), v->name); #endif /* KMK */ #if defined (CONFIG_WITH_COMPILER) || defined (CONFIG_WITH_MAKE_STATS) if (v->evalval_count != 0) { # ifdef CONFIG_WITH_MAKE_STATS printf (_(", %u evalvals (%llu ticks)"), v->evalval_count, v->cTicksEvalVal); # else printf (_(", %u evalvals"), v->evalval_count); # endif var_stats_evalvaled++; } var_stats_evalvals += v->evalval_count; if (v->expand_count != 0) { printf (_(", %u expands"), v->expand_count); var_stats_expanded++; } var_stats_expands += v->expand_count; # ifdef CONFIG_WITH_COMPILER if (v->evalprog != 0) { printf (_(", evalprog")); var_stats_evalprogs++; } if (v->expandprog != 0) { printf (_(", expandprog")); var_stats_expandprogs++; } # endif #endif #ifdef CONFIG_WITH_MAKE_STATS if (v->changes != 0) { printf (_(", %u changes"), v->changes); var_stats_changed++; } var_stats_changes += v->changes; if (v->reallocs != 0) { printf (_(", %u reallocs"), v->reallocs); var_stats_realloced++; } var_stats_reallocs += v->reallocs; if (v->references != 0) { printf (_(", %u references"), v->references); var_stats_referenced++; } var_stats_references += v->references; var_stats_val_len += v->value_length; if (v->value_alloc_len) var_stats_val_alloc_len += v->value_alloc_len; else var_stats_val_rdonly_len += v->value_length; assert (v->value_length == strlen (v->value)); /*assert (v->rdonly_val ? !v->value_alloc_len : v->value_alloc_len > v->value_length); - FIXME */ #endif /* CONFIG_WITH_MAKE_STATS */ putchar ('\n'); fputs (prefix, stdout); /* Is this a 'define'? */ if (v->recursive && strchr (v->value, '\n') != 0) #ifndef KMK /** @todo language feature for aliases */ printf ("define %s\n%s\nendef\n", v->name, v->value); #else printf ("define %s\n%s\nendef\n", alias->name, v->value); #endif else { char *p; #ifndef KMK /** @todo language feature for aliases */ printf ("%s %s= ", v->name, v->recursive ? v->append ? "+" : "" : ":"); #else printf ("%s %s= ", alias->name, v->recursive ? v->append ? "+" : "" : ":"); #endif /* Check if the value is just whitespace. */ p = next_token (v->value); if (p != v->value && *p == '\0') /* All whitespace. */ printf ("$(subst ,,%s)", v->value); else if (v->recursive) fputs (v->value, stdout); else /* Double up dollar signs. */ for (p = v->value; *p != '\0'; ++p) { if (*p == '$') putchar ('$'); putchar (*p); } putchar ('\n'); } } static void print_auto_variable (const void *item, void *arg) { const struct variable *v = item; if (v->origin == o_automatic) print_variable (item, arg); } static void print_noauto_variable (const void *item, void *arg) { const struct variable *v = item; if (v->origin != o_automatic) print_variable (item, arg); } /* Print all the variables in SET. PREFIX is printed before the actual variable definitions (everything else is comments). */ #ifndef KMK static #endif void print_variable_set (struct variable_set *set, const char *prefix, int pauto) { #if defined (CONFIG_WITH_COMPILER) || defined (CONFIG_WITH_MAKE_STATS) var_stats_expands = var_stats_expanded = var_stats_evalvals = var_stats_evalvaled = 0; #endif #ifdef CONFIG_WITH_COMPILER var_stats_expandprogs = var_stats_evalprogs = 0; #endif #ifdef CONFIG_WITH_MAKE_STATS var_stats_changes = var_stats_changed = var_stats_reallocs = var_stats_realloced = var_stats_references = var_stats_referenced = var_stats_val_len = var_stats_val_alloc_len = var_stats_val_rdonly_len = 0; #endif hash_map_arg (&set->table, (pauto ? print_auto_variable : print_variable), (void *)prefix); if (set->table.ht_fill) { #ifdef CONFIG_WITH_MAKE_STATS unsigned long fragmentation; fragmentation = var_stats_val_alloc_len - (var_stats_val_len - var_stats_val_rdonly_len); printf(_("# variable set value stats:\n\ # strings %7lu bytes, readonly %6lu bytes\n"), var_stats_val_len, var_stats_val_rdonly_len); if (var_stats_val_alloc_len) printf(_("# allocated %7lu bytes, fragmentation %6lu bytes (%u%%)\n"), var_stats_val_alloc_len, fragmentation, (unsigned int)((100.0 * fragmentation) / var_stats_val_alloc_len)); if (var_stats_changed) printf(_("# changed %5lu (%2u%%), changes %6lu\n"), var_stats_changed, (unsigned int)((100.0 * var_stats_changed) / set->table.ht_fill), var_stats_changes); if (var_stats_realloced) printf(_("# reallocated %5lu (%2u%%), reallocations %6lu\n"), var_stats_realloced, (unsigned int)((100.0 * var_stats_realloced) / set->table.ht_fill), var_stats_reallocs); if (var_stats_referenced) printf(_("# referenced %5lu (%2u%%), references %6lu\n"), var_stats_referenced, (unsigned int)((100.0 * var_stats_referenced) / set->table.ht_fill), var_stats_references); #endif #if defined (CONFIG_WITH_COMPILER) || defined (CONFIG_WITH_MAKE_STATS) if (var_stats_evalvals) printf(_("# evalvaled %5lu (%2u%%), evalval calls %6lu\n"), var_stats_evalvaled, (unsigned int)((100.0 * var_stats_evalvaled) / set->table.ht_fill), var_stats_evalvals); if (var_stats_expands) printf(_("# expanded %5lu (%2u%%), expands %6lu\n"), var_stats_expanded, (unsigned int)((100.0 * var_stats_expanded) / set->table.ht_fill), var_stats_expands); #endif #ifdef CONFIG_WITH_COMPILER if (var_stats_expandprogs || var_stats_evalprogs) printf(_("# eval progs %5lu (%2u%%), expand progs %6lu (%2u%%)\n"), var_stats_evalprogs, (unsigned int)((100.0 * var_stats_evalprogs) / set->table.ht_fill), var_stats_expandprogs, (unsigned int)((100.0 * var_stats_expandprogs) / set->table.ht_fill)); #endif } fputs (_("# variable set hash-table stats:\n"), stdout); fputs ("# ", stdout); hash_print_stats (&set->table, stdout); putc ('\n', stdout); } /* Print the data base of variables. */ void print_variable_data_base (void) { puts (_("\n# Variables\n")); print_variable_set (&global_variable_set, "", 0); puts (_("\n# Pattern-specific Variable Values")); { struct pattern_var *p; unsigned int rules = 0; for (p = pattern_vars; p != 0; p = p->next) { ++rules; printf ("\n%s :\n", p->target); print_variable (&p->variable, (void *)"# "); } if (rules == 0) puts (_("\n# No pattern-specific variable values.")); else printf (_("\n# %u pattern-specific variable values"), rules); } #ifdef CONFIG_WITH_STRCACHE2 strcache2_print_stats (&variable_strcache, "# "); #endif } #ifdef CONFIG_WITH_PRINT_STATS_SWITCH void print_variable_stats (void) { fputs (_("\n# Global variable hash-table stats:\n# "), stdout); hash_print_stats (&global_variable_set.table, stdout); fputs ("\n", stdout); } #endif /* Print all the local variables of FILE. */ void print_file_variables (const struct file *file) { if (file->variables != 0) print_variable_set (file->variables->set, "# ", 1); } void print_target_variables (const struct file *file) { if (file->variables != 0) { int l = strlen (file->name); char *t = alloca (l + 3); strcpy (t, file->name); t[l] = ':'; t[l+1] = ' '; t[l+2] = '\0'; hash_map_arg (&file->variables->set->table, print_noauto_variable, t); } } #ifdef WINDOWS32 void sync_Path_environment (void) { char *path = allocated_variable_expand ("$(PATH)"); static char *environ_path = NULL; if (!path) return; /* If done this before, free the previous entry before allocating new one. */ free (environ_path); /* Create something WINDOWS32 world can grok. */ convert_Path_to_windows32 (path, ';'); environ_path = xstrdup (concat (3, "PATH", "=", path)); putenv (environ_path); free (path); } #endif kbuild-3686/src/kmk/config.h.W32.template0000664000175000017500000003575115053010075020076 0ustar locutuslocutus/* config.h.W32 -- hand-massaged config.h file for Windows builds -*-C-*- Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ /* Suppress some Visual C++ warnings. Maybe after the code cleanup for ISO C we can remove some/all of these. */ #if _MSC_VER > 1000 # pragma warning(disable:4100) /* unreferenced formal parameter */ # pragma warning(disable:4102) /* unreferenced label */ # pragma warning(disable:4127) /* conditional expression is constant */ # pragma warning(disable:4131) /* uses old-style declarator */ # pragma warning(disable:4702) /* unreachable code */ # define _CRT_SECURE_NO_WARNINGS /* function or variable may be unsafe */ # define _CRT_NONSTDC_NO_WARNINGS /* functions w/o a leading underscore */ #endif /* Define to 1 if the 'closedir' function returns void instead of 'int'. */ /* #undef CLOSEDIR_VOID */ /* Define to one of '_getb67', 'GETB67', 'getb67' for Cray-2 and Cray-YMP systems. This function is required for 'alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using 'alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if using 'getloadavg.c'. */ #define C_GETLOADAVG 1 /* Define to 1 for DGUX with . */ /* #undef DGUX */ /* Define to 1 if translation of program messages to the user's native language is requested. */ /* #undef ENABLE_NLS */ /* Use high resolution file timestamps if nonzero. */ #define FILE_TIMESTAMP_HI_RES 0 /* Define to 1 if the 'getloadavg' function needs to be run setuid or setgid. */ /* #undef GETLOADAVG_PRIVILEGED */ /* Define to 1 if you have 'alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ /* #undef HAVE_ALLOCA_H */ /* Define to 1 if you have the 'atexit' function. */ #define HAVE_ATEXIT 1 /* Use case insensitive file names */ /* #undef HAVE_CASE_INSENSITIVE_FS */ /* Define to 1 if you have the clock_gettime function. */ /* #undef HAVE_CLOCK_GETTIME */ /* Embed GNU Guile support. Windows build sets this on the compilation command line. */ /* #undef HAVE_GUILE */ /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* #undef HAVE_DCGETTEXT */ /* Define to 1 if you have the declaration of 'bsd_signal', and to 0 if you don't. */ #define HAVE_DECL_BSD_SIGNAL 0 /* Define to 1 if you have the declaration of 'sys_siglist', and to 0 if you don't. */ #define HAVE_DECL_SYS_SIGLIST 0 /* Define to 1 if you have the declaration of '_sys_siglist', and to 0 if you don't. */ #define HAVE_DECL__SYS_SIGLIST 0 /* Define to 1 if you have the declaration of '__sys_siglist', and to 0 if you don't. */ #define HAVE_DECL___SYS_SIGLIST 0 /* Define to 1 if you have the header file, and it defines 'DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you have the header file, and it defines getcwd() and chdir(). */ #if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(__INTERIX) # define HAVE_DIRECT_H 1 #endif /* Use platform specific coding */ #define HAVE_DOS_PATHS 1 /* Define to 1 if you have the 'dup2' function. */ #define HAVE_DUP2 1 /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define to 1 if you have the 'fdopen' function. */ #ifdef __MINGW32__ #define HAVE_FDOPEN 1 #endif /* Define to 1 if you have the 'fileno' function. */ #define HAVE_FILENO 1 /* Define to 1 if you have the 'getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the 'getgroups' function. */ /* #undef HAVE_GETGROUPS */ /* Define to 1 if you have the 'gethostbyname' function. */ /* #undef HAVE_GETHOSTBYNAME */ /* Define to 1 if you have the 'gethostname' function. */ /* #undef HAVE_GETHOSTNAME */ /* Define to 1 if you have the 'getloadavg' function. */ /* #undef HAVE_GETLOADAVG */ /* Define to 1 if you have the 'getrlimit' function. */ /* #undef HAVE_GETRLIMIT */ /* Define if the GNU gettext() function is already present or preinstalled. */ /* #undef HAVE_GETTEXT */ /* Define to 1 if you have a standard gettimeofday function */ #ifdef __MINGW32__ #define HAVE_GETTIMEOFDAY 1 #endif /* Define if you have the iconv() function. */ /* #undef HAVE_ICONV */ /* Define to 1 if you have the header file. */ #ifdef __MINGW32__ #define HAVE_INTTYPES_H 1 #endif /* Define to 1 if you have the 'dgc' library (-ldgc). */ /* #undef HAVE_LIBDGC */ /* Define to 1 if you have the 'kstat' library (-lkstat). */ /* #undef HAVE_LIBKSTAT */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ /*#define HAVE_LOCALE_H 1*/ /* Define to 1 if you have the 'lstat' function. */ /* #undef HAVE_LSTAT */ /* Define to 1 if you have the header file. */ /* #undef HAVE_MACH_MACH_H */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the 'mkstemp' function. */ /* #undef HAVE_MKSTEMP */ /* Define to 1 if you have the 'mktemp' function. */ #define HAVE_MKTEMP 1 /* Define to 1 if you have the header file, and it defines 'DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NLIST_H */ /* Define to 1 if you have the 'pipe' function. */ /* #undef HAVE_PIPE */ /* Define to 1 if you have the 'pstat_getdynamic' function. */ /* #undef HAVE_PSTAT_GETDYNAMIC */ /* Define to 1 if you have the 'readlink' function. */ /* #undef HAVE_READLINK */ /* Define to 1 if you have the 'realpath' function. */ /* #undef HAVE_REALPATH */ /* Define to 1 if defines the SA_RESTART constant. */ /* #undef HAVE_SA_RESTART */ /* Define to 1 if you have the 'setegid' function. */ /* #undef HAVE_SETEGID */ /* Define to 1 if you have the 'seteuid' function. */ /* #undef HAVE_SETEUID */ /* Define to 1 if you have the 'setlinebuf' function. */ /* #undef HAVE_SETLINEBUF */ /* Define to 1 if you have the 'setlocale' function. */ /*#define HAVE_SETLOCALE 1*/ /* Define to 1 if you have the 'setregid' function. */ /* #undef HAVE_SETREGID */ /* Define to 1 if you have the 'setreuid' function. */ /* #undef HAVE_SETREUID */ /* Define to 1 if you have the 'setrlimit' function. */ /* #undef HAVE_SETRLIMIT */ /* Define to 1 if you have the 'setvbuf' function. */ #define HAVE_SETVBUF 1 /* Define to 1 if you have the 'sigaction' function. */ /* #undef HAVE_SIGACTION */ /* Define to 1 if you have the 'sigsetmask' function. */ /* #undef HAVE_SIGSETMASK */ /* Define to 1 if you have the 'socket' function. */ /* #undef HAVE_SOCKET */ /* Define to 1 if you have the header file. */ #ifdef __MINGW32__ #define HAVE_STDINT_H 1 #endif /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the 'strcasecmp' function. */ #ifdef __MINGW32__ #define HAVE_STRCASECMP 1 #endif /* Define to 1 if you have the 'strcmpi' function. */ #define HAVE_STRCMPI 1 /* Define to 1 if you have the 'strcoll' function and it is properly defined. */ #define HAVE_STRCOLL 1 /* Define to 1 if you have the 'strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the 'strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the 'stricmp' function. */ #define HAVE_STRICMP 1 /* Define to 1 if you have the header file. */ /* #define HAVE_STRINGS_H 1 */ /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the 'strncasecmp' function. */ #ifdef __MINGW32__ #define HAVE_STRNCASECMP 1 #endif /* Define to 1 if you have the 'strncmpi' function. */ /* #undef HAVE_STRNCMPI */ /* Define to 1 if you have the 'strndup' function. */ /* #undef HAVE_STRNDUP */ /* Define to 1 if you have the 'strnicmp' function. */ #ifdef __MINGW32__ #define HAVE_STRNICMP 1 #endif /* Define to 1 if you have the 'strsignal' function. */ /* #undef HAVE_STRSIGNAL */ /* Define to 1 if you have the `isatty' function. */ #define HAVE_ISATTY 1 /* Define to 1 if you have the `ttyname' function. */ #define HAVE_TTYNAME 1 char *ttyname (int); /* Define to 1 if 'n_un.n_name' is a member of 'struct nlist'. */ /* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* 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, and it defines 'DIR'. */ /* #undef HAVE_SYS_NDIR_H */ /* Define to 1 if you have the header file. */ #ifdef __MINGW32__ #define HAVE_SYS_PARAM_H 1 #endif /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_RESOURCE_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIMEB_H 1 /* Define to 1 if you have the header file. */ #ifdef __MINGW32__ #define HAVE_SYS_TIME_H 1 #endif /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_WAIT_H */ /* Define to 1 if you have the \'union wait' type in . */ /* #undef HAVE_UNION_WAIT */ /* Define to 1 if you have the header file. */ #ifdef __MINGW32__ #define HAVE_UNISTD_H 1 #endif /* Define to 1 if you have the 'wait3' function. */ /* #undef HAVE_WAIT3 */ /* Define to 1 if you have the 'waitpid' function. */ /* #undef HAVE_WAITPID */ /* Build host information. (not used by kmk) */ #define MAKE_HOST "Windows32" /* Define to 1 to enable job server support in GNU make. */ #define MAKE_JOBSERVER 1 /* Define to 1 to enable 'load' support in GNU make. */ #define MAKE_LOAD 1 /* Define to 1 to enable symbolic link timestamp checking. */ /* #undef MAKE_SYMLINKS */ /* Define to 1 if your 'struct nlist' has an 'n_un' member. Obsolete, depend on 'HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* #undef NLIST_NAME_UNION */ /* Define to 1 if struct nlist.n_name is a pointer rather than an array. */ /* #undef NLIST_STRUCT */ /* Define to 1 if your C compiler doesn't accept -c and -o together. */ /* #undef NO_MINUS_C_MINUS_O */ /* Name of this package (needed by automake) */ #define PACKAGE "%PACKAGE%" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bug-make@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "GNU make" /* Define to the home page for this package. */ #define PACKAGE_URL "http://www.gnu.org/software/make/" /* Define to the version of this package. */ #define PACKAGE_VERSION "%VERSION%" /* Define to the character that separates directories in PATH. */ #define PATH_SEPARATOR_CHAR ';' /* Define as the return type of signal handlers ('int' or 'void'). */ #define RETSIGTYPE void /* Define to the name of the SCCS 'get' command. */ #define SCCS_GET "echo no sccs get" /* Define this if the SCCS 'get' command understands the '-G' option. */ /* #undef SCCS_GET_MINUS_G */ /* Define to 1 if the 'setvbuf' function takes the buffering type as its second argument and the buffer pointer as the third, as on System V before release 3. */ /* #undef SETVBUF_REVERSED */ /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if the 'S_IS*' macros in do not work properly. */ /* #undef STAT_MACROS_BROKEN */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define if struct stat contains a nanoseconds field */ /* #undef ST_MTIM_NSEC */ /* Define to 1 on System V Release 4. */ /* #undef SVR4 */ /* Define to 1 if you can safely include both and . */ #ifdef __MINGW32__ #define TIME_WITH_SYS_TIME 1 #endif /* Define to 1 for Encore UMAX. */ /* #undef UMAX */ /* Define to 1 for Encore UMAX 4.3 that has instead of . */ /* #undef UMAX4_3 */ /* Version number of package */ #define VERSION "%VERSION%" /* Define if using the dmalloc debugging malloc package */ /* #undef WITH_DMALLOC */ /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* # undef _ALL_SOURCE */ #endif /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for 'stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Define to empty if 'const' does not conform to ANSI C. */ /* #undef const */ #include /* Define to 'int' if doesn't define. */ #define gid_t int /* Define to 'int' if does not define. */ /* GCC 4.x reportedly defines pid_t. */ #ifndef _PID_T_ #ifdef _WIN64 #define pid_t __int64 #else #define pid_t int #endif #endif /* Define to 'int' if doesn't define. */ #define uid_t int /* Define uintmax_t if not defined in or . */ #if !HAVE_STDINT_H && !HAVE_INTTYPES_H #define uintmax_t unsigned long #endif /* Define if you have that is POSIX.1 compatible. */ /* #undef HAVE_SYS_WAIT_H */ /* Define to the installation directory for locales. */ #define LOCALEDIR "" /* * Refer to README.W32 for info on the following settings */ /* * If you have a shell that does not grok 'sh -c quoted-command-line' * correctly, you need this setting. Please see below for specific * shell support. */ /*#define BATCH_MODE_ONLY_SHELL 1 */ /* * Define if you have the Cygnus "Cygwin" GNU Windows32 tool set. * Do NOT define BATCH_MODE_ONLY_SHELL if you define HAVE_CYGWIN_SHELL */ /*#define HAVE_CYGWIN_SHELL 1 */ /* * Define if you have the MKS tool set or shell. Do NOT define * BATCH_MODE_ONLY_SHELL if you define HAVE_MKS_SHELL */ /*#define HAVE_MKS_SHELL 1 */ /* * Enforce the mutual exclusivity restriction. */ #ifdef HAVE_MKS_SHELL #undef BATCH_MODE_ONLY_SHELL #endif #ifdef HAVE_CYGWIN_SHELL #undef BATCH_MODE_ONLY_SHELL #endif kbuild-3686/src/kmk/filedef.h0000664000175000017500000002703415053010075016036 0ustar locutuslocutus/* Definition of target file data structures for GNU Make. Copyright (C) 1988-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ /* Structure that represents the info on one file that the makefile says how to make. All of these are chained together through 'next'. */ #include "hash.h" struct file { const char *name; const char *hname; /* Hashed filename */ const char *vpath; /* VPATH/vpath pathname */ struct dep *deps; /* all dependencies, including duplicates */ #ifdef CONFIG_WITH_LAZY_DEPS_VARS struct dep *deps_no_dupes; /* dependencies without duplicates, created on demaned by func_deps. */ #endif struct commands *cmds; /* Commands to execute for this target. */ const char *stem; /* Implicit stem, if an implicit rule has been used */ struct dep *also_make; /* Targets that are made by making this. */ struct file *prev; /* Previous entry for same file name; used when there are multiple double-colon entries for the same file. */ struct file *last; /* Last entry for the same file name. */ /* File that this file was renamed to. After any time that a file could be renamed, call 'check_renamed' (below). */ struct file *renamed; /* List of variable sets used for this file. */ struct variable_set_list *variables; /* Pattern-specific variable reference for this target, or null if there isn't one. Also see the pat_searched flag, below. */ struct variable_set_list *pat_variables; /* Immediate dependent that caused this target to be remade, or nil if there isn't one. */ struct file *parent; /* For a double-colon entry, this is the first double-colon entry for the same file. Otherwise this is null. */ struct file *double_colon; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET /* For a target of an explicit multi target rule, this points to the primary target. Otherwise this is null. */ struct file *multi_head; /* Pointer to next target of an explicit multi target rule. */ struct file *multi_next; #endif #ifdef CONFIG_WITH_COMPILER struct kmk_cc_evalprog *evalprog; /* Pointer to evalval/evalctx "program". */ #endif FILE_TIMESTAMP last_mtime; /* File's modtime, if already known. */ FILE_TIMESTAMP mtime_before_update; /* File's modtime before any updating has been performed. */ unsigned int considered; /* equal to 'considered' if file has been considered on current scan of goal chain */ int command_flags; /* Flags OR'd in for cmds; see commands.h. */ enum update_status /* Status of the last attempt to update. */ { us_success = 0, /* Successfully updated. Must be 0! */ us_none, /* No attempt to update has been made. */ us_question, /* Needs to be updated (-q is is set). */ us_failed /* Update failed. */ } update_status ENUM_BITFIELD (2); enum cmd_state /* State of the commands. */ { cs_not_started = 0, /* Not yet started. Must be 0! */ cs_deps_running, /* Dep commands running. */ cs_running, /* Commands running. */ cs_finished /* Commands finished. */ } command_state ENUM_BITFIELD (2); unsigned int builtin:1; /* True if the file is a builtin rule. */ unsigned int precious:1; /* Non-0 means don't delete file on quit */ unsigned int loaded:1; /* True if the file is a loaded object. */ unsigned int low_resolution_time:1; /* Nonzero if this file's time stamp has only one-second resolution. */ unsigned int tried_implicit:1; /* Nonzero if have searched for implicit rule for making this file; don't search again. */ unsigned int updating:1; /* Nonzero while updating deps of this file */ unsigned int updated:1; /* Nonzero if this file has been remade. */ unsigned int is_target:1; /* Nonzero if file is described as target. */ unsigned int cmd_target:1; /* Nonzero if file was given on cmd line. */ unsigned int phony:1; /* Nonzero if this is a phony file i.e., a prerequisite of .PHONY. */ unsigned int intermediate:1;/* Nonzero if this is an intermediate file. */ unsigned int secondary:1; /* Nonzero means remove_intermediates should not delete it. */ unsigned int dontcare:1; /* Nonzero if no complaint is to be made if this target cannot be remade. */ unsigned int ignore_vpath:1;/* Nonzero if we threw out VPATH name. */ unsigned int pat_searched:1;/* Nonzero if we already searched for pattern-specific variables. */ unsigned int no_diag:1; /* True if the file failed to update and no diagnostics has been issued (dontcare). */ #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET unsigned int multi_maybe:1; /* Nonzero if this file isn't always updated by the explicit multi target rule. */ #endif #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION unsigned int need_2nd_target_expansion:1; /* Nonzero if this file needs second expansion of its name. Whether it can receive this is decided at parse time, and the expanding done in snap_deps. */ #endif #if defined (CONFIG_WITH_COMPILER) || defined (CONFIG_WITH_MAKE_STATS) unsigned int eval_count:14; /* Times evaluated as a makefile. */ #endif }; extern struct file *default_file; struct file *lookup_file (const char *name); #ifdef CONFIG_WITH_STRCACHE2 struct file *lookup_file_cached (const char *name); #endif struct file *enter_file (const char *name); struct dep *split_prereqs (char *prereqstr); struct dep *enter_prereqs (struct dep *prereqs, const char *stem); void remove_intermediates (int sig); void snap_deps (void); void rename_file (struct file *file, const char *name); void rehash_file (struct file *file, const char *name); void set_command_state (struct file *file, enum cmd_state state); void notice_finished_file (struct file *file); void init_hash_files (void); void verify_file_data_base (void); char *build_target_list (char *old_list); void print_prereqs (const struct dep *deps); void print_file_data_base (void); int try_implicit_rule (struct file *file, unsigned int depth); int stemlen_compare (const void *v1, const void *v2); #if FILE_TIMESTAMP_HI_RES # define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \ file_timestamp_cons (fname, (st).st_mtime, (st).ST_MTIM_NSEC) #else # define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \ file_timestamp_cons (fname, (st).st_mtime, 0) #endif /* If FILE_TIMESTAMP is 64 bits (or more), use nanosecond resolution. (Multiply by 2**30 instead of by 10**9 to save time at the cost of slightly decreasing the number of available timestamps.) With 64-bit FILE_TIMESTAMP, this stops working on 2514-05-30 01:53:04 UTC, but by then uintmax_t should be larger than 64 bits. */ #define FILE_TIMESTAMPS_PER_S (FILE_TIMESTAMP_HI_RES ? 1000000000 : 1) #define FILE_TIMESTAMP_LO_BITS (FILE_TIMESTAMP_HI_RES ? 30 : 0) #define FILE_TIMESTAMP_S(ts) (((ts) - ORDINARY_MTIME_MIN) \ >> FILE_TIMESTAMP_LO_BITS) #define FILE_TIMESTAMP_NS(ts) ((int) (((ts) - ORDINARY_MTIME_MIN) \ & ((1 << FILE_TIMESTAMP_LO_BITS) - 1))) /* Upper bound on length of string "YYYY-MM-DD HH:MM:SS.NNNNNNNNN" representing a file timestamp. The upper bound is not necessarily 29, since the year might be less than -999 or greater than 9999. Subtract one for the sign bit if in case file timestamps can be negative; subtract FLOOR_LOG2_SECONDS_PER_YEAR to yield an upper bound on how many file timestamp bits might affect the year; 302 / 1000 is log10 (2) rounded up; add one for integer division truncation; add one more for a minus sign if file timestamps can be negative; add 4 to allow for any 4-digit epoch year (e.g. 1970); add 25 to allow for "-MM-DD HH:MM:SS.NNNNNNNNN". */ #define FLOOR_LOG2_SECONDS_PER_YEAR 24 #define FILE_TIMESTAMP_PRINT_LEN_BOUND \ (((sizeof (FILE_TIMESTAMP) * CHAR_BIT - 1 - FLOOR_LOG2_SECONDS_PER_YEAR) \ * 302 / 1000) \ + 1 + 1 + 4 + 25) FILE_TIMESTAMP file_timestamp_cons (char const *, time_t, long int); FILE_TIMESTAMP file_timestamp_now (int *); void file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts); /* Return the mtime of file F (a struct file *), caching it. The value is NONEXISTENT_MTIME if the file does not exist. */ #define file_mtime(f) file_mtime_1 ((f), 1) /* Return the mtime of file F (a struct file *), caching it. Don't search using vpath for the file--if it doesn't actually exist, we don't find it. The value is NONEXISTENT_MTIME if the file does not exist. */ #define file_mtime_no_search(f) file_mtime_1 ((f), 0) FILE_TIMESTAMP f_mtime (struct file *file, int search); #define file_mtime_1(f, v) \ ((f)->last_mtime == UNKNOWN_MTIME ? f_mtime ((f), v) : (f)->last_mtime) /* Special timestamp values. */ /* The file's timestamp is not yet known. */ #define UNKNOWN_MTIME 0 /* The file does not exist. */ #define NONEXISTENT_MTIME 1 /* The file does not exist, and we assume that it is older than any actual file. */ #define OLD_MTIME 2 /* The smallest and largest ordinary timestamps. */ #define ORDINARY_MTIME_MIN (OLD_MTIME + 1) #if FILE_TIMESTAMP_HI_RES == 0 /* bird: shut up annoying warnings! ASSUMES: unsigned FILE_TIMESTAMP ++. */ # define ORDINARY_MTIME_MAX ( ~ (FILE_TIMESTAMP) 0 ) #else #define ORDINARY_MTIME_MAX ((FILE_TIMESTAMP_S (NEW_MTIME) \ << FILE_TIMESTAMP_LO_BITS) \ + ORDINARY_MTIME_MIN + FILE_TIMESTAMPS_PER_S - 1) #endif /* Modtime value to use for 'infinitely new'. We used to get the current time from the system and use that whenever we wanted 'new'. But that causes trouble when the machine running make and the machine holding a file have different ideas about what time it is; and can also lose for 'force' targets, which need to be considered newer than anything that depends on them, even if said dependents' modtimes are in the future. */ #if 1 /* bird: ASSUME the type is unsigned and the wrath of a pedantic gcc. */ # define NEW_MTIME ( ~ (FILE_TIMESTAMP) 0 ) #else #define NEW_MTIME INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP) #endif #define check_renamed(file) \ while ((file)->renamed != 0) (file) = (file)->renamed /* No ; here. */ /* Have we snapped deps yet? */ extern int snapped_deps; kbuild-3686/src/kmk/w32/0000775000175000017500000000000015053010075014674 5ustar locutuslocutuskbuild-3686/src/kmk/w32/include/0000775000175000017500000000000015053010075016317 5ustar locutuslocutuskbuild-3686/src/kmk/w32/include/dirent.h0000664000175000017500000000312415053010075017755 0ustar locutuslocutus/* Windows version of dirent.h Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #ifndef _DIRENT_H #define _DIRENT_H #ifdef KMK # include # include "nt/ntdir.h" #else /* !KMK */ #ifdef __MINGW32__ # include # include_next #else #include #include #include #include #ifndef NAME_MAX #define NAME_MAX 255 #endif #define __DIRENT_COOKIE 0xfefeabab struct dirent { ino_t d_ino; /* unused - no equivalent on WINDOWS32 */ char d_name[NAME_MAX+1]; }; typedef struct dir_struct { ULONG dir_ulCookie; HANDLE dir_hDirHandle; DWORD dir_nNumFiles; char dir_pDirectoryName[NAME_MAX+1]; struct dirent dir_sdReturn; } DIR; DIR *opendir(const char *); struct dirent *readdir(DIR *); void rewinddir(DIR *); void closedir(DIR *); int telldir(DIR *); void seekdir(DIR *, long); #endif /* !__MINGW32__ */ #endif /* !KMK */ #endif kbuild-3686/src/kmk/w32/include/sub_proc.h0000664000175000017500000000521215053010074020303 0ustar locutuslocutus/* Definitions for Windows process invocation. Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #ifndef SUB_PROC_H #define SUB_PROC_H #ifdef CONFIG_NEW_WIN_CHILDREN # error "Just checking..." #endif /* * Component Name: * * $Date$ * * $Source$ * * $Id$ */ #define EXTERN_DECL(entry, args) extern entry args #define VOID_DECL void EXTERN_DECL(HANDLE process_init, (VOID_DECL)); EXTERN_DECL(HANDLE process_init_fd, (HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)); EXTERN_DECL(long process_begin, (HANDLE proc, char **argv, char **envp, char *exec_path, char *as_user)); EXTERN_DECL(long process_pipe_io, (HANDLE proc, char *stdin_data, int stdin_data_len)); #ifndef KMK /* unused */ EXTERN_DECL(long process_file_io, (HANDLE proc)); #endif EXTERN_DECL(void process_cleanup, (HANDLE proc)); EXTERN_DECL(HANDLE process_wait_for_any, (int block, DWORD* pdwWaitStatus)); EXTERN_DECL(void process_register, (HANDLE proc)); EXTERN_DECL(HANDLE process_easy, (char** argv, char** env, int outfd, int errfd)); EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal)); EXTERN_DECL(int process_used_slots, (VOID_DECL)); EXTERN_DECL(DWORD process_set_handles, (HANDLE *handles)); #ifdef KMK EXTERN_DECL(int process_kmk_register_submit, (HANDLE hEvent, intptr_t clue, pid_t *pPid)); EXTERN_DECL(int process_kmk_register_redirect, (HANDLE hProcess, pid_t *pPid)); #endif /* support routines */ EXTERN_DECL(long process_errno, (HANDLE proc)); EXTERN_DECL(long process_last_err, (HANDLE proc)); EXTERN_DECL(long process_exit_code, (HANDLE proc)); EXTERN_DECL(long process_signal, (HANDLE proc)); EXTERN_DECL(char * process_outbuf, (HANDLE proc)); EXTERN_DECL(char * process_errbuf, (HANDLE proc)); EXTERN_DECL(int process_outcnt, (HANDLE proc)); EXTERN_DECL(int process_errcnt, (HANDLE proc)); EXTERN_DECL(void process_pipes, (HANDLE proc, int pipes[3])); EXTERN_DECL(void process_noinherit, (int fildes)); #endif kbuild-3686/src/kmk/w32/include/dlfcn.h0000664000175000017500000000176015053010075017562 0ustar locutuslocutus/* dlfcn.h replacement for MS-Windows build. Copyright (C) 2013-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #ifndef DLFCN_H #define DLFCN_H #define RTLD_LAZY 1 #define RTLD_NOW 2 #define RTLD_GLOBAL 4 extern void *dlopen (const char *, int); extern void *dlsym (void *, const char *); extern char *dlerror (void); extern int dlclose (void *); #endif /* DLFCN_H */ kbuild-3686/src/kmk/w32/include/pathstuff.h0000664000175000017500000000217415053010074020477 0ustar locutuslocutus/* Definitions for Windows path manipulation. Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #ifndef _PATHSTUFF_H #define _PATHSTUFF_H char *convert_Path_to_windows32(char *Path, char to_delim); char *convert_vpath_to_windows32(char *Path, char to_delim); #if 1 char *unix_slashes(char *filename); /* bird */ char *unix_slashes_resolved(const char *src, char *dst, unsigned len); /* bird */ #else char *w32ify(const char *filename, int resolve); #endif char *getcwd_fs(char *buf, int len); #endif kbuild-3686/src/kmk/w32/include/w32err.h0000664000175000017500000000166315053010075017622 0ustar locutuslocutus/* Definitions for Windows error handling. Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #ifndef _W32ERR_H_ #define _W32ERR_H_ #ifndef EXTERN_DECL #define EXTERN_DECL(entry, args) entry args #endif EXTERN_DECL(const char * map_windows32_error_to_string, (DWORD error)); #endif /* !_W32ERR_H */ kbuild-3686/src/kmk/w32/tstFileInfo.c0000664000175000017500000001167615053010075017301 0ustar locutuslocutus/* $Id: $ */ /** @file * Test program for some NtQueryInformationFile functionality. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ #include #include typedef enum _FILE_INFORMATION_CLASS { FileDirectoryInformation = 1, FileFullDirectoryInformation, // 2 FileBothDirectoryInformation, // 3 FileBasicInformation, // 4 wdm FileStandardInformation, // 5 wdm FileInternalInformation, // 6 FileEaInformation, // 7 FileAccessInformation, // 8 FileNameInformation, // 9 FileRenameInformation, // 10 FileLinkInformation, // 11 FileNamesInformation, // 12 FileDispositionInformation, // 13 FilePositionInformation, // 14 wdm FileFullEaInformation, // 15 FileModeInformation, // 16 FileAlignmentInformation, // 17 FileAllInformation, // 18 FileAllocationInformation, // 19 FileEndOfFileInformation, // 20 wdm FileAlternateNameInformation, // 21 FileStreamInformation, // 22 FilePipeInformation, // 23 FilePipeLocalInformation, // 24 FilePipeRemoteInformation, // 25 FileMailslotQueryInformation, // 26 FileMailslotSetInformation, // 27 FileCompressionInformation, // 28 FileObjectIdInformation, // 29 FileCompletionInformation, // 30 FileMoveClusterInformation, // 31 FileQuotaInformation, // 32 FileReparsePointInformation, // 33 FileNetworkOpenInformation, // 34 FileAttributeTagInformation, // 35 FileTrackingInformation, // 36 FileIdBothDirectoryInformation, // 37 FileIdFullDirectoryInformation, // 38 FileMaximumInformation } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; typedef struct _FILE_NAME_INFORMATION { ULONG FileNameLength; WCHAR FileName[1]; } FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; typedef LONG NTSTATUS; typedef struct _IO_STATUS_BLOCK { union { NTSTATUS Status; PVOID Pointer; }; ULONG_PTR Information; } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass); int main(int argc, char **argv) { int rc = 0; int i; NTSTATUS (NTAPI *pfnNtQueryInformationFile)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass); pfnNtQueryInformationFile = GetProcAddress(LoadLibrary("ntdll.dll"), "NtQueryInformationFile"); for (i = 1; i < argc; i++) { HANDLE hFile = CreateFile(argv[i], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hFile) { long rcNt; char abBuf[4096]; IO_STATUS_BLOCK Ios; memset(abBuf, 0, sizeof(abBuf)); memset(&Ios, 0, sizeof(Ios)); rcNt = pfnNtQueryInformationFile(hFile, &Ios, abBuf, sizeof(abBuf), FileNameInformation); if (rcNt >= 0) { PFILE_NAME_INFORMATION pFileNameInfo = (PFILE_NAME_INFORMATION)abBuf; printf("#%d: %s - rcNt=%#x - FileNameInformation:\n" " FileName: %ls\n" " FileNameLength: %lu\n", i, argv[i], rcNt, pFileNameInfo->FileName, pFileNameInfo->FileNameLength ); } else printf("#%d: %s - rcNt=%#x - FileNameInformation!\n", i, argv[i], rcNt); CloseHandle(hFile); } else { printf("#%d: %s - open failed, last error %d\n", i, argv[i], GetLastError()); rc = 1; } } return rc; } kbuild-3686/src/kmk/w32/Makefile.am0000664000175000017500000000204115053010075016725 0ustar locutuslocutus# Makefile.am to create libw32.a for mingw32 host. # Copyright (C) 1997-2016 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) any later # version. # # GNU Make 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, see . AUTOMAKE_OPTIONS = subdir-objects noinst_LIBRARIES = libw32.a libw32_a_SOURCES = subproc/misc.c subproc/sub_proc.c subproc/w32err.c \ compat/posixfcn.c pathstuff.c w32os.c libw32_a_CPPFLAGS = -I$(srcdir)/include -I$(srcdir)/subproc -I$(top_srcdir) \ -I$(top_srcdir)/glob kbuild-3686/src/kmk/w32/winchildren.h0000664000175000017500000001135215053010075017355 0ustar locutuslocutus/* $Id: winchildren.h 3313 2020-03-16 02:31:38Z bird $ */ /** @file * Child process creation and management for kmk. */ /* * Copyright (c) 2018 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ #ifndef INCLUDED_WINCHILDREN_H #define INCLUDED_WINCHILDREN_H /** Child processor group allocator state. */ typedef struct MKWINCHILDCPUGROUPALLOCSTATE { /** The group index for the worker allocator. * This is ever increasing and must be modded by g_cProcessorGroups. */ unsigned int idxGroup; /** The processor in group index for the worker allocator. */ unsigned int idxProcessorInGroup; } MKWINCHILDCPUGROUPALLOCSTATE; /** Pointer to a CPU group allocator state. */ typedef MKWINCHILDCPUGROUPALLOCSTATE *PMKWINCHILDCPUGROUPALLOCSTATE; #ifdef DECLARE_HANDLE /** * A childcare worker pipe. */ typedef struct WINCCWPIPE { /** My end of the pipe. */ HANDLE hPipeMine; /** The child end of the pipe. */ HANDLE hPipeChild; /** The event for asynchronous reading. */ HANDLE hEvent; /** Which pipe this is (1 == stdout, 2 == stderr). */ unsigned char iWhich; /** Set if we've got a read pending already. */ BOOL fReadPending; /** Indicator that we've written out something. This is cleared before * we start catching output from a new child and use in the CL.exe * supression heuristics. */ BOOL fHaveWrittenOut; /** Number of bytes at the start of the buffer that we've already * written out. We try write out whole lines. */ DWORD cbWritten; /** The buffer offset of the read currently pending. */ DWORD offPendingRead; /** Read buffer size. */ DWORD cbBuffer; /** The read buffer allocation. */ unsigned char *pbBuffer; /** Overlapped I/O structure. */ OVERLAPPED Overlapped; } WINCCWPIPE; #endif typedef struct WINCCWPIPE *PWINCCWPIPE; void MkWinChildInit(unsigned int cJobSlot); void MkWinChildReExecMake(char **papszArgs, char **papszEnv); intptr_t MkWinChildGetCompleteEventHandle(void); int MkWinChildCreate(char **papszArgs, char **papszEnv, const char *pszShell, struct child *pMkChild, pid_t *pPid); int MkWinChildCreateWithStdOutPipe(char **papszArgs, char **papszEnv, int fdErr, pid_t *pPid, int *pfdReadPipe); void MkWinChildInitCpuGroupAllocator(PMKWINCHILDCPUGROUPALLOCSTATE pState); unsigned int MkWinChildAllocateCpuGroup(PMKWINCHILDCPUGROUPALLOCSTATE pState); #ifdef KMK struct KMKBUILTINENTRY; int MkWinChildCreateBuiltIn(struct KMKBUILTINENTRY const *pBuiltIn, int cArgs, char **papszArgs, char **papszEnv, struct child *pMkChild, pid_t *pPid); int MkWinChildCreateAppend(const char *pszFilename, char **ppszAppend, size_t cbAppend, int fTruncate, struct child *pMkChild, pid_t *pPid); int MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr, struct child *pMkChild, pid_t *pPid); PWINCCWPIPE MkWinChildcareCreateWorkerPipe(unsigned iWhich, unsigned int idxWorker); void MkWinChildcareWorkerDrainPipes(struct WINCHILD *pChild, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr); void MkWinChildcareDeleteWorkerPipe(PWINCCWPIPE pPipe); int MkWinChildCreateRedirect(intptr_t hProcess, pid_t *pPid); # ifdef DECLARE_HANDLE int MkWinChildBuiltInExecChild(void *pvWorker, const char *pszExecutable, char **papszArgs, BOOL fQuotedArgv, char **papszEnvVars, const char *pszCwd, BOOL pafReplace[3], HANDLE pahReplace[3]); # endif #endif /* KMK */ int MkWinChildKill(pid_t pid, int iSignal, struct child *pMkChild); int MkWinChildWait(int fBlock, pid_t *pPid, int *piExitCode, int *piSignal, int *pfCoreDumped, struct child **ppMkChild); void MkWinChildExclusiveAcquire(void); void MkWinChildExclusiveRelease(void); #undef CLOSE_ON_EXEC #define CLOSE_ON_EXEC(a_fd) MkWinChildUnrelatedCloseOnExec(a_fd) int MkWinChildUnrelatedCloseOnExec(int fd); #endif kbuild-3686/src/kmk/w32/winchildren.c0000664000175000017500000043043715053010075017361 0ustar locutuslocutus/* $Id: winchildren.c 3667 2025-02-21 14:36:48Z bird $ */ /** @file * Child process creation and management for kmk. */ /* * Copyright (c) 2018 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /* No GNU coding style here atm, convert if upstreamed. */ /** @page pg_win_children Windows child process creation and managment * * This new implementation aims at addressing the following: * * 1. Speed up process creation by doing the expensive CreateProcess call * in a worker thread. * * 2. No 64 process limit imposed by WaitForMultipleObjects. * * 3. Better distribute jobs among processor groups. * * 4. Offloading more expensive kmkbuiltin operations to worker threads, * making the main thread focus on managing child processes. * * 5. Output synchronization using reusable pipes. * * * To be quite honest, the first item (CreateProcess expense) didn't occur to me * at first and was more of a sideeffect discovered along the way. A test * rebuilding IPRT went from 4m52s to 3m19s on a 8 thread system. * * The 2nd and 3rd goals are related to newer build servers that have lots of * CPU threads and various Windows NT (aka NT OS/2 at the time) design choices * made in the late 1980ies. * * WaitForMultipleObjects does not support waiting for more than 64 objects, * unlike poll and select. This is just something everyone ends up having to * work around in the end. * * Affinity masks are uintptr_t sized, so 64-bit hosts can only manage 64 * processors and 32-bit only 32. Workaround was introduced with Windows 7 * (IIRC) and is called processor groups. The CPU threads are grouped into 1 or * more groups of up to 64 processors. Processes are generally scheduled to a * signle processor group at first, but threads may be changed to be scheduled * on different groups. This code will try distribute children evenly among the * processor groups, using a very simple algorithm (see details in code). * * * @section sec_win_children_av Remarks on Microsoft Defender and other AV * * Part of the motivation for writing this code was horrible CPU utilization on * a brand new AMD Threadripper 1950X system with lots of memory and SSDs, * running 64-bit Windows 10 build 16299. * * Turns out Microsoft defender adds some overhead to CreateProcess * and other stuff: * - Old make with CreateProcess on main thread: * - With runtime defender enabled: 14 min 6 seconds * - With runtime defender disabled: 4 min 49 seconds * - New make with CreateProcess on worker thread (this code): * - With runtime defender enabled: 6 min 29 seconds * - With runtime defender disabled: 4 min 36 seconds * - With runtime defender disabled out dir only: 5 min 59 seconds * * See also kWorker / kSubmit for more bickering about AV & disk encryption. */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #include #include #include "../makeint.h" #include "../job.h" #include "../filedef.h" #include "../debug.h" #include "../kmkbuiltin.h" #include "winchildren.h" #include #include #include #include "nt/nt_child_inject_standard_handles.h" #include "console.h" #ifndef KMK_BUILTIN_STANDALONE extern void kmk_cache_exec_image_w(const wchar_t *); /* imagecache.c */ #endif /* Option values from main.c: */ extern const char *win_job_object_mode; extern const char *win_job_object_name; extern int win_job_object_no_kill; /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ #define MKWINCHILD_MAX_PATH 1024 #define MKWINCHILD_DO_SET_PROCESSOR_GROUP /** Checks the UTF-16 environment variable pointed to is the PATH. */ #define IS_PATH_ENV_VAR(a_cwcVar, a_pwszVar) \ ( (a_cwcVar) >= 5 \ && (a_pwszVar)[4] == L'=' \ && ((a_pwszVar)[0] == L'P' || (a_pwszVar)[0] == L'p') \ && ((a_pwszVar)[1] == L'A' || (a_pwszVar)[1] == L'a') \ && ((a_pwszVar)[2] == L'T' || (a_pwszVar)[2] == L't') \ && ((a_pwszVar)[3] == L'H' || (a_pwszVar)[3] == L'h') ) /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ /** Pointer to a childcare worker thread. */ typedef struct WINCHILDCAREWORKER *PWINCHILDCAREWORKER; /** Pointer to a windows child process. */ typedef struct WINCHILD *PWINCHILD; /** * Child process type. */ typedef enum WINCHILDTYPE { WINCHILDTYPE_INVALID = 0, /** Normal child process. */ WINCHILDTYPE_PROCESS, #ifdef KMK /** kmkbuiltin command. */ WINCHILDTYPE_BUILT_IN, /** kmkbuiltin_append result write out. */ WINCHILDTYPE_APPEND, /** kSubmit job. */ WINCHILDTYPE_SUBMIT, /** kmk_redirect job. */ WINCHILDTYPE_REDIRECT, #endif /** End of valid child types. */ WINCHILDTYPE_END } WINCHILDTYPE; /** * Windows child process. */ typedef struct WINCHILD { /** Magic / eyecatcher (WINCHILD_MAGIC). */ ULONG uMagic; /** Child type. */ WINCHILDTYPE enmType; /** Pointer to the next child process. */ PWINCHILD pNext; /** The pid for this child. */ pid_t pid; /** The make child structure associated with this child. */ struct child *pMkChild; /** The process exit code. */ int iExitCode; /** Kill signal, in case we or someone else killed it. */ int iSignal; /** Set if core was dumped. */ int fCoreDumped; /** Set if the a child process is a candidate for cl.exe where we supress * annoying source name output. */ BOOL fProbableClExe; /** The worker executing this child. */ PWINCHILDCAREWORKER pWorker; /** Type specific data. */ union { /** Data for WINCHILDTYPE_PROCESS. */ struct { /** Argument vector (single allocation, strings following array). */ char **papszArgs; /** Length of the argument strings. */ size_t cbArgsStrings; /** Environment vector. Only a copy if fEnvIsCopy is set. */ char **papszEnv; /** If we made a copy of the environment, this is the size of the * strings and terminator string (not in array). This is done to * speed up conversion, since MultiByteToWideChar can handle '\0'. */ size_t cbEnvStrings; /** The make shell to use (copy). */ char *pszShell; /** Handle to use for standard out. */ HANDLE hStdOut; /** Handle to use for standard out. */ HANDLE hStdErr; /** Whether to close hStdOut after creating the process. */ BOOL fCloseStdOut; /** Whether to close hStdErr after creating the process. */ BOOL fCloseStdErr; /** Whether to catch output from the process. */ BOOL fCatchOutput; /** Child process handle. */ HANDLE hProcess; } Process; /** Data for WINCHILDTYPE_BUILT_IN. */ struct { /** The built-in command. */ PCKMKBUILTINENTRY pBuiltIn; /** Number of arguments. */ int cArgs; /** Argument vector (single allocation, strings following array). */ char **papszArgs; /** Environment vector. Only a copy if fEnvIsCopy is set. */ char **papszEnv; } BuiltIn; /** Data for WINCHILDTYPE_APPEND. */ struct { /** The filename. */ char *pszFilename; /** How much to append. */ size_t cbAppend; /** What to append. */ char *pszAppend; /** Whether to truncate the file. */ int fTruncate; } Append; /** Data for WINCHILDTYPE_SUBMIT. */ struct { /** The event we're to wait on (hooked up to a pipe) */ HANDLE hEvent; /** Parameter for the cleanup callback. */ void *pvSubmitWorker; /** Standard output catching pipe. Optional. */ PWINCCWPIPE pStdOut; /** Standard error catching pipe. Optional. */ PWINCCWPIPE pStdErr; } Submit; /** Data for WINCHILDTYPE_REDIRECT. */ struct { /** Child process handle. */ HANDLE hProcess; } Redirect; } u; } WINCHILD; /** WINCHILD::uMagic value. */ #define WINCHILD_MAGIC 0xbabebabeU /** * Data for a windows childcare worker thread. * * We use one worker thread per child, reusing the threads when possible. * * This setup helps avoid the 64-bit handle with the WaitForMultipleObject API. * * It also helps using all CPUs on systems with more than one CPU group * (typically systems with more than 64 CPU threads or/and multiple sockets, or * special configs). * * This helps facilitates using pipes for collecting output child rather * than temporary files. Pipes doesn't involve NTFS and can easily be reused. * * Finally, kBuild specific, this allows running kmkbuiltin_xxxx commands in * threads. */ typedef struct WINCHILDCAREWORKER { /** Magic / eyecatcher (WINCHILDCAREWORKER_MAGIC). */ ULONG uMagic; /** The worker index. */ unsigned int idxWorker; /** The processor group for this worker. */ unsigned int iProcessorGroup; /** The thread ID. */ unsigned int tid; /** The thread handle. */ HANDLE hThread; /** The event the thread is idling on. */ HANDLE hEvtIdle; /** The pipe catching standard output from a child. */ PWINCCWPIPE pStdOut; /** The pipe catching standard error from a child. */ PWINCCWPIPE pStdErr; /** Pointer to the current child. */ PWINCHILD volatile pCurChild; /** List of children pending execution on this worker. * This is updated atomitically just like g_pTailCompletedChildren. */ PWINCHILD volatile pTailTodoChildren; /** TRUE if idle, FALSE if not. */ long volatile fIdle; } WINCHILDCAREWORKER; /** WINCHILD::uMagic value. */ #define WINCHILDCAREWORKER_MAGIC 0xdad0dad0U /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ /** Whether it's initialized or not. */ static BOOL g_fInitialized = FALSE; /** Set when we're shutting down everything. */ static BOOL volatile g_fShutdown = FALSE; /** Event used to wait for children. */ static HANDLE g_hEvtWaitChildren = INVALID_HANDLE_VALUE; /** Number of childcare workers currently in g_papChildCareworkers. */ static unsigned g_cChildCareworkers = 0; /** Maximum number of childcare workers in g_papChildCareworkers. */ static unsigned g_cChildCareworkersMax = 0; /** Pointer to childcare workers. */ static PWINCHILDCAREWORKER *g_papChildCareworkers = NULL; /** The processor group allocator state. */ static MKWINCHILDCPUGROUPALLOCSTATE g_ProcessorGroupAllocator; /** Number of processor groups in the system. */ static unsigned g_cProcessorGroups = 1; /** Array detailing how many active processors there are in each group. */ static unsigned const *g_pacProcessorsInGroup = &g_cProcessorGroups; /** Info from the GetLogicalProcessorInformationEx call - can be NULL. */ static GROUP_RELATIONSHIP const *g_pGroupInfo = NULL; /** Kernel32!GetActiveProcessorGroupCount */ static WORD (WINAPI *g_pfnGetActiveProcessorGroupCount)(VOID); /** Kernel32!GetActiveProcessorCount */ static DWORD (WINAPI *g_pfnGetActiveProcessorCount)(WORD); /** Kernel32!GetLogicalProcessorInformationEx */ static DWORD (WINAPI *g_pfnGetLogicalProcessorInformationEx)(LOGICAL_PROCESSOR_RELATIONSHIP, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD); /** Kernel32!SetThreadGroupAffinity */ static BOOL (WINAPI *g_pfnSetThreadGroupAffinity)(HANDLE, CONST GROUP_AFFINITY *, GROUP_AFFINITY *); /** Kernel32!SetThreadSelectedCpuSetMasks (windows 11+). */ static BOOL (WINAPI *g_pfnSetThreadSelectedCpuSetMasks)(HANDLE, PGROUP_AFFINITY, USHORT); /** Kernel32!SetProcessDefaultCpuSetMasks (windows 11+). */ static BOOL (WINAPI *g_pfnSetProcessDefaultCpuSetMasks)(HANDLE, PGROUP_AFFINITY, USHORT); /** NTDLL!NtQueryInformationProcess */ static NTSTATUS (NTAPI *g_pfnNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); /** Set if the windows host is 64-bit. */ static BOOL g_f64BitHost = (K_ARCH_BITS == 64); /** Windows version info. * @note Putting this before the volatile stuff, hoping to keep it in a * different cache line than the static bits above. */ static OSVERSIONINFOA g_VersionInfo = { sizeof(g_VersionInfo), 4, 0, 1381, VER_PLATFORM_WIN32_NT, {0} }; /** Children that has been completed. * This is updated atomically, pushing completed children in LIFO fashion * (thus 'tail'), then hitting g_hEvtWaitChildren if head. */ static PWINCHILD volatile g_pTailCompletedChildren = NULL; /** Number of idle pending children. * This is updated before g_hEvtWaitChildren is signalled. */ static unsigned volatile g_cPendingChildren = 0; /** Number of idle childcare worker threads. */ static unsigned volatile g_cIdleChildcareWorkers = 0; /** Index of the last idle child careworker (just a hint). */ static unsigned volatile g_idxLastChildcareWorker = 0; #ifdef WITH_RW_LOCK /** RW lock for serializing kmkbuiltin_redirect and CreateProcess. */ static SRWLOCK g_RWLock; #endif /** The job object for this make instance, if we created/opened one. */ static HANDLE g_hJob = NULL; /********************************************************************************************************************************* * Internal Functions * *********************************************************************************************************************************/ static void mkWinChildInitJobObjectAssociation(void); #if K_ARCH_BITS == 32 && !defined(_InterlockedCompareExchangePointer) /** _InterlockedCompareExchangePointer is missing? (VS2010) */ K_INLINE void *_InterlockedCompareExchangePointer(void * volatile *ppvDst, void *pvNew, void *pvOld) { return (void *)_InterlockedCompareExchange((long volatile *)ppvDst, (intptr_t)pvNew, (intptr_t)pvOld); } #endif /** * Initializes the windows child module. * * @param cJobSlots The number of job slots. */ void MkWinChildInit(unsigned int cJobSlots) { HMODULE hmod; /* * Figure out how many childcare workers first. */ static unsigned int const s_cMaxWorkers = 4096; unsigned cWorkers; if (cJobSlots >= 1 && cJobSlots < s_cMaxWorkers) cWorkers = cJobSlots; else cWorkers = s_cMaxWorkers; /* * Allocate the array and the child completed event object. */ g_papChildCareworkers = (PWINCHILDCAREWORKER *)xcalloc(cWorkers * sizeof(g_papChildCareworkers[0])); g_cChildCareworkersMax = cWorkers; g_hEvtWaitChildren = CreateEvent(NULL, FALSE /*fManualReset*/, FALSE /*fInitialState*/, NULL /*pszName*/); if (!g_hEvtWaitChildren) fatal(NILF, INTSTR_LENGTH, _("MkWinChildInit: CreateEvent failed: %u"), GetLastError()); /* * NTDLL imports that we need. */ hmod = GetModuleHandleA("NTDLL.DLL"); *(FARPROC *)&g_pfnNtQueryInformationProcess = GetProcAddress(hmod, "NtQueryInformationProcess"); if (!g_pfnNtQueryInformationProcess) fatal(NILF, 0, _("MkWinChildInit: NtQueryInformationProcess not found")); #if K_ARCH_BITS == 32 /* * Initialize g_f64BitHost. */ if (!IsWow64Process(GetCurrentProcess(), &g_f64BitHost)) fatal(NILF, INTSTR_LENGTH, _("MkWinChildInit: IsWow64Process failed: %u"), GetLastError()); #elif K_ARCH_BITS == 64 assert(g_f64BitHost); #else # error "K_ARCH_BITS is bad/missing" #endif /* * Figure out how many processor groups there are. * For that we need to first figure the windows version. */ if (!GetVersionExA(&g_VersionInfo)) { DWORD uRawVer = GetVersion(); g_VersionInfo.dwMajorVersion = uRawVer & 0xff; g_VersionInfo.dwMinorVersion = (uRawVer >> 8) & 0xff; g_VersionInfo.dwBuildNumber = (uRawVer >> 16) & 0x7fff; } if (g_VersionInfo.dwMajorVersion >= 6) { hmod = GetModuleHandleA("KERNEL32.DLL"); *(FARPROC *)&g_pfnGetActiveProcessorGroupCount = GetProcAddress(hmod, "GetActiveProcessorGroupCount"); *(FARPROC *)&g_pfnGetActiveProcessorCount = GetProcAddress(hmod, "GetActiveProcessorCount"); *(FARPROC *)&g_pfnSetThreadGroupAffinity = GetProcAddress(hmod, "SetThreadGroupAffinity"); *(FARPROC *)&g_pfnGetLogicalProcessorInformationEx = GetProcAddress(hmod, "GetLogicalProcessorInformationEx"); *(FARPROC *)&g_pfnSetThreadSelectedCpuSetMasks = GetProcAddress(hmod, "SetThreadSelectedCpuSetMasks"); /* W11 */ *(FARPROC *)&g_pfnSetProcessDefaultCpuSetMasks = GetProcAddress(hmod, "SetProcessDefaultCpuSetMasks"); /* W11 */ if ( g_pfnSetThreadGroupAffinity && g_pfnGetActiveProcessorCount && g_pfnGetActiveProcessorGroupCount && g_pfnGetLogicalProcessorInformationEx) { unsigned int *pacProcessorsInGroup; unsigned iGroup; g_cProcessorGroups = g_pfnGetActiveProcessorGroupCount(); if (g_cProcessorGroups == 0) g_cProcessorGroups = 1; pacProcessorsInGroup = (unsigned int *)xmalloc(sizeof(g_pacProcessorsInGroup[0]) * g_cProcessorGroups); g_pacProcessorsInGroup = pacProcessorsInGroup; for (iGroup = 0; iGroup < g_cProcessorGroups; iGroup++) pacProcessorsInGroup[iGroup] = g_pfnGetActiveProcessorCount(iGroup); /* Get active process group affinity masks so we can set them correctly. */ { DWORD cbNeeded = cbNeeded = offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group) + offsetof(GROUP_RELATIONSHIP, GroupInfo) + sizeof(PROCESSOR_GROUP_INFO) * (g_cProcessorGroups + 4); PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX pInfo = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)xcalloc(cbNeeded); BOOL fRet = g_pfnGetLogicalProcessorInformationEx(RelationGroup, pInfo, &cbNeeded); if (!fRet && GetLastError() == ERROR_BUFFER_OVERFLOW) { free(pInfo); pInfo = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)xcalloc(cbNeeded); fRet = g_pfnGetLogicalProcessorInformationEx(RelationGroup, pInfo, &cbNeeded); } if ( fRet && pInfo->Group.ActiveGroupCount > 0 && pInfo->Group.ActiveGroupCount <= pInfo->Group.MaximumGroupCount) { g_pGroupInfo = &pInfo->Group; /* leaked */ pInfo = NULL; } else free(pInfo); } /* Iff this is windows 11 or later, the default policy should be that threads can be scheduled in any CPU group, so reset any prior crap to make sure this remains the case for us and our children. This means we can skip g_pfnSetThreadGroupAffinity the calls later. */ if (g_pfnSetProcessDefaultCpuSetMasks) g_pfnSetProcessDefaultCpuSetMasks(GetCurrentProcess(), NULL, 0); if (g_pfnSetThreadSelectedCpuSetMasks) g_pfnSetThreadSelectedCpuSetMasks(GetCurrentThread(), NULL, 0); MkWinChildInitCpuGroupAllocator(&g_ProcessorGroupAllocator); } else { g_pfnSetThreadGroupAffinity = NULL; g_pfnGetActiveProcessorCount = NULL; g_pfnGetActiveProcessorGroupCount = NULL; g_pfnGetLogicalProcessorInformationEx = NULL; } } #ifdef WITH_RW_LOCK /* * For serializing with standard file handle manipulation (kmkbuiltin_redirect). */ InitializeSRWLock(&g_RWLock); #endif /* * Associate with a job object. */ mkWinChildInitJobObjectAssociation(); /* * This is dead code that was thought to fix a problem observed doing * `tcc.exe /c "kmk |& tee bld.log"` and leading to a crash in cl.exe * when spawned with fInheritHandles = FALSE, see hStdErr=NULL in the * child. However, it turns out this was probably caused by not clearing * the CRT file descriptor and handle table in the startup info. * Leaving the code here in case it comes in handy after all. */ #if 0 { struct { DWORD uStdHandle; HANDLE hHandle; } aHandles[3] = { { STD_INPUT_HANDLE, NULL }, { STD_OUTPUT_HANDLE, NULL }, { STD_ERROR_HANDLE, NULL } }; int i; for (i = 0; i < 3; i++) aHandles[i].hHandle = GetStdHandle(aHandles[i].uStdHandle); for (i = 0; i < 3; i++) if ( aHandles[i].hHandle == NULL || aHandles[i].hHandle == INVALID_HANDLE_VALUE) { int fd = open("nul", _O_RDWR); if (fd >= 0) { if (_dup2(fd, i) >= 0) { assert((HANDLE)_get_osfhandle(i) != aHandles[i].hHandle); assert((HANDLE)_get_osfhandle(i) == GetStdHandle(aHandles[i].uStdHandle)); } else ONNNS(fatal, NILF, "_dup2(%d('nul'), %d) failed: %u (%s)", fd, i, errno, strerror(errno)); if (fd != i) close(fd); } else ONNS(fatal, NILF, "open(nul,RW) failed: %u (%s)", i, errno, strerror(errno)); } else { int j; for (j = i + 1; j < 3; j++) if (aHandles[j].hHandle == aHandles[i].hHandle) { int fd = _dup(j); if (fd >= 0) { if (_dup2(fd, j) >= 0) { aHandles[j].hHandle = (HANDLE)_get_osfhandle(j); assert(aHandles[j].hHandle != aHandles[i].hHandle); assert(aHandles[j].hHandle == GetStdHandle(aHandles[j].uStdHandle)); } else ONNNS(fatal, NILF, "_dup2(%d, %d) failed: %u (%s)", fd, j, errno, strerror(errno)); if (fd != j) close(fd); } else ONNS(fatal, NILF, "_dup(%d) failed: %u (%s)", j, errno, strerror(errno)); } } } #endif } /** * Create or open a job object for this make instance and its children. * * Depending on the --job-object=mode value, we typically create/open a job * object here if we're the root make instance. The job object is then * typically configured to kill all remaining processes when the root make * terminates, so that there aren't any stuck processes around messing up * subsequent builds. This is very handy on build servers. * * If we're it no-kill mode, the job object is pretty pointless for manual * cleanup as the job object becomes invisible (or something) when the last * handle to it closes, i.e. g_hJob. On windows 8 and later it looks * like any orphaned children are immediately assigned to the parent job * object. Too bad for kmk_kill and such. * * win_job_object_mode values: login, root, each, none */ static void mkWinChildInitJobObjectAssociation(void) { BOOL fCreate = TRUE; char szJobName[128]; const char *pszJobName = win_job_object_name; /* Skip if disabled. */ if (strcmp(win_job_object_mode, "none") == 0) return; /* Skip if not root make instance, unless we're having one job object per make instance. */ if ( makelevel != 0 && strcmp(win_job_object_mode, "each") != 0) return; /* Format the the default job object name if --job-object-name wasn't given. */ if (!pszJobName || *pszJobName == '\0') { pszJobName = szJobName; if (strcmp(win_job_object_mode, "login") == 0) { /* Use the AuthenticationId like mspdbsrv.exe does. */ HANDLE hToken; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { TOKEN_STATISTICS TokenStats; DWORD cbRet = 0; memset(&TokenStats, 0, sizeof(TokenStats)); if (GetTokenInformation(hToken, TokenStatistics, &TokenStats, sizeof(TokenStats), &cbRet)) snprintf(szJobName, sizeof(szJobName), "kmk-job-obj-login-%08x.%08x", (unsigned)TokenStats.AuthenticationId.HighPart, (unsigned)TokenStats.AuthenticationId.LowPart); else { ONN(message, 0, _("GetTokenInformation failed: %u (cbRet=%u)"), GetLastError(), cbRet); return; } CloseHandle(hToken); } else { ON(message, 0, _("OpenProcessToken failed: %u"), GetLastError()); return; } } else { SYSTEMTIME Now = {0}; GetSystemTime(&Now); snprintf(szJobName, sizeof(szJobName), "kmk-job-obj-%04u-%02u-%02uT%02u-%02u-%02uZ%u", Now.wYear, Now.wMonth, Now.wDay, Now.wHour, Now.wMinute, Now.wSecond, getpid()); } } /* In login mode and when given a job object name, we try open it first. */ if ( win_job_object_name || strcmp(win_job_object_mode, "login") == 0) { g_hJob = OpenJobObjectA(JOB_OBJECT_ASSIGN_PROCESS, win_job_object_no_kill /*bInheritHandle*/, pszJobName); if (g_hJob) fCreate = FALSE; else { DWORD dwErr = GetLastError(); if (dwErr != ERROR_PATH_NOT_FOUND && dwErr != ERROR_FILE_NOT_FOUND) { OSN(message, 0, _("OpenJobObjectA(,,%s) failed: %u"), pszJobName, GetLastError()); return; } } } if (fCreate) { SECURITY_ATTRIBUTES SecAttr = { sizeof(SecAttr), NULL, TRUE /*bInheritHandle*/ }; g_hJob = CreateJobObjectA(win_job_object_no_kill ? &SecAttr : NULL, pszJobName); if (g_hJob) { /* We need to set the BREAKAWAY_OK flag, as we don't want make CreateProcess fail if someone tries to break way. Also set KILL_ON_JOB_CLOSE unless --job-object-no-kill is given. */ JOBOBJECT_EXTENDED_LIMIT_INFORMATION Info; DWORD cbActual = 0; memset(&Info, 0, sizeof(Info)); if (QueryInformationJobObject(g_hJob, JobObjectExtendedLimitInformation, &Info, sizeof(Info), &cbActual)) { Info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_BREAKAWAY_OK; if (!win_job_object_no_kill) Info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; else Info.BasicLimitInformation.LimitFlags &= ~JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; if (!SetInformationJobObject(g_hJob, JobObjectExtendedLimitInformation, &Info, sizeof(Info))) OSSN(message, 0, _("SetInformationJobObject(%s,JobObjectExtendedLimitInformation,{%s},) failed: %u"), pszJobName, win_job_object_mode, GetLastError()); } else OSN(message, 0, _("QueryInformationJobObject(%s,JobObjectExtendedLimitInformation,,,) failed: %u"), pszJobName, GetLastError()); } else { OSN(message, 0, _("CreateJobObjectA(NULL,%s) failed: %u"), pszJobName, GetLastError()); return; } } /* Make it our job object. */ if (!(AssignProcessToJobObject(g_hJob, GetCurrentProcess()))) OSN(message, 0, _("AssignProcessToJobObject(%s, me) failed: %u"), pszJobName, GetLastError()); } /** * Used by mkWinChildcareWorkerThread() and MkWinChildWait() to get the head * child from a lifo (g_pTailCompletedChildren, pTailTodoChildren). * * @returns Head child. * @param ppTail Pointer to the child variable. * @param pChild Tail child. */ static PWINCHILD mkWinChildDequeFromLifo(PWINCHILD volatile *ppTail, PWINCHILD pChild) { if (pChild->pNext) { PWINCHILD pPrev; do { pPrev = pChild; pChild = pChild->pNext; } while (pChild->pNext); pPrev->pNext = NULL; } else { PWINCHILD const pWantedChild = pChild; pChild = _InterlockedCompareExchangePointer(ppTail, NULL, pWantedChild); if (pChild != pWantedChild) { PWINCHILD pPrev; do { pPrev = pChild; pChild = pChild->pNext; } while (pChild->pNext); pPrev->pNext = NULL; assert(pChild == pWantedChild); } } return pChild; } /** * Output error message while running on a worker thread. * * @returns -1 * @param pWorker The calling worker. Mainly for getting the * current child and its stderr output unit. Pass * NULL if the output should go thru the child * stderr buffering. * @param iType The error type: * - 0: more of a info directly to stdout, * - 1: child related error, * - 2: child related error for immedate release. * @param pszFormat The message format string. * @param ... Argument for the message. */ static int MkWinChildError(PWINCHILDCAREWORKER pWorker, int iType, const char *pszFormat, ...) { /* * Format the message into stack buffer. */ char szMsg[4096]; int cchMsg; int cchPrefix; va_list va; /* Compose the prefix, being paranoid about it not exceeding the buffer in any way. */ const char *pszInfix = iType == 0 ? "info: " : "error: "; const char *pszProgram = program; if (strlen(pszProgram) > 80) { #ifdef KMK pszProgram = "kmk"; #else pszProgram = "gnumake"; #endif } if (makelevel == 0) cchPrefix = snprintf(szMsg, sizeof(szMsg) / 2, "%s: %s", pszProgram, pszInfix); else cchPrefix = snprintf(szMsg, sizeof(szMsg) / 2, "%s[%u]: %s", pszProgram, makelevel, pszInfix); assert(cchPrefix < sizeof(szMsg) / 2 && cchPrefix > 0); /* Format the user specified message. */ va_start(va, pszFormat); cchMsg = vsnprintf(&szMsg[cchPrefix], sizeof(szMsg) - 2 - cchPrefix, pszFormat, va); va_end(va); szMsg[sizeof(szMsg) - 2] = '\0'; cchMsg = strlen(szMsg); /* Make sure there's a newline at the end of it (we reserved space for that). */ if (cchMsg <= 0 || szMsg[cchMsg - 1] != '\n') { szMsg[cchMsg++] = '\n'; szMsg[cchMsg] = '\0'; } #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY /* * Try use the stderr of the current child of the worker. */ if ( iType != 0 && iType != 3 && pWorker) { PWINCHILD pChild = pWorker->pCurChild; if (pChild) { struct child *pMkChild = pChild->pMkChild; if (pMkChild) { output_write_text(&pMkChild->output, 1 /*is_err*/, szMsg, cchMsg); return -1; } } } #endif /* * Fallback to writing directly to stderr. */ maybe_con_fwrite(szMsg, cchMsg, 1, iType == 0 ? stdout : stderr); return -1; } /** * Duplicates the given UTF-16 string. * * @returns 0 * @param pwszSrc The UTF-16 string to duplicate. * @param cwcSrc Length, may include the terminator. * @param ppwszDst Where to return the duplicate. */ static int mkWinChildDuplicateUtf16String(const WCHAR *pwszSrc, size_t cwcSrc, WCHAR **ppwszDst) { size_t cb = sizeof(WCHAR) * cwcSrc; if (cwcSrc > 0 && pwszSrc[cwcSrc - 1] == L'\0') *ppwszDst = (WCHAR *)memcpy(xmalloc(cb), pwszSrc, cb); else { WCHAR *pwszDst = (WCHAR *)xmalloc(cb + sizeof(WCHAR)); memcpy(pwszDst, pwszSrc, cb); pwszDst[cwcSrc] = L'\0'; *ppwszDst = pwszDst; } return 0; } /** * Used to flush data we're read but not yet written at the termination of a * process. * * @param pChild The child. * @param pPipe The pipe. */ static void mkWinChildcareWorkerFlushUnwritten(PWINCHILD pChild, PWINCCWPIPE pPipe) { DWORD cbUnwritten = pPipe->offPendingRead - pPipe->cbWritten; assert(pPipe->cbWritten <= pPipe->cbBuffer - 16); assert(pPipe->offPendingRead <= pPipe->cbBuffer - 16); if (cbUnwritten) { #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY if (pChild && pChild->pMkChild) { output_write_bin(&pChild->pMkChild->output, pPipe->iWhich == 2, &pPipe->pbBuffer[pPipe->cbWritten], cbUnwritten); pPipe->cbWritten += cbUnwritten; } else #endif { DWORD cbWritten = 0; if (WriteFile(GetStdHandle(pPipe->iWhich == 1 ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE), &pPipe->pbBuffer[pPipe->cbWritten], cbUnwritten, &cbWritten, NULL)) pPipe->cbWritten += cbWritten <= cbUnwritten ? cbWritten : cbUnwritten; /* paranoia */ } pPipe->fHaveWrittenOut = TRUE; } } /** * This logic mirrors kwSandboxConsoleFlushAll. * * @returns TRUE if it looks like a CL.EXE source line, otherwise FALSE. * @param pPipe The pipe. * @param offStart The start of the output in the pipe buffer. * @param offEnd The end of the output in the pipe buffer. */ static BOOL mkWinChildcareWorkerIsClExeSourceLine(PWINCCWPIPE pPipe, DWORD offStart, DWORD offEnd) { if (offEnd < offStart + 2) return FALSE; if (offEnd - offStart > 80) return FALSE; if ( pPipe->pbBuffer[offEnd - 2] != '\r' || pPipe->pbBuffer[offEnd - 1] != '\n') return FALSE; offEnd -= 2; while (offEnd-- > offStart) { char ch = pPipe->pbBuffer[offEnd]; if (isalnum(ch) || ch == '.' || ch == ' ' || ch == '_' || ch == '-') { /* likely */ } else return FALSE; } return TRUE; } /** * Adds output to the given standard output for the child. * * There is no pending read when this function is called, so we're free to * reshuffle the buffer if desirable. * * @param pChild The child. Optional (kSubmit). * @param iWhich Which standard descriptor number. * @param cbNewData How much more output was caught. */ static void mkWinChildcareWorkerCaughtMoreOutput(PWINCHILD pChild, PWINCCWPIPE pPipe, DWORD cbNewData) { DWORD offStart = pPipe->cbWritten; assert(offStart <= pPipe->offPendingRead); assert(offStart <= pPipe->cbBuffer - 16); assert(pPipe->offPendingRead <= pPipe->cbBuffer - 16); if (cbNewData > 0) { DWORD offRest; /* Move offPendingRead ahead by cbRead. */ pPipe->offPendingRead += cbNewData; assert(pPipe->offPendingRead <= pPipe->cbBuffer); if (pPipe->offPendingRead > pPipe->cbBuffer) pPipe->offPendingRead = pPipe->cbBuffer; /* Locate the last newline in the buffer. */ offRest = pPipe->offPendingRead; while (offRest > offStart && pPipe->pbBuffer[offRest - 1] != '\n') offRest--; /* If none were found and we've less than 16 bytes left in the buffer, try find a word boundrary to flush on instead. */ if ( offRest <= offStart && pPipe->cbBuffer - pPipe->offPendingRead + offStart < 16) { offRest = pPipe->offPendingRead; while ( offRest > offStart && isalnum(pPipe->pbBuffer[offRest - 1])) offRest--; if (offRest == offStart) offRest = pPipe->offPendingRead; } /* If this is a potential CL.EXE process, we will keep the source filename unflushed and maybe discard it at the end. */ else if ( pChild && pChild->fProbableClExe && pPipe->iWhich == 1 && offRest == pPipe->offPendingRead && mkWinChildcareWorkerIsClExeSourceLine(pPipe, offStart, offRest)) offRest = offStart; if (offRest > offStart) { /* Write out offStart..offRest. */ DWORD cbToWrite = offRest - offStart; #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY if (pChild && pChild->pMkChild) { output_write_bin(&pChild->pMkChild->output, pPipe->iWhich == 2, &pPipe->pbBuffer[offStart], cbToWrite); offStart += cbToWrite; pPipe->cbWritten = offStart; } else #endif { DWORD cbWritten = 0; if (WriteFile(GetStdHandle(pPipe->iWhich == 1 ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE), &pPipe->pbBuffer[offStart], cbToWrite, &cbWritten, NULL)) { offStart += cbWritten <= cbToWrite ? cbWritten : cbToWrite; /* paranoia */ pPipe->cbWritten = offStart; } } pPipe->fHaveWrittenOut = TRUE; } } /* Shuffle the data to the front of the buffer. */ if (offStart > 0) { DWORD cbUnwritten = pPipe->offPendingRead - offStart; if (cbUnwritten > 0) memmove(pPipe->pbBuffer, &pPipe->pbBuffer[offStart], cbUnwritten); pPipe->offPendingRead -= pPipe->cbWritten; pPipe->cbWritten = 0; } } /** * Catches output from the given pipe. * * @param pChild The child. Optional (kSubmit). * @param pPipe The pipe. * @param fDraining Set if we're draining the pipe after the process * terminated. */ static void mkWinChildcareWorkerCatchOutput(PWINCHILD pChild, PWINCCWPIPE pPipe, BOOL fDraining) { /* * Deal with already pending read. */ if (pPipe->fReadPending) { DWORD cbRead = 0; if (GetOverlappedResult(pPipe->hPipeMine, &pPipe->Overlapped, &cbRead, !fDraining)) { mkWinChildcareWorkerCaughtMoreOutput(pChild, pPipe, cbRead); pPipe->fReadPending = FALSE; } else if (fDraining && GetLastError() == ERROR_IO_INCOMPLETE) return; else { MkWinChildError(pChild ? pChild->pWorker : NULL, 2, "GetOverlappedResult failed: %u\n", GetLastError()); pPipe->fReadPending = FALSE; if (fDraining) return; } } /* * Read data till one becomes pending. */ for (;;) { DWORD cbRead; memset(&pPipe->Overlapped, 0, sizeof(pPipe->Overlapped)); pPipe->Overlapped.hEvent = pPipe->hEvent; ResetEvent(pPipe->hEvent); assert(pPipe->offPendingRead < pPipe->cbBuffer); SetLastError(0); cbRead = 0; if (!ReadFile(pPipe->hPipeMine, &pPipe->pbBuffer[pPipe->offPendingRead], pPipe->cbBuffer - pPipe->offPendingRead, &cbRead, &pPipe->Overlapped)) { DWORD dwErr = GetLastError(); if (dwErr == ERROR_IO_PENDING) pPipe->fReadPending = TRUE; else MkWinChildError(pChild ? pChild->pWorker : NULL, 2, "ReadFile failed on standard %s: %u\n", pPipe->iWhich == 1 ? "output" : "error", GetLastError()); return; } mkWinChildcareWorkerCaughtMoreOutput(pChild, pPipe, cbRead); } } /** * Makes sure the output pipes are drained and pushed to output. * * @param pChild The child. Optional (kSubmit). * @param pStdOut The standard output pipe structure. * @param pStdErr The standard error pipe structure. */ void MkWinChildcareWorkerDrainPipes(PWINCHILD pChild, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr) { mkWinChildcareWorkerCatchOutput(pChild, pStdOut, TRUE /*fDraining*/); mkWinChildcareWorkerCatchOutput(pChild, pStdErr, TRUE /*fDraining*/); /* Drop lone 'source.c' line from CL.exe, but only if no other output at all. */ if ( pChild && pChild->fProbableClExe && !pStdOut->fHaveWrittenOut && !pStdErr->fHaveWrittenOut && pStdErr->cbWritten == pStdErr->offPendingRead && pStdOut->cbWritten < pStdOut->offPendingRead && mkWinChildcareWorkerIsClExeSourceLine(pStdOut, pStdOut->cbWritten, pStdOut->offPendingRead)) { if (!pStdOut->fReadPending) pStdOut->cbWritten = pStdOut->offPendingRead = 0; else pStdOut->cbWritten = pStdOut->offPendingRead; } else { mkWinChildcareWorkerFlushUnwritten(pChild, pStdOut); mkWinChildcareWorkerFlushUnwritten(pChild, pStdErr); } } /** * Commmon worker for waiting on a child process and retrieving the exit code. * * @returns Child exit code. * @param pWorker The worker. * @param pChild The child. * @param hProcess The process handle. * @param pwszJob The job name. * @param fCatchOutput Set if we need to work the output pipes * associated with the worker. */ static int mkWinChildcareWorkerWaitForProcess(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild, HANDLE hProcess, WCHAR const *pwszJob, BOOL fCatchOutput) { DWORD const msStart = GetTickCount(); DWORD msNextMsg = msStart + 15000; /* Reset the written indicators on the pipes before we start loop. */ pWorker->pStdOut->fHaveWrittenOut = FALSE; pWorker->pStdErr->fHaveWrittenOut = FALSE; for (;;) { /* * Do the waiting and output catching. */ DWORD dwStatus; if (!fCatchOutput) dwStatus = WaitForSingleObject(hProcess, 15001 /*ms*/); else { HANDLE ahHandles[3] = { hProcess, pWorker->pStdOut->hEvent, pWorker->pStdErr->hEvent }; dwStatus = WaitForMultipleObjects(3, ahHandles, FALSE /*fWaitAll*/, 1000 /*ms*/); if (dwStatus == WAIT_OBJECT_0 + 1) mkWinChildcareWorkerCatchOutput(pChild, pWorker->pStdOut, FALSE /*fDraining*/); else if (dwStatus == WAIT_OBJECT_0 + 2) mkWinChildcareWorkerCatchOutput(pChild, pWorker->pStdErr, FALSE /*fDraining*/); } assert(dwStatus != WAIT_FAILED); /* * Get the exit code and return if the process was signalled as done. */ if (dwStatus == WAIT_OBJECT_0) { DWORD dwExitCode = -42; if (GetExitCodeProcess(hProcess, &dwExitCode)) { pChild->iExitCode = (int)dwExitCode; if (fCatchOutput) MkWinChildcareWorkerDrainPipes(pChild, pWorker->pStdOut, pWorker->pStdErr); return dwExitCode; } } /* * Loop again if just a timeout or pending output? * Put out a message every 15 or 30 seconds if the job takes a while. */ else if ( dwStatus == WAIT_TIMEOUT || dwStatus == WAIT_OBJECT_0 + 1 || dwStatus == WAIT_OBJECT_0 + 2 || dwStatus == WAIT_IO_COMPLETION) { DWORD msNow = GetTickCount(); if (msNow >= msNextMsg) { if ( !pChild->pMkChild || !pChild->pMkChild->recursive) /* ignore make recursions */ { if ( !pChild->pMkChild || !pChild->pMkChild->file || !pChild->pMkChild->file->name) MkWinChildError(NULL, 0, "Pid %u ('%ls') still running after %u seconds\n", GetProcessId(hProcess), pwszJob, (msNow - msStart) / 1000); else MkWinChildError(NULL, 0, "Target '%s' (pid %u) still running after %u seconds\n", pChild->pMkChild->file->name, GetProcessId(hProcess), (msNow - msStart) / 1000); } /* After 15s, 30s, 60s, 120s, 180s, ... */ if (msNextMsg == msStart + 15000) msNextMsg += 15000; else msNextMsg += 30000; } continue; } /* Something failed. */ pChild->iExitCode = GetLastError(); if (pChild->iExitCode == 0) pChild->iExitCode = -4242; return pChild->iExitCode; } } /** * Closes standard handles that need closing before destruction. * * @param pChild The child (WINCHILDTYPE_PROCESS). */ static void mkWinChildcareWorkerCloseStandardHandles(PWINCHILD pChild) { if ( pChild->u.Process.fCloseStdOut && pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE) { CloseHandle(pChild->u.Process.hStdOut); pChild->u.Process.hStdOut = INVALID_HANDLE_VALUE; pChild->u.Process.fCloseStdOut = FALSE; } if ( pChild->u.Process.fCloseStdErr && pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE) { CloseHandle(pChild->u.Process.hStdErr); pChild->u.Process.hStdErr = INVALID_HANDLE_VALUE; pChild->u.Process.fCloseStdErr = FALSE; } } /** * Does the actual process creation. * * @returns 0 if there is anything to wait on, otherwise non-zero windows error. * @param pWorker The childcare worker. * @param pChild The child. * @param pwszImageName The image path. * @param pwszCommandLine The command line. * @param pwszzEnvironment The enviornment block. */ static int mkWinChildcareWorkerCreateProcess(PWINCHILDCAREWORKER pWorker, WCHAR const *pwszImageName, WCHAR const *pwszCommandLine, WCHAR const *pwszzEnvironment, WCHAR const *pwszCwd, BOOL pafReplace[3], HANDLE pahChild[3], BOOL fCatchOutput, HANDLE *phProcess) { PROCESS_INFORMATION ProcInfo; STARTUPINFOW StartupInfo; DWORD fFlags = CREATE_UNICODE_ENVIRONMENT; BOOL const fHaveHandles = pafReplace[0] | pafReplace[1] | pafReplace[2]; BOOL fRet; DWORD dwErr; #ifdef KMK extern int process_priority; #endif #ifdef DEBUG_STDOUT_CLOSE_ISSUE my_check_stdout("mkWinChildcareWorkerCreateProcess/entry"); #endif /* * Populate startup info. * * Turns out we can get away without passing TRUE for the inherit handles * parameter to CreateProcess when we're not using STARTF_USESTDHANDLES. * At least on NT, which is all worth caring about at this point + context IMO. * * Not inherting the handles is a good thing because it means we won't * accidentally end up with a pipe handle or such intended for a different * child process, potentially causing the EOF/HUP event to be delayed. * * Since the present handle inhertiance requirements only involves standard * output and error, we'll never set the inherit handles flag and instead * do manual handle duplication and planting. */ memset(&StartupInfo, 0, sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); GetStartupInfoW(&StartupInfo); StartupInfo.lpReserved2 = 0; /* No CRT file handle + descriptor info possible, sorry. */ StartupInfo.cbReserved2 = 0; if ( !fHaveHandles && !fCatchOutput) StartupInfo.dwFlags &= ~STARTF_USESTDHANDLES; else { fFlags |= CREATE_SUSPENDED; StartupInfo.dwFlags &= ~STARTF_USESTDHANDLES; } /* * Flags. */ #ifdef KMK switch (process_priority) { case 1: fFlags |= CREATE_SUSPENDED | IDLE_PRIORITY_CLASS; break; case 2: fFlags |= CREATE_SUSPENDED | BELOW_NORMAL_PRIORITY_CLASS; break; case 3: fFlags |= CREATE_SUSPENDED | NORMAL_PRIORITY_CLASS; break; case 4: fFlags |= CREATE_SUSPENDED | HIGH_PRIORITY_CLASS; break; case 5: fFlags |= CREATE_SUSPENDED | REALTIME_PRIORITY_CLASS; break; } #endif if (g_cProcessorGroups > 1) fFlags |= CREATE_SUSPENDED; /* * Try create the process. */ DB(DB_JOBS, ("CreateProcessW(%ls, %ls,,, TRUE, %#x...)\n", pwszImageName, pwszCommandLine, fFlags)); memset(&ProcInfo, 0, sizeof(ProcInfo)); #ifdef WITH_RW_LOCK AcquireSRWLockShared(&g_RWLock); #endif fRet = CreateProcessW((WCHAR *)pwszImageName, (WCHAR *)pwszCommandLine, NULL /*pProcSecAttr*/, NULL /*pThreadSecAttr*/, FALSE /*fInheritHandles*/, fFlags, (WCHAR *)pwszzEnvironment, pwszCwd, &StartupInfo, &ProcInfo); dwErr = GetLastError(); #ifdef WITH_RW_LOCK ReleaseSRWLockShared(&g_RWLock); #endif if (fRet) *phProcess = ProcInfo.hProcess; else { MkWinChildError(pWorker, 1, "CreateProcess(%ls) failed: %u\n", pwszImageName, dwErr); return (int)dwErr; } /* * If the child is suspended, we've got some adjustment work to be done. */ dwErr = ERROR_SUCCESS; if (fFlags & CREATE_SUSPENDED) { /* * First do handle inhertiance as that's the most complicated. */ if (fHaveHandles || fCatchOutput) { char szErrMsg[128]; if (fCatchOutput) { if (!pafReplace[1]) { pafReplace[1] = TRUE; pahChild[1] = pWorker->pStdOut->hPipeChild; } if (!pafReplace[2]) { pafReplace[2] = TRUE; pahChild[2] = pWorker->pStdErr->hPipeChild; } } dwErr = nt_child_inject_standard_handles(ProcInfo.hProcess, pafReplace, pahChild, szErrMsg, sizeof(szErrMsg)); if (dwErr != 0) MkWinChildError(pWorker, 1, "%s\n", szErrMsg); } /* * Assign processor group (ignore failure). */ #ifdef MKWINCHILD_DO_SET_PROCESSOR_GROUP if (g_cProcessorGroups > 1 && !g_pfnSetProcessDefaultCpuSetMasks) { GROUP_AFFINITY Affinity = { 0, pWorker->iProcessorGroup, { 0, 0, 0 } }; if (g_pGroupInfo && pWorker->iProcessorGroup < g_pGroupInfo->ActiveGroupCount) Affinity.Mask = g_pGroupInfo->GroupInfo[pWorker->iProcessorGroup].ActiveProcessorMask; fRet = g_pfnSetThreadGroupAffinity(ProcInfo.hThread, &Affinity, NULL); assert(fRet); } #endif #ifdef KMK /* * Set priority (ignore failure). */ switch (process_priority) { case 1: fRet = SetThreadPriority(ProcInfo.hThread, THREAD_PRIORITY_IDLE); break; case 2: fRet = SetThreadPriority(ProcInfo.hThread, THREAD_PRIORITY_BELOW_NORMAL); break; case 3: fRet = SetThreadPriority(ProcInfo.hThread, THREAD_PRIORITY_NORMAL); break; case 4: fRet = SetThreadPriority(ProcInfo.hThread, THREAD_PRIORITY_HIGHEST); break; case 5: fRet = SetThreadPriority(ProcInfo.hThread, THREAD_PRIORITY_TIME_CRITICAL); break; default: fRet = TRUE; } assert(fRet); #endif /* * Inject the job object if we're in a non-killing mode, to postpone * the closing of the job object and maybe make it more useful. */ if (win_job_object_no_kill && g_hJob) { HANDLE hWhatever = INVALID_HANDLE_VALUE; DuplicateHandle(GetCurrentProcess(), g_hJob, ProcInfo.hProcess, &hWhatever, GENERIC_ALL, TRUE /*bInheritHandle*/, DUPLICATE_SAME_ACCESS); } /* * Resume the thread if the adjustments succeeded, otherwise kill it. */ if (dwErr == ERROR_SUCCESS) { fRet = ResumeThread(ProcInfo.hThread); assert(fRet); if (!fRet) { dwErr = GetLastError(); MkWinChildError(pWorker, 1, "ResumeThread failed on child process: %u\n", dwErr); } } if (dwErr != ERROR_SUCCESS) TerminateProcess(ProcInfo.hProcess, dwErr); } /* * Close unnecessary handles and cache the image. */ CloseHandle(ProcInfo.hThread); kmk_cache_exec_image_w(pwszImageName); #ifdef DEBUG_STDOUT_CLOSE_ISSUE my_check_stdout("mkWinChildcareWorkerCreateProcess/tail"); #endif return 0; } /** * Converts a argument vector that has already been quoted correctly. * * The argument vector is typically the result of quote_argv(). * * @returns 0 on success, non-zero on failure. * @param pWorker The childcare worker. * @param papszArgs The argument vector to convert. * @param ppwszCommandLine Where to return the command line. */ static int mkWinChildcareWorkerConvertQuotedArgvToCommandline(PWINCHILDCAREWORKER pWorker, char **papszArgs, WCHAR **ppwszCommandLine) { WCHAR *pwszCmdLine; WCHAR *pwszDst; /* * Calc length the converted length. */ unsigned cwcNeeded = 1; unsigned i = 0; const char *pszSrc; while ((pszSrc = papszArgs[i]) != NULL) { int cwcThis = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, -1, NULL, 0); if (cwcThis > 0 || *pszSrc == '\0') cwcNeeded += cwcThis + 1; else { DWORD dwErr = GetLastError(); MkWinChildError(pWorker, 1, _("MultiByteToWideChar failed to convert argv[%u] (%s): %u\n"), i, pszSrc, dwErr); return dwErr; } i++; } /* * Allocate and do the conversion. */ pwszCmdLine = pwszDst = (WCHAR *)xmalloc(cwcNeeded * sizeof(WCHAR)); i = 0; while ((pszSrc = papszArgs[i]) != NULL) { int cwcThis; if (i > 0) { *pwszDst++ = ' '; cwcNeeded--; } cwcThis = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, -1, pwszDst, cwcNeeded); if (!cwcThis && *pszSrc != '\0') { DWORD dwErr = GetLastError(); MkWinChildError(pWorker, 1, _("MultiByteToWideChar failed to convert argv[%u] (%s): %u\n"), i, pszSrc, dwErr); free(pwszCmdLine); return dwErr; } if (cwcThis > 0 && pwszDst[cwcThis - 1] == '\0') cwcThis--; pwszDst += cwcThis; cwcNeeded -= cwcThis; i++; } *pwszDst++ = '\0'; *ppwszCommandLine = pwszCmdLine; return 0; } #define MKWCCWCMD_F_CYGWIN_SHELL 1 #define MKWCCWCMD_F_MKS_SHELL 2 #define MKWCCWCMD_F_HAVE_SH 4 #define MKWCCWCMD_F_HAVE_KASH_C 8 /**< kmk_ash -c "..." */ /* * @param pWorker The childcare worker if on one, otherwise NULL. */ static int mkWinChildcareWorkerConvertCommandline(PWINCHILDCAREWORKER pWorker, char **papszArgs, unsigned fFlags, WCHAR **ppwszCommandLine) { struct ARGINFO { size_t cchSrc; size_t cwcDst; /**< converted size w/o terminator. */ size_t cwcDstExtra : 24; /**< Only set with fSlowly. */ size_t fSlowly : 1; size_t fQuoteIt : 1; size_t fEndSlashes : 1; /**< if escapes needed for trailing backslashes. */ size_t fExtraSpace : 1; /**< if kash -c "" needs an extra space before the quote. */ } *paArgInfo; size_t cArgs; size_t i; size_t cwcNeeded; WCHAR *pwszDst; WCHAR *pwszCmdLine; /* * Count them first so we can allocate an info array of the stack. */ cArgs = 0; while (papszArgs[cArgs] != NULL) cArgs++; paArgInfo = (struct ARGINFO *)alloca(sizeof(paArgInfo[0]) * cArgs); /* * Preprocess them and calculate the exact command line length. */ cwcNeeded = 1; for (i = 0; i < cArgs; i++) { char *pszSrc = papszArgs[i]; size_t cchSrc = strlen(pszSrc); paArgInfo[i].cchSrc = cchSrc; if (cchSrc == 0) { /* empty needs quoting. */ paArgInfo[i].cwcDst = 2; paArgInfo[i].cwcDstExtra = 0; paArgInfo[i].fSlowly = 0; paArgInfo[i].fQuoteIt = 1; paArgInfo[i].fExtraSpace = 0; paArgInfo[i].fEndSlashes = 0; } else { const char *pszSpace = memchr(pszSrc, ' ', cchSrc); const char *pszTab = memchr(pszSrc, '\t', cchSrc); const char *pszDQuote = memchr(pszSrc, '"', cchSrc); const char *pszEscape = memchr(pszSrc, '\\', cchSrc); int cwcDst = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, cchSrc + 1, NULL, 0); if (cwcDst >= 0) --cwcDst; else { DWORD dwErr = GetLastError(); MkWinChildError(pWorker, 1, _("MultiByteToWideChar failed to convert argv[%u] (%s): %u\n"), i, pszSrc, dwErr); return dwErr; } #if 0 if (!pszSpace && !pszTab && !pszDQuote && !pszEscape) { /* no special handling needed. */ paArgInfo[i].cwcDst = cwcDst; paArgInfo[i].cwcDstExtra = 0; paArgInfo[i].fSlowly = 0; paArgInfo[i].fQuoteIt = 0; paArgInfo[i].fExtraSpace = 0; paArgInfo[i].fEndSlashes = 0; } else if (!pszDQuote && !pszEscape) { /* Just double quote it. */ paArgInfo[i].cwcDst = cwcDst + 2; paArgInfo[i].cwcDstExtra = 0; paArgInfo[i].fSlowly = 0; paArgInfo[i].fQuoteIt = 1; paArgInfo[i].fExtraSpace = 0; paArgInfo[i].fEndSlashes = 0; } else #endif { /* Complicated, need to scan the string to figure out what to do. */ size_t cwcDstExtra; int cBackslashes; char ch; paArgInfo[i].fQuoteIt = 0; paArgInfo[i].fSlowly = 1; paArgInfo[i].fExtraSpace = 0; paArgInfo[i].fEndSlashes = 0; cwcDstExtra = 0; cBackslashes = 0; while ((ch = *pszSrc++) != '\0') { switch (ch) { default: cBackslashes = 0; break; case '\\': cBackslashes++; break; case '"': if (fFlags & (MKWCCWCMD_F_CYGWIN_SHELL | MKWCCWCMD_F_MKS_SHELL)) cwcDstExtra += 1; /* just an extra '"' */ else cwcDstExtra += 1 + cBackslashes; /* extra '\\' for the '"' and for each preceeding slash. */ cBackslashes = 0; break; case ' ': case '\t': if (!paArgInfo[i].fQuoteIt) { paArgInfo[i].fQuoteIt = 1; cwcDstExtra += 2; } cBackslashes = 0; break; } } /* If we're quoting the argument and it ends with trailing '\\', it/they must be escaped. */ if ( cBackslashes > 0 && paArgInfo[i].fQuoteIt && !(fFlags & (MKWCCWCMD_F_CYGWIN_SHELL | MKWCCWCMD_F_MKS_SHELL))) { cwcDstExtra += cBackslashes; paArgInfo[i].fEndSlashes = 1; } paArgInfo[i].cwcDst = cwcDst + cwcDstExtra; paArgInfo[i].cwcDstExtra = cwcDstExtra; } } if ( (fFlags & MKWCCWCMD_F_HAVE_KASH_C) && paArgInfo[i].fQuoteIt) { paArgInfo[i].fExtraSpace = 1; paArgInfo[i].cwcDst++; paArgInfo[i].cwcDstExtra++; } cwcNeeded += (i != 0) + paArgInfo[i].cwcDst; } /* * Allocate the result buffer and do the actual conversion. */ pwszDst = pwszCmdLine = (WCHAR *)xmalloc(sizeof(WCHAR) * cwcNeeded); for (i = 0; i < cArgs; i++) { char *pszSrc = papszArgs[i]; size_t cwcDst = paArgInfo[i].cwcDst; if (i != 0) *pwszDst++ = L' '; if (paArgInfo[i].fQuoteIt) { *pwszDst++ = L'"'; cwcDst -= 2; } if (!paArgInfo[i].fSlowly) { int cwcDst2 = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, paArgInfo[i].cchSrc, pwszDst, cwcDst + 1); assert(cwcDst2 >= 0); pwszDst += cwcDst; } else { /* Do the conversion into the end of the output buffer, then move it up to where it should be char by char. */ int cBackslashes; size_t cwcLeft = paArgInfo[i].cwcDst - paArgInfo[i].cwcDstExtra; WCHAR volatile *pwchSlowSrc = pwszDst + paArgInfo[i].cwcDstExtra; WCHAR volatile *pwchSlowDst = pwszDst; int cwcDst2 = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, paArgInfo[i].cchSrc, (WCHAR *)pwchSlowSrc, cwcLeft + 1); assert(cwcDst2 >= 0); cBackslashes = 0; while (cwcLeft-- > 0) { WCHAR wcSrc = *pwchSlowSrc++; if (wcSrc != L'\\' && wcSrc != L'"') cBackslashes = 0; else if (wcSrc == L'\\') cBackslashes++; else if ( (fFlags & (MKWCCWCMD_F_CYGWIN_SHELL | MKWCCWCMD_F_HAVE_SH)) == (MKWCCWCMD_F_CYGWIN_SHELL | MKWCCWCMD_F_HAVE_SH)) { *pwchSlowDst++ = L'"'; /* cygwin: '"' instead of '\\', no escaped slashes. */ cBackslashes = 0; } else { if (!(fFlags & (MKWCCWCMD_F_CYGWIN_SHELL | MKWCCWCMD_F_MKS_SHELL))) cBackslashes += 1; /* one extra escape the '"' and one for each preceeding slash. */ while (cBackslashes > 0) { *pwchSlowDst++ = L'\\'; cBackslashes--; } } *pwchSlowDst++ = wcSrc; assert((uintptr_t)pwchSlowDst <= (uintptr_t)pwchSlowSrc); } if (paArgInfo[i].fEndSlashes) while (cBackslashes-- > 0) *pwchSlowDst++ = L'\\'; pwszDst += cwcDst; assert(pwszDst == (WCHAR *)pwchSlowDst); } if (paArgInfo[i].fExtraSpace) *pwszDst++ = L' '; if (paArgInfo[i].fQuoteIt) *pwszDst++ = L'"'; } *pwszDst = L'\0'; *ppwszCommandLine = pwszCmdLine; return 0; } static int mkWinChildcareWorkerConvertCommandlineWithShell(PWINCHILDCAREWORKER pWorker, const WCHAR *pwszShell, char **papszArgs, WCHAR **ppwszCommandLine) { MkWinChildError(pWorker, 1, "%s: not found!\n", papszArgs[0]); //__debugbreak(); return ERROR_FILE_NOT_FOUND; } /** * Searches the environment block for the PATH variable. * * @returns Pointer to the path in the block or "." in pwszPathFallback. * @param pwszzEnv The UTF-16 environment block to search. * @param pwszPathFallback Fallback. */ static const WCHAR *mkWinChildcareWorkerFindPathValue(const WCHAR *pwszzEnv, WCHAR pwszPathFallback[4]) { while (*pwszzEnv) { size_t cwcVar = wcslen(pwszzEnv); if (!IS_PATH_ENV_VAR(cwcVar, pwszzEnv)) pwszzEnv += cwcVar + 1; else if (cwcVar > 5) return &pwszzEnv[5]; else break; } pwszPathFallback[0] = L'.'; pwszPathFallback[1] = L'\0'; return pwszPathFallback; } /** * Checks if we need to had this executable file to the shell. * * @returns TRUE if it's shell fooder, FALSE if we think windows can handle it. * @param hFile Handle to the file in question */ static BOOL mkWinChildcareWorkerCheckIfNeedShell(HANDLE hFile) { /* * Read the first 512 bytes and check for an executable image header. */ union { DWORD dwSignature; WORD wSignature; BYTE ab[128]; } uBuf; DWORD cbRead; uBuf.dwSignature = 0; if ( ReadFile(hFile, &uBuf, sizeof(uBuf), &cbRead, NULL /*pOverlapped*/) && cbRead == sizeof(uBuf)) { if (uBuf.wSignature == IMAGE_DOS_SIGNATURE) return FALSE; if (uBuf.dwSignature == IMAGE_NT_SIGNATURE) return FALSE; if ( uBuf.wSignature == IMAGE_OS2_SIGNATURE /* NE */ || uBuf.wSignature == 0x5d4c /* LX */ || uBuf.wSignature == IMAGE_OS2_SIGNATURE_LE /* LE */) return FALSE; } return TRUE; } /** * Checks if the image path looks like microsoft CL.exe. * * @returns TRUE / FALSE. * @param pwszImagePath The executable image path to evalutate. * @param cwcImagePath The length of the image path. */ static BOOL mkWinChildIsProbableClExe(WCHAR const *pwszImagePath, size_t cwcImagePath) { assert(pwszImagePath[cwcImagePath] == '\0'); return cwcImagePath > 7 && (pwszImagePath[cwcImagePath - 7] == L'/' || pwszImagePath[cwcImagePath - 7] == L'\\') && (pwszImagePath[cwcImagePath - 6] == L'c' || pwszImagePath[cwcImagePath - 6] == L'C') && (pwszImagePath[cwcImagePath - 5] == L'l' || pwszImagePath[cwcImagePath - 5] == L'L') && pwszImagePath[cwcImagePath - 4] == L'.' && (pwszImagePath[cwcImagePath - 3] == L'e' || pwszImagePath[cwcImagePath - 3] == L'E') && (pwszImagePath[cwcImagePath - 2] == L'x' || pwszImagePath[cwcImagePath - 2] == L'X') && (pwszImagePath[cwcImagePath - 1] == L'e' || pwszImagePath[cwcImagePath - 1] == L'E'); } /** * Temporary workaround for seemingly buggy kFsCache.c / dir-nt-bird.c. * * Something is not invalidated / updated correctly! */ static BOOL mkWinChildcareWorkerIsRegularFileW(PWINCHILDCAREWORKER pWorker, wchar_t const *pwszPath) { BOOL fRet = FALSE; #ifdef KMK if (utf16_regular_file_p(pwszPath)) fRet = TRUE; else #endif { /* Don't believe the cache. */ DWORD dwAttr = GetFileAttributesW(pwszPath); if (dwAttr != INVALID_FILE_ATTRIBUTES) { if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) { #ifdef KMK extern void dir_cache_invalid_volatile(void); dir_cache_invalid_volatile(); if (utf16_regular_file_p(pwszPath)) MkWinChildError(pWorker, 1, "kFsCache was out of sync! pwszPath=%S\n", pwszPath); else { dir_cache_invalid_all(); if (utf16_regular_file_p(pwszPath)) MkWinChildError(pWorker, 1, "kFsCache was really out of sync! pwszPath=%S\n", pwszPath); else MkWinChildError(pWorker, 1, "kFsCache is really out of sync!! pwszPath=%S\n", pwszPath); } #endif fRet = TRUE; } } } return fRet; } /** * Tries to locate the image file, searching the path and maybe falling back on * the shell in case it knows more (think cygwin with its own view of the file * system). * * This will also check for shell script, falling back on the shell too to * handle those. * * @returns 0 on success, windows error code on failure. * @param pWorker The childcare worker. * @param pszArg0 The first argument. * @param pwszSearchPath In case mkWinChildcareWorkerConvertEnvironment * had a chance of locating the search path already. * @param pwszzEnv The environment block, in case we need to look for * the path. * @param pszShell The shell. * @param ppwszImagePath Where to return the pointer to the image path. This * could be the shell. * @param pfNeedShell Where to return shell vs direct execution indicator. * @param pfProbableClExe Where to return an indicator of probably CL.EXE. */ static int mkWinChildcareWorkerFindImage(PWINCHILDCAREWORKER pWorker, char const *pszArg0, WCHAR *pwszSearchPath, WCHAR const *pwszzEnv, const char *pszShell, WCHAR **ppwszImagePath, BOOL *pfNeedShell, BOOL *pfProbableClExe) { /** @todo Slap a cache on this code. We usually end up executing the same * stuff over and over again (e.g. compilers, linkers, etc). * Hitting the file system is slow on windows. */ /* * Convert pszArg0 to unicode so we can work directly on that. */ WCHAR wszArg0[MKWINCHILD_MAX_PATH + 4]; /* +4 for painless '.exe' appending */ DWORD dwErr; size_t cbArg0 = strlen(pszArg0) + 1; int const cwcArg0 = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszArg0, cbArg0, wszArg0, MKWINCHILD_MAX_PATH); if (cwcArg0 > 0) { HANDLE hFile = INVALID_HANDLE_VALUE; WCHAR wszPathBuf[MKWINCHILD_MAX_PATH + 4]; /* +4 for painless '.exe' appending */ int cwc; /* * If there isn't an .exe suffix, we may have to add one. * Also we ASSUME that .exe suffixes means no hash bang detection needed. */ int const fHasExeSuffix = cwcArg0 > CSTRLEN(".exe") && wszArg0[cwcArg0 - 4] == '.' && (wszArg0[cwcArg0 - 3] == L'e' || wszArg0[cwcArg0 - 3] == L'E') && (wszArg0[cwcArg0 - 2] == L'x' || wszArg0[cwcArg0 - 2] == L'X') && (wszArg0[cwcArg0 - 1] == L'e' || wszArg0[cwcArg0 - 1] == L'E'); /* * If there isn't any path specified, we need to search the PATH env.var. */ int const fHasPath = wszArg0[1] == L':' || wszArg0[0] == L'\\' || wszArg0[0] == L'/' || wmemchr(wszArg0, L'/', cwcArg0) || wmemchr(wszArg0, L'\\', cwcArg0); /* Before we do anything, flip UNIX slashes to DOS ones. */ WCHAR *pwc = wszArg0; while ((pwc = wcschr(pwc, L'/')) != NULL) *pwc++ = L'\\'; /* Don't need to set these all the time... */ *pfNeedShell = FALSE; *pfProbableClExe = FALSE; /* * If any kind of path is specified in arg0, we will not search the * PATH env.var and can limit ourselves to maybe slapping a .exe on to it. */ if (fHasPath) { /* * If relative to a CWD, turn it into an absolute one. */ unsigned cwcPath = cwcArg0; WCHAR *pwszPath = wszArg0; if ( *pwszPath != L'\\' && (pwszPath[1] != ':' || pwszPath[2] != L'\\') ) { DWORD cwcAbsPath = GetFullPathNameW(wszArg0, MKWINCHILD_MAX_PATH, wszPathBuf, NULL); if (cwcAbsPath > 0) { cwcPath = cwcAbsPath + 1; /* include terminator, like MultiByteToWideChar does. */ pwszPath = wszPathBuf; } } /* * Check with .exe suffix first. * We don't open .exe files and look for hash bang stuff, we just * assume they are executable images that CreateProcess can deal with. */ if (!fHasExeSuffix) { pwszPath[cwcPath - 1] = L'.'; pwszPath[cwcPath ] = L'e'; pwszPath[cwcPath + 1] = L'x'; pwszPath[cwcPath + 2] = L'e'; pwszPath[cwcPath + 3] = L'\0'; } if (mkWinChildcareWorkerIsRegularFileW(pWorker, pwszPath)) { *pfProbableClExe = mkWinChildIsProbableClExe(pwszPath, cwcPath + 4 - 1); return mkWinChildDuplicateUtf16String(pwszPath, cwcPath + 4, ppwszImagePath); } /* * If no suffix was specified, try without .exe too, but now we need * to see if it's for the shell or CreateProcess. */ if (!fHasExeSuffix) { pwszPath[cwcPath - 1] = L'\0'; #ifdef KMK if (mkWinChildcareWorkerIsRegularFileW(pWorker, pwszPath)) #endif { hFile = CreateFileW(pwszPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL /*pSecAttr*/, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { *pfNeedShell = mkWinChildcareWorkerCheckIfNeedShell(hFile); CloseHandle(hFile); if (!*pfNeedShell) { *pfProbableClExe = mkWinChildIsProbableClExe(pwszPath, cwcPath - 1); return mkWinChildDuplicateUtf16String(pwszPath, cwcPath, ppwszImagePath); } } } } } /* * No path, need to search the PATH env.var. for the executable, maybe * adding an .exe suffix while do so if that is missing. */ else { BOOL fSearchedCwd = FALSE; WCHAR wszPathFallback[4]; if (!pwszSearchPath) pwszSearchPath = (WCHAR *)mkWinChildcareWorkerFindPathValue(pwszzEnv, wszPathFallback); for (;;) { size_t cwcCombined; /* * Find the end of the current PATH component. */ size_t cwcSkip; WCHAR wcEnd; size_t cwcComponent = 0; WCHAR wc; while ((wc = pwszSearchPath[cwcComponent]) != L'\0') { if (wc != ';' && wc != ':') { /* likely */ } else if (wc == ';') break; else if (cwcComponent != (pwszSearchPath[cwcComponent] != L'"' ? 1 : 2)) break; cwcComponent++; } wcEnd = wc; /* Trim leading spaces and double quotes. */ while ( cwcComponent > 0 && ((wc = *pwszSearchPath) == L'"' || wc == L' ' || wc == L'\t')) { pwszSearchPath++; cwcComponent--; } cwcSkip = cwcComponent; /* Trim trailing spaces & double quotes. */ while ( cwcComponent > 0 && ((wc = pwszSearchPath[cwcComponent - 1]) == L'"' || wc == L' ' || wc == L'\t')) cwcComponent--; /* * Skip empty components. Join the component and the filename, making sure to * resolve any CWD relative stuff first. */ cwcCombined = cwcComponent + 1 + cwcArg0; if (cwcComponent > 0 && cwcCombined <= MKWINCHILD_MAX_PATH) { /* Copy the component into wszPathBuf, maybe abspath'ing it. */ DWORD cwcAbsPath = 0; if ( *pwszSearchPath != L'\\' && (pwszSearchPath[1] != ':' || pwszSearchPath[2] != L'\\') ) { /* To save an extra buffer + copying, we'll temporarily modify the PATH value in our converted UTF-16 environment block. */ WCHAR const wcSaved = pwszSearchPath[cwcComponent]; pwszSearchPath[cwcComponent] = L'\0'; cwcAbsPath = GetFullPathNameW(pwszSearchPath, MKWINCHILD_MAX_PATH, wszPathBuf, NULL); pwszSearchPath[cwcComponent] = wcSaved; if (cwcAbsPath > 0 && cwcAbsPath + 1 + cwcArg0 <= MKWINCHILD_MAX_PATH) cwcCombined = cwcAbsPath + 1 + cwcArg0; else cwcAbsPath = 0; } if (cwcAbsPath == 0) { memcpy(wszPathBuf, pwszSearchPath, cwcComponent * sizeof(WCHAR)); cwcAbsPath = cwcComponent; } /* Append the filename. */ if ((wc = wszPathBuf[cwcAbsPath - 1]) == L'\\' || wc == L'/' || wc == L':') { memcpy(&wszPathBuf[cwcAbsPath], wszArg0, cwcArg0 * sizeof(WCHAR)); cwcCombined--; } else { wszPathBuf[cwcAbsPath] = L'\\'; memcpy(&wszPathBuf[cwcAbsPath + 1], wszArg0, cwcArg0 * sizeof(WCHAR)); } assert(wszPathBuf[cwcCombined - 1] == L'\0'); /* DOS slash conversion */ pwc = wszPathBuf; while ((pwc = wcschr(pwc, L'/')) != NULL) *pwc++ = L'\\'; /* * Search with exe suffix first. */ if (!fHasExeSuffix) { wszPathBuf[cwcCombined - 1] = L'.'; wszPathBuf[cwcCombined ] = L'e'; wszPathBuf[cwcCombined + 1] = L'x'; wszPathBuf[cwcCombined + 2] = L'e'; wszPathBuf[cwcCombined + 3] = L'\0'; } if (mkWinChildcareWorkerIsRegularFileW(pWorker, wszPathBuf)) { *pfProbableClExe = mkWinChildIsProbableClExe(wszPathBuf, cwcCombined + (fHasExeSuffix ? 0 : 4) - 1); return mkWinChildDuplicateUtf16String(wszPathBuf, cwcCombined + (fHasExeSuffix ? 0 : 4), ppwszImagePath); } if (!fHasExeSuffix) { wszPathBuf[cwcCombined - 1] = L'\0'; #ifdef KMK if (mkWinChildcareWorkerIsRegularFileW(pWorker, wszPathBuf)) #endif { /* * Check if the file exists w/o the added '.exe' suffix. If it does, * we need to check if we can pass it to CreateProcess or need the shell. */ hFile = CreateFileW(wszPathBuf, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL /*pSecAttr*/, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { *pfNeedShell = mkWinChildcareWorkerCheckIfNeedShell(hFile); CloseHandle(hFile); if (!*pfNeedShell) { *pfProbableClExe = mkWinChildIsProbableClExe(wszPathBuf, cwcCombined - 1); return mkWinChildDuplicateUtf16String(wszPathBuf, cwcCombined, ppwszImagePath); } break; } } } } /* * Advance to the next component. */ if (wcEnd != '\0') pwszSearchPath += cwcSkip + 1; else if (fSearchedCwd) break; else { fSearchedCwd = TRUE; wszPathFallback[0] = L'.'; wszPathFallback[1] = L'\0'; pwszSearchPath = wszPathFallback; } } } /* * We need the shell. It will take care of finding/reporting missing * image files and such. */ *pfNeedShell = TRUE; if (pszShell) { cwc = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszShell, strlen(pszShell) + 1, wszPathBuf, MKWINCHILD_MAX_PATH); if (cwc > 0) return mkWinChildDuplicateUtf16String(wszPathBuf, cwc, ppwszImagePath); dwErr = GetLastError(); MkWinChildError(pWorker, 1, _("MultiByteToWideChar failed to convert shell (%s): %u\n"), pszShell, dwErr); } else { MkWinChildError(pWorker, 1, "%s: not found!\n", pszArg0); dwErr = ERROR_FILE_NOT_FOUND; } } else { dwErr = GetLastError(); MkWinChildError(pWorker, 1, _("MultiByteToWideChar failed to convert argv[0] (%s): %u\n"), pszArg0, dwErr); } return dwErr == ERROR_INSUFFICIENT_BUFFER ? ERROR_FILENAME_EXCED_RANGE : dwErr; } /** * Creates the environment block. * * @returns 0 on success, windows error code on failure. * @param pWorker The childcare worker if on one, otherwise NULL. * @param papszEnv The environment vector to convert. * @param cbEnvStrings The size of the environment strings, iff they are * sequential in a block. Otherwise, zero. * @param ppwszEnv Where to return the pointer to the environment * block. * @param ppwszSearchPath Where to return the pointer to the path value * within the environment block. This will not be set * if cbEnvStrings is non-zero, more efficient to let * mkWinChildcareWorkerFindImage() search when needed. */ static int mkWinChildcareWorkerConvertEnvironment(PWINCHILDCAREWORKER pWorker, char **papszEnv, size_t cbEnvStrings, WCHAR **ppwszEnv, WCHAR const **ppwszSearchPath) { DWORD dwErr; int cwcRc; int cwcDst; WCHAR *pwszzDst; *ppwszSearchPath = NULL; /* * We've got a little optimization here with help from mkWinChildCopyStringArray. */ if (cbEnvStrings) { cwcDst = cbEnvStrings + 32; pwszzDst = (WCHAR *)xmalloc(cwcDst * sizeof(WCHAR)); cwcRc = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, papszEnv[0], cbEnvStrings, pwszzDst, cwcDst); if (cwcRc != 0) { *ppwszEnv = pwszzDst; return 0; } /* Resize the allocation and try again. */ dwErr = GetLastError(); if (dwErr == ERROR_INSUFFICIENT_BUFFER) { cwcRc = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, papszEnv[0], cbEnvStrings, NULL, 0); if (cwcRc > 0) cwcDst = cwcRc + 32; else cwcDst *= 2; pwszzDst = (WCHAR *)xrealloc(pwszzDst, cwcDst); cwcRc = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, papszEnv[0], cbEnvStrings, pwszzDst, cwcDst); if (cwcRc != 0) { *ppwszEnv = pwszzDst; return 0; } dwErr = GetLastError(); } MkWinChildError(pWorker, 1, _("MultiByteToWideChar failed to convert environment block: %u\n"), dwErr); } /* * Need to convert it string by string. */ else { size_t offPathValue = ~(size_t)0; size_t offDst; /* * Estimate the size first. */ size_t cEnvVars; size_t cwcDst = 32; size_t iVar = 0; const char *pszSrc; while ((pszSrc = papszEnv[iVar]) != NULL) { cwcDst += strlen(pszSrc) + 1; iVar++; } cEnvVars = iVar; /* Allocate estimated WCHARs and convert the variables one by one, reallocating the block as needed. */ pwszzDst = (WCHAR *)xmalloc(cwcDst * sizeof(WCHAR)); cwcDst--; /* save one wchar for the terminating empty string. */ offDst = 0; for (iVar = 0; iVar < cEnvVars; iVar++) { size_t cwcLeft = cwcDst - offDst; size_t const cbSrc = strlen(pszSrc = papszEnv[iVar]) + 1; assert(cwcDst >= offDst); cwcRc = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, cbSrc, &pwszzDst[offDst], cwcLeft); if (cwcRc > 0) { /* likely */ } else { dwErr = GetLastError(); if (dwErr == ERROR_INSUFFICIENT_BUFFER) { /* Need more space. So, calc exacly how much and resize the block accordingly. */ size_t cbSrc2 = cbSrc; size_t iVar2 = iVar; cwcLeft = 1; for (;;) { size_t cwcRc2 = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, cbSrc, NULL, 0); if (cwcRc2 > 0) cwcLeft += cwcRc2; else cwcLeft += cbSrc * 4; /* advance */ iVar2++; if (iVar2 >= cEnvVars) break; pszSrc = papszEnv[iVar2]; cbSrc2 = strlen(pszSrc) + 1; } pszSrc = papszEnv[iVar]; /* Grow the allocation and repeat the conversion. */ if (offDst + cwcLeft > cwcDst + 1) { cwcDst = offDst + cwcLeft; pwszzDst = (WCHAR *)xrealloc(pwszzDst, cwcDst * sizeof(WCHAR)); cwcDst--; /* save one wchar for the terminating empty string. */ cwcRc = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, cbSrc, &pwszzDst[offDst], cwcLeft - 1); if (cwcRc <= 0) dwErr = GetLastError(); } } if (cwcRc <= 0) { MkWinChildError(pWorker, 1, _("MultiByteToWideChar failed to convert environment string #%u (%s): %u\n"), iVar, pszSrc, dwErr); free(pwszzDst); return dwErr; } } /* Look for the PATH. */ if ( offPathValue == ~(size_t)0 && IS_PATH_ENV_VAR(cwcRc, &pwszzDst[offDst]) ) offPathValue = offDst + 4 + 1; /* Advance. */ offDst += cwcRc; } pwszzDst[offDst++] = '\0'; if (offPathValue != ~(size_t)0) *ppwszSearchPath = &pwszzDst[offPathValue]; *ppwszEnv = pwszzDst; return 0; } free(pwszzDst); return dwErr; } /** * Childcare worker: handle regular process. * * @param pWorker The worker. * @param pChild The kSubmit child. */ static void mkWinChildcareWorkerThreadHandleProcess(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild) { WCHAR *pwszSearchPath = NULL; WCHAR *pwszzEnvironment = NULL; WCHAR *pwszCommandLine = NULL; WCHAR *pwszImageName = NULL; BOOL fNeedShell = FALSE; BOOL fProbableClExe = FALSE; int rc; /* * First we convert the environment so we get the PATH we need to * search for the executable. */ rc = mkWinChildcareWorkerConvertEnvironment(pWorker, pChild->u.Process.papszEnv ? pChild->u.Process.papszEnv : environ, pChild->u.Process.cbEnvStrings, &pwszzEnvironment, &pwszSearchPath); /* * Find the executable and maybe checking if it's a shell script, then * convert it to a command line. */ if (rc == 0) rc = mkWinChildcareWorkerFindImage(pWorker, pChild->u.Process.papszArgs[0], pwszSearchPath, pwszzEnvironment, pChild->u.Process.pszShell, &pwszImageName, &fNeedShell, &pChild->fProbableClExe); if (rc == 0) { if (!fNeedShell) rc = mkWinChildcareWorkerConvertCommandline(pWorker, pChild->u.Process.papszArgs, 0 /*fFlags*/, &pwszCommandLine); else rc = mkWinChildcareWorkerConvertCommandlineWithShell(pWorker, pwszImageName, pChild->u.Process.papszArgs, &pwszCommandLine); /* * Create the child process. */ if (rc == 0) { BOOL afReplace[3] = { FALSE, pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE, pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE }; HANDLE ahChild[3] = { INVALID_HANDLE_VALUE, pChild->u.Process.hStdOut, pChild->u.Process.hStdErr }; rc = mkWinChildcareWorkerCreateProcess(pWorker, pwszImageName, pwszCommandLine, pwszzEnvironment, NULL /*pwszCwd*/, afReplace, ahChild, pChild->u.Process.fCatchOutput, &pChild->u.Process.hProcess); mkWinChildcareWorkerCloseStandardHandles(pChild); if (rc == 0) { /* * Wait for the child to complete. */ mkWinChildcareWorkerWaitForProcess(pWorker, pChild, pChild->u.Process.hProcess, pwszImageName, pChild->u.Process.fCatchOutput); } else pChild->iExitCode = rc; } else pChild->iExitCode = rc; } else pChild->iExitCode = rc; free(pwszCommandLine); free(pwszImageName); free(pwszzEnvironment); /* In case we failed, we must make sure the child end of pipes used by $(shell no_such_command.exe) are closed, otherwise the main thread will be stuck reading the parent end. */ mkWinChildcareWorkerCloseStandardHandles(pChild); } #ifdef KMK /** * Childcare worker: handle builtin command. * * @param pWorker The worker. * @param pChild The kSubmit child. */ static void mkWinChildcareWorkerThreadHandleBuiltIn(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild) { PCKMKBUILTINENTRY pBuiltIn = pChild->u.BuiltIn.pBuiltIn; KMKBUILTINCTX Ctx = { pBuiltIn->uName.s.sz, pChild->pMkChild ? &pChild->pMkChild->output : NULL, pWorker, }; if (pBuiltIn->uFnSignature == FN_SIG_MAIN) pChild->iExitCode = pBuiltIn->u.pfnMain(pChild->u.BuiltIn.cArgs, pChild->u.BuiltIn.papszArgs, pChild->u.BuiltIn.papszEnv, &Ctx); else if (pBuiltIn->uFnSignature == FN_SIG_MAIN_SPAWNS) pChild->iExitCode = pBuiltIn->u.pfnMainSpawns(pChild->u.BuiltIn.cArgs, pChild->u.BuiltIn.papszArgs, pChild->u.BuiltIn.papszEnv, &Ctx, pChild->pMkChild, NULL /*pPid*/); else { assert(0); pChild->iExitCode = 98; } } /** * Childcare worker: handle append write-out. * * @param pWorker The worker. * @param pChild The kSubmit child. */ static void mkWinChildcareWorkerThreadHandleAppend(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild) { int fd = open(pChild->u.Append.pszFilename, pChild->u.Append.fTruncate ? O_WRONLY | O_TRUNC | O_CREAT | _O_NOINHERIT | _O_BINARY : O_WRONLY | O_APPEND | O_CREAT | _O_NOINHERIT | _O_BINARY, 0666); if (fd >= 0) { ssize_t cbWritten = write(fd, pChild->u.Append.pszAppend, pChild->u.Append.cbAppend); if (cbWritten == (ssize_t)pChild->u.Append.cbAppend) { if (close(fd) >= 0) { pChild->iExitCode = 0; return; } MkWinChildError(pWorker, 1, "kmk_builtin_append: close failed on '%s': %u (%s)\n", pChild->u.Append.pszFilename, errno, strerror(errno)); } else MkWinChildError(pWorker, 1, "kmk_builtin_append: error writing %lu bytes to on '%s': %u (%s)\n", pChild->u.Append.cbAppend, pChild->u.Append.pszFilename, errno, strerror(errno)); close(fd); } else MkWinChildError(pWorker, 1, "kmk_builtin_append: error opening '%s': %u (%s)\n", pChild->u.Append.pszFilename, errno, strerror(errno)); pChild->iExitCode = 1; } /** * Childcare worker: handle kSubmit job. * * @param pWorker The worker. * @param pChild The kSubmit child. */ static void mkWinChildcareWorkerThreadHandleSubmit(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild) { void *pvSubmitWorker = pChild->u.Submit.pvSubmitWorker; /* * Prep the wait handles. */ HANDLE ahHandles[3] = { pChild->u.Submit.hEvent, NULL, NULL }; DWORD cHandles = 1; if (pChild->u.Submit.pStdOut) { assert(pChild->u.Submit.pStdErr); pChild->u.Submit.pStdOut->fHaveWrittenOut = FALSE; ahHandles[cHandles++] = pChild->u.Submit.pStdOut->hEvent; pChild->u.Submit.pStdErr->fHaveWrittenOut = FALSE; ahHandles[cHandles++] = pChild->u.Submit.pStdErr->hEvent; } /* * Wait loop. */ for (;;) { int iExitCode = -42; int iSignal = -1; DWORD dwStatus; if (cHandles == 1) dwStatus = WaitForSingleObject(ahHandles[0], INFINITE); else { dwStatus = WaitForMultipleObjects(cHandles, ahHandles, FALSE /*fWaitAll*/, INFINITE); assert(dwStatus != WAIT_FAILED); if (dwStatus == WAIT_OBJECT_0 + 1) mkWinChildcareWorkerCatchOutput(pChild, pChild->u.Submit.pStdOut, FALSE /*fDraining*/); else if (dwStatus == WAIT_OBJECT_0 + 2) mkWinChildcareWorkerCatchOutput(pChild, pChild->u.Submit.pStdErr, FALSE /*fDraining*/); } if (kSubmitSubProcGetResult((intptr_t)pvSubmitWorker, dwStatus == WAIT_OBJECT_0 /*fBlock*/, &iExitCode, &iSignal) == 0) { if (pChild->u.Submit.pStdOut) MkWinChildcareWorkerDrainPipes(pChild, pChild->u.Submit.pStdOut, pChild->u.Submit.pStdErr); pChild->iExitCode = iExitCode; pChild->iSignal = iSignal; /* Cleanup must be done on the main thread. */ return; } if (pChild->iSignal != 0) kSubmitSubProcKill((intptr_t)pvSubmitWorker, pChild->iSignal); } } /** * Childcare worker: handle kmk_redirect process. * * @param pWorker The worker. * @param pChild The redirect child. */ static void mkWinChildcareWorkerThreadHandleRedirect(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild) { mkWinChildcareWorkerWaitForProcess(pWorker, pChild, pChild->u.Redirect.hProcess, L"kmk_redirect", FALSE /*fCatchOutput*/); } #endif /* KMK */ /** * Childcare worker thread. * * @returns 0 * @param pvUser The worker instance. */ static unsigned int __stdcall mkWinChildcareWorkerThread(void *pvUser) { PWINCHILDCAREWORKER pWorker = (PWINCHILDCAREWORKER)pvUser; assert(pWorker->uMagic == WINCHILDCAREWORKER_MAGIC); #ifdef MKWINCHILD_DO_SET_PROCESSOR_GROUP /* * Adjust process group if necessary. * * Note! It seems that setting the mask to zero means that we select all * active processors. Couldn't find any alternative API for getting * the correct active processor mask. */ if (g_cProcessorGroups > 1 && !g_pfnSetProcessDefaultCpuSetMasks) { BOOL fRet; GROUP_AFFINITY Affinity = { 0, pWorker->iProcessorGroup, { 0, 0, 0 } }; if (g_pGroupInfo && pWorker->iProcessorGroup < g_pGroupInfo->ActiveGroupCount) Affinity.Mask = g_pGroupInfo->GroupInfo[pWorker->iProcessorGroup].ActiveProcessorMask; fRet = g_pfnSetThreadGroupAffinity(GetCurrentThread(), &Affinity, NULL); assert(fRet); (void)fRet; # ifndef NDEBUG { GROUP_AFFINITY ActualAffinity = { 0xbeefbeefU, 0xbeef, { 0xbeef, 0xbeef, 0xbeef } }; fRet = GetThreadGroupAffinity(GetCurrentThread(), &ActualAffinity); assert(fRet); (void)fRet; assert(ActualAffinity.Group == pWorker->iProcessorGroup); } # endif } #endif /* * Work loop. */ while (!g_fShutdown) { /* * Try go idle. */ PWINCHILD pChild = pWorker->pTailTodoChildren; if (!pChild) { _InterlockedExchange(&pWorker->fIdle, TRUE); pChild = pWorker->pTailTodoChildren; if (!pChild) { DWORD dwStatus; _InterlockedIncrement((long *)&g_cIdleChildcareWorkers); _InterlockedExchange((long *)&g_idxLastChildcareWorker, pWorker->idxWorker); dwStatus = WaitForSingleObject(pWorker->hEvtIdle, INFINITE); _InterlockedExchange(&pWorker->fIdle, FALSE); _InterlockedDecrement((long *)&g_cIdleChildcareWorkers); assert(dwStatus != WAIT_FAILED); if (dwStatus == WAIT_FAILED) Sleep(20); pChild = pWorker->pTailTodoChildren; } else _InterlockedExchange(&pWorker->fIdle, FALSE); } if (pChild) { /* * We got work to do. First job is to deque the job. */ pChild = mkWinChildDequeFromLifo(&pWorker->pTailTodoChildren, pChild); #ifdef DEBUG_STDOUT_CLOSE_ISSUE my_check_stdout("mkWinChildcareWorkerThread/deque"); #endif assert(pChild); if (pChild) { PWINCHILD pTailExpect; pChild->pWorker = pWorker; pWorker->pCurChild = pChild; switch (pChild->enmType) { case WINCHILDTYPE_PROCESS: mkWinChildcareWorkerThreadHandleProcess(pWorker, pChild); #ifdef DEBUG_STDOUT_CLOSE_ISSUE my_check_stdout("mkWinChildcareWorkerThread/done-process"); #endif break; #ifdef KMK case WINCHILDTYPE_BUILT_IN: mkWinChildcareWorkerThreadHandleBuiltIn(pWorker, pChild); # ifdef DEBUG_STDOUT_CLOSE_ISSUE my_check_stdout("mkWinChildcareWorkerThread/done-built-in"); # endif break; case WINCHILDTYPE_APPEND: mkWinChildcareWorkerThreadHandleAppend(pWorker, pChild); # ifdef DEBUG_STDOUT_CLOSE_ISSUE my_check_stdout("mkWinChildcareWorkerThread/done-append"); # endif break; case WINCHILDTYPE_SUBMIT: mkWinChildcareWorkerThreadHandleSubmit(pWorker, pChild); # ifdef DEBUG_STDOUT_CLOSE_ISSUE my_check_stdout("mkWinChildcareWorkerThread/done-submit"); # endif break; case WINCHILDTYPE_REDIRECT: mkWinChildcareWorkerThreadHandleRedirect(pWorker, pChild); # ifdef DEBUG_STDOUT_CLOSE_ISSUE my_check_stdout("mkWinChildcareWorkerThread/done-redirect"); # endif break; #endif default: assert(0); } pWorker->pCurChild = NULL; pChild->pWorker = NULL; /* * Move the child to the completed list. */ pTailExpect = NULL; for (;;) { PWINCHILD pTailActual; pChild->pNext = pTailExpect; pTailActual = _InterlockedCompareExchangePointer(&g_pTailCompletedChildren, pChild, pTailExpect); if (pTailActual != pTailExpect) pTailExpect = pTailActual; else { _InterlockedDecrement(&g_cPendingChildren); if (pTailExpect) break; if (SetEvent(g_hEvtWaitChildren)) break; MkWinChildError(pWorker, 1, "SetEvent(g_hEvtWaitChildren=%p) failed: %u\n", g_hEvtWaitChildren, GetLastError()); break; } } } } } _endthreadex(0); return 0; } /** * Creates a pipe for catching child output. * * This is a custom CreatePipe implementation that allows for overlapped I/O on * our end of the pipe. Silly that they don't offer an API that does this. * * @returns The pipe that was created. NULL on failure. * @param pPipe The structure for the pipe. * @param iWhich Which standard descriptor this is a pipe for. * @param idxWorker The worker index. */ PWINCCWPIPE MkWinChildcareCreateWorkerPipe(unsigned iWhich, unsigned int idxWorker) { /* * We try generate a reasonably unique name from the get go, so this retry * loop shouldn't really ever be needed. But you never know. */ static unsigned s_iSeqNo = 0; DWORD const cMaxInstances = 1; DWORD const cbPipe = 4096; DWORD const cMsTimeout = 0; unsigned cTries = 256; while (cTries-- > 0) { /* Create the pipe (our end). */ HANDLE hPipeRead; DWORD fOpenMode = PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE; DWORD fPipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS; WCHAR wszName[MAX_PATH]; s_iSeqNo++; _snwprintf(wszName, MAX_PATH, L"\\\\.\\pipe\\kmk-winchildren-%u-%u-%u-%s-%u-%u", GetCurrentProcessId(), GetCurrentThreadId(), idxWorker, iWhich == 1 ? L"out" : L"err", s_iSeqNo, GetTickCount()); hPipeRead = CreateNamedPipeW(wszName, fOpenMode, fPipeMode, cMaxInstances, cbPipe, cbPipe, cMsTimeout, NULL /*pSecAttr*/); if (hPipeRead == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER) { fOpenMode &= ~FILE_FLAG_FIRST_PIPE_INSTANCE; fPipeMode &= ~PIPE_REJECT_REMOTE_CLIENTS; hPipeRead = CreateNamedPipeW(wszName, fOpenMode, fPipeMode, cMaxInstances, cbPipe, cbPipe, cMsTimeout, NULL /*pSecAttr*/); } if (hPipeRead != INVALID_HANDLE_VALUE) { /* Connect the other end. */ HANDLE hPipeWrite = CreateFileW(wszName, GENERIC_WRITE | FILE_READ_ATTRIBUTES, 0 /*fShareMode*/, NULL /*pSecAttr*/, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL /*hTemplateFile*/); if (hPipeWrite != INVALID_HANDLE_VALUE) { /* * Create the event object and we're done. * * It starts in signalled stated so we don't need special code * for handing when we start waiting. */ HANDLE hEvent = CreateEventW(NULL /*pSecAttr*/, TRUE /*fManualReset*/, TRUE /*fInitialState*/, NULL /*pwszName*/); if (hEvent != NULL) { PWINCCWPIPE pPipe = (PWINCCWPIPE)xcalloc(sizeof(*pPipe)); pPipe->hPipeMine = hPipeRead; pPipe->hPipeChild = hPipeWrite; pPipe->hEvent = hEvent; pPipe->iWhich = iWhich; pPipe->fReadPending = FALSE; pPipe->cbBuffer = cbPipe; pPipe->pbBuffer = xcalloc(cbPipe); return pPipe; } CloseHandle(hPipeWrite); CloseHandle(hPipeRead); return NULL; } CloseHandle(hPipeRead); } } return NULL; } /** * Destroys a childcare worker pipe. * * @param pPipe The pipe. */ void MkWinChildcareDeleteWorkerPipe(PWINCCWPIPE pPipe) { if (pPipe->hPipeChild != NULL) { CloseHandle(pPipe->hPipeChild); pPipe->hPipeChild = NULL; } if (pPipe->hPipeMine != NULL) { if (pPipe->fReadPending) if (!CancelIo(pPipe->hPipeMine)) WaitForSingleObject(pPipe->hEvent, INFINITE); CloseHandle(pPipe->hPipeMine); pPipe->hPipeMine = NULL; } if (pPipe->hEvent != NULL) { CloseHandle(pPipe->hEvent); pPipe->hEvent = NULL; } if (pPipe->pbBuffer) { free(pPipe->pbBuffer); pPipe->pbBuffer = NULL; } } /** * Initializes the processor group allocator. * * @param pState The allocator to initialize. */ void MkWinChildInitCpuGroupAllocator(PMKWINCHILDCPUGROUPALLOCSTATE pState) { /* We shift the starting group with the make nesting level as part of our very simple distribution strategy. */ pState->idxGroup = makelevel; pState->idxProcessorInGroup = 0; } /** * Allocate CPU group for the next child process. * * @returns CPU group. * @param pState The allocator state. Must be initialized by * MkWinChildInitCpuGroupAllocator(). */ unsigned int MkWinChildAllocateCpuGroup(PMKWINCHILDCPUGROUPALLOCSTATE pState) { unsigned int iGroup = 0; if (g_cProcessorGroups > 1) { unsigned int cMaxInGroup; unsigned int cInGroup; iGroup = pState->idxGroup % g_cProcessorGroups; /* Advance. We employ a very simple strategy that does 50% in each group for each group cycle. Odd processor counts are caught in odd group cycles. The init function selects the starting group based on make nesting level to avoid stressing out the first group. */ cInGroup = ++pState->idxProcessorInGroup; cMaxInGroup = g_pacProcessorsInGroup[iGroup]; if ( !(cMaxInGroup & 1) || !((pState->idxGroup / g_cProcessorGroups) & 1)) cMaxInGroup /= 2; else cMaxInGroup = cMaxInGroup / 2 + 1; if (cInGroup >= cMaxInGroup) { pState->idxProcessorInGroup = 0; pState->idxGroup++; } } return iGroup; } /** * Creates another childcare worker. * * @returns The new worker, if we succeeded. */ static PWINCHILDCAREWORKER mkWinChildcareCreateWorker(void) { PWINCHILDCAREWORKER pWorker = (PWINCHILDCAREWORKER)xcalloc(sizeof(*pWorker)); pWorker->uMagic = WINCHILDCAREWORKER_MAGIC; pWorker->idxWorker = g_cChildCareworkers; pWorker->hEvtIdle = CreateEventW(NULL, FALSE /*fManualReset*/, FALSE /*fInitialState*/, NULL /*pwszName*/); if (pWorker->hEvtIdle) { pWorker->pStdOut = MkWinChildcareCreateWorkerPipe(1, pWorker->idxWorker); if (pWorker->pStdOut) { pWorker->pStdErr = MkWinChildcareCreateWorkerPipe(2, pWorker->idxWorker); if (pWorker->pStdErr) { /* Before we start the thread, assign it to a processor group. */ pWorker->iProcessorGroup = MkWinChildAllocateCpuGroup(&g_ProcessorGroupAllocator); /* Try start the thread. */ pWorker->hThread = (HANDLE)_beginthreadex(NULL, 0 /*cbStack*/, mkWinChildcareWorkerThread, pWorker, 0, &pWorker->tid); if (pWorker->hThread != NULL) { pWorker->idxWorker = g_cChildCareworkers++; /* paranoia */ g_papChildCareworkers[pWorker->idxWorker] = pWorker; return pWorker; } /* Bail out! */ ONS (error, NILF, "_beginthreadex failed: %u (%s)\n", errno, strerror(errno)); MkWinChildcareDeleteWorkerPipe(pWorker->pStdErr); } else ON (error, NILF, "Failed to create stderr pipe: %u\n", GetLastError()); MkWinChildcareDeleteWorkerPipe(pWorker->pStdOut); } else ON (error, NILF, "Failed to create stdout pipe: %u\n", GetLastError()); CloseHandle(pWorker->hEvtIdle); } else ON (error, NILF, "CreateEvent failed: %u\n", GetLastError()); pWorker->uMagic = ~WINCHILDCAREWORKER_MAGIC; free(pWorker); return NULL; } /** * Helper for copying argument and environment vectors. * * @returns Single alloc block copy. * @param papszSrc The source vector. * @param pcbStrings Where to return the size of the strings & terminator. */ static char **mkWinChildCopyStringArray(char **papszSrc, size_t *pcbStrings) { const char *psz; char **papszDstArray; char *pszDstStr; size_t i; /* Calc sizes first. */ size_t cbStrings = 1; /* (one extra for terminator string) */ size_t cStrings = 0; while ((psz = papszSrc[cStrings]) != NULL) { cbStrings += strlen(psz) + 1; cStrings++; } *pcbStrings = cbStrings; /* Allocate destination. */ papszDstArray = (char **)xmalloc(cbStrings + (cStrings + 1) * sizeof(papszDstArray[0])); pszDstStr = (char *)&papszDstArray[cStrings + 1]; /* Copy it. */ for (i = 0; i < cStrings; i++) { const char *pszSource = papszSrc[i]; size_t cchString = strlen(pszSource); papszDstArray[i] = pszDstStr; memcpy(pszDstStr, pszSource, cchString); pszDstStr += cchString; *pszDstStr++ = '\0'; } *pszDstStr = '\0'; assert(&pszDstStr[1] - papszDstArray[0] == cbStrings); papszDstArray[i] = NULL; return papszDstArray; } /** * Allocate and init a WINCHILD. * * @returns The new windows child structure. * @param enmType The child type. */ static PWINCHILD mkWinChildNew(WINCHILDTYPE enmType) { PWINCHILD pChild = xcalloc(sizeof(*pChild)); pChild->enmType = enmType; pChild->fCoreDumped = 0; pChild->iSignal = 0; pChild->iExitCode = 222222; pChild->uMagic = WINCHILD_MAGIC; pChild->pid = (intptr_t)pChild; return pChild; } /** * Destructor for WINCHILD. * * @param pChild The child structure to destroy. */ static void mkWinChildDelete(PWINCHILD pChild) { assert(pChild->uMagic == WINCHILD_MAGIC); pChild->uMagic = ~WINCHILD_MAGIC; switch (pChild->enmType) { case WINCHILDTYPE_PROCESS: { if (pChild->u.Process.papszArgs) { free(pChild->u.Process.papszArgs); pChild->u.Process.papszArgs = NULL; } if (pChild->u.Process.cbEnvStrings && pChild->u.Process.papszEnv) { free(pChild->u.Process.papszEnv); pChild->u.Process.papszEnv = NULL; } if (pChild->u.Process.pszShell) { free(pChild->u.Process.pszShell); pChild->u.Process.pszShell = NULL; } if (pChild->u.Process.hProcess) { CloseHandle(pChild->u.Process.hProcess); pChild->u.Process.hProcess = NULL; } mkWinChildcareWorkerCloseStandardHandles(pChild); break; } #ifdef KMK case WINCHILDTYPE_BUILT_IN: if (pChild->u.BuiltIn.papszArgs) { free(pChild->u.BuiltIn.papszArgs); pChild->u.BuiltIn.papszArgs = NULL; } if (pChild->u.BuiltIn.papszEnv) { free(pChild->u.BuiltIn.papszEnv); pChild->u.BuiltIn.papszEnv = NULL; } break; case WINCHILDTYPE_APPEND: if (pChild->u.Append.pszFilename) { free(pChild->u.Append.pszFilename); pChild->u.Append.pszFilename = NULL; } if (pChild->u.Append.pszAppend) { free(pChild->u.Append.pszAppend); pChild->u.Append.pszAppend = NULL; } break; case WINCHILDTYPE_SUBMIT: if (pChild->u.Submit.pvSubmitWorker) { kSubmitSubProcCleanup((intptr_t)pChild->u.Submit.pvSubmitWorker); pChild->u.Submit.pvSubmitWorker = NULL; } break; case WINCHILDTYPE_REDIRECT: if (pChild->u.Redirect.hProcess) { CloseHandle(pChild->u.Redirect.hProcess); pChild->u.Redirect.hProcess = NULL; } break; #endif /* KMK */ default: assert(0); } free(pChild); } /** * Queues the child with a worker, creating new workers if necessary. * * @returns 0 on success, windows error code on failure (child destroyed). * @param pChild The child. * @param pPid Where to return the PID (optional). */ static int mkWinChildPushToCareWorker(PWINCHILD pChild, pid_t *pPid) { PWINCHILDCAREWORKER pWorker = NULL; PWINCHILD pOldChild; PWINCHILD pCurChild; /* * There are usually idle workers around, except for at the start. */ if (g_cIdleChildcareWorkers > 0) { /* * Try the idle hint first and move forward from it. */ unsigned int const cWorkers = g_cChildCareworkers; unsigned int iHint = g_idxLastChildcareWorker; unsigned int i; for (i = iHint; i < cWorkers; i++) { PWINCHILDCAREWORKER pPossibleWorker = g_papChildCareworkers[i]; if (pPossibleWorker->fIdle) { pWorker = pPossibleWorker; break; } } if (!pWorker) { /* Scan from the start. */ if (iHint > cWorkers) iHint = cWorkers; for (i = 0; i < iHint; i++) { PWINCHILDCAREWORKER pPossibleWorker = g_papChildCareworkers[i]; if (pPossibleWorker->fIdle) { pWorker = pPossibleWorker; break; } } } } if (!pWorker) { /* * Try create more workers if we haven't reached the max yet. */ if (g_cChildCareworkers < g_cChildCareworkersMax) pWorker = mkWinChildcareCreateWorker(); /* * Queue it with an existing worker. Look for one without anthing extra scheduled. */ if (!pWorker) { unsigned int i = g_cChildCareworkers; if (i == 0) fatal(NILF, 0, _("Failed to create worker threads for managing child processes!\n")); pWorker = g_papChildCareworkers[--i]; if (pWorker->pTailTodoChildren) while (i-- > 0) { PWINCHILDCAREWORKER pPossibleWorker = g_papChildCareworkers[i]; if (!pPossibleWorker->pTailTodoChildren) { pWorker = pPossibleWorker; break; } } } } /* * Do the queueing. */ pOldChild = NULL; for (;;) { pChild->pNext = pOldChild; pCurChild = _InterlockedCompareExchangePointer((void **)&pWorker->pTailTodoChildren, pChild, pOldChild); if (pCurChild == pOldChild) { DWORD volatile dwErr; _InterlockedIncrement(&g_cPendingChildren); if ( !pWorker->fIdle || SetEvent(pWorker->hEvtIdle)) { *pPid = pChild->pid; return 0; } _InterlockedDecrement(&g_cPendingChildren); dwErr = GetLastError(); assert(0); mkWinChildDelete(pChild); return dwErr ? dwErr : -20; } pOldChild = pCurChild; } } /** * Creates a regular child process (job.c). * * Will copy the information and push it to a childcare thread that does the * actual process creation. * * @returns 0 on success, windows status code on failure. * @param papszArgs The arguments. * @param papszEnv The environment (optional). * @param pszShell The SHELL variable value (optional). * @param pMkChild The make child structure (optional). * @param pPid Where to return the pid. */ int MkWinChildCreate(char **papszArgs, char **papszEnv, const char *pszShell, struct child *pMkChild, pid_t *pPid) { PWINCHILD pChild = mkWinChildNew(WINCHILDTYPE_PROCESS); pChild->pMkChild = pMkChild; pChild->u.Process.papszArgs = mkWinChildCopyStringArray(papszArgs, &pChild->u.Process.cbArgsStrings); if ( !papszEnv || !pMkChild || pMkChild->environment == papszEnv) { pChild->u.Process.cbEnvStrings = 0; pChild->u.Process.papszEnv = papszEnv; } else pChild->u.Process.papszEnv = mkWinChildCopyStringArray(papszEnv, &pChild->u.Process.cbEnvStrings); if (pszShell) pChild->u.Process.pszShell = xstrdup(pszShell); pChild->u.Process.hStdOut = INVALID_HANDLE_VALUE; pChild->u.Process.hStdErr = INVALID_HANDLE_VALUE; /* We always catch the output in order to prevent character soups courtesy of the microsoft CRT and/or linkers writing character by character to the console. Always try write whole lines, even when --output-sync is none. */ pChild->u.Process.fCatchOutput = TRUE; return mkWinChildPushToCareWorker(pChild, pPid); } /** * Creates a chile process with a pipe hooked up to stdout. * * @returns 0 on success, non-zero on failure. * @param papszArgs The argument vector. * @param papszEnv The environment vector (optional). * @param fdErr File descriptor to hook up to stderr. * @param pPid Where to return the pid. * @param pfdReadPipe Where to return the read end of the pipe. */ int MkWinChildCreateWithStdOutPipe(char **papszArgs, char **papszEnv, int fdErr, pid_t *pPid, int *pfdReadPipe) { /* * Create the pipe. */ HANDLE hReadPipe; HANDLE hWritePipe; if (CreatePipe(&hReadPipe, &hWritePipe, NULL, 0 /* default size */)) { //if (SetHandleInformation(hWritePipe, HANDLE_FLAG_INHERIT /* clear */ , HANDLE_FLAG_INHERIT /*set*/)) { int fdReadPipe = _open_osfhandle((intptr_t)hReadPipe, O_RDONLY); if (fdReadPipe >= 0) { PWINCHILD pChild; int rc; /* * Get a handle for fdErr. Ignore failure. */ HANDLE hStdErr = INVALID_HANDLE_VALUE; if (fdErr >= 0) { HANDLE hNative = (HANDLE)_get_osfhandle(fdErr); if (!DuplicateHandle(GetCurrentProcess(), hNative, GetCurrentProcess(), &hStdErr, 0 /*DesiredAccess*/, TRUE /*fInherit*/, DUPLICATE_SAME_ACCESS)) { ONN(error, NILF, _("DuplicateHandle failed on stderr descriptor (%u): %u\n"), fdErr, GetLastError()); hStdErr = INVALID_HANDLE_VALUE; } } /* * Push it off to the worker thread. */ pChild = mkWinChildNew(WINCHILDTYPE_PROCESS); pChild->u.Process.papszArgs = mkWinChildCopyStringArray(papszArgs, &pChild->u.Process.cbArgsStrings); pChild->u.Process.papszEnv = mkWinChildCopyStringArray(papszEnv ? papszEnv : environ, &pChild->u.Process.cbEnvStrings); //if (pszShell) // pChild->u.Process.pszShell = xstrdup(pszShell); pChild->u.Process.hStdOut = hWritePipe; pChild->u.Process.hStdErr = hStdErr; pChild->u.Process.fCloseStdErr = TRUE; pChild->u.Process.fCloseStdOut = TRUE; rc = mkWinChildPushToCareWorker(pChild, pPid); if (rc == 0) *pfdReadPipe = fdReadPipe; else { ON(error, NILF, _("mkWinChildPushToCareWorker failed on pipe: %d\n"), rc); close(fdReadPipe); *pfdReadPipe = -1; *pPid = -1; } return rc; } ON(error, NILF, _("_open_osfhandle failed on pipe: %u\n"), errno); } //else // ON(error, NILF, _("SetHandleInformation failed on pipe: %u\n"), GetLastError()); if (hReadPipe != INVALID_HANDLE_VALUE) CloseHandle(hReadPipe); CloseHandle(hWritePipe); } else ON(error, NILF, _("CreatePipe failed: %u\n"), GetLastError()); *pfdReadPipe = -1; *pPid = -1; return -1; } #ifdef KMK /** * Interface used by kmkbuiltin.c for executing builtin commands on threads. * * @returns 0 on success, windows status code on failure. * @param pBuiltIn The kmk built-in command entry. * @param cArgs The number of arguments in papszArgs. * @param papszArgs The argument vector. * @param papszEnv The environment vector, optional. * @param pMkChild The make child structure. * @param pPid Where to return the pid. */ int MkWinChildCreateBuiltIn(PCKMKBUILTINENTRY pBuiltIn, int cArgs, char **papszArgs, char **papszEnv, struct child *pMkChild, pid_t *pPid) { size_t cbIgnored; PWINCHILD pChild = mkWinChildNew(WINCHILDTYPE_BUILT_IN); pChild->pMkChild = pMkChild; pChild->u.BuiltIn.pBuiltIn = pBuiltIn; pChild->u.BuiltIn.cArgs = cArgs; pChild->u.BuiltIn.papszArgs = mkWinChildCopyStringArray(papszArgs, &cbIgnored); pChild->u.BuiltIn.papszEnv = papszEnv ? mkWinChildCopyStringArray(papszEnv, &cbIgnored) : NULL; return mkWinChildPushToCareWorker(pChild, pPid); } /** * Interface used by append.c for do the slow file system part. * * This will append the given buffer to the specified file and free the buffer. * * @returns 0 on success, windows status code on failure. * * @param pszFilename The name of the file to append to. * @param ppszAppend What to append. The pointer pointed to is set to * NULL once we've taken ownership of the buffer and * promise to free it. * @param cbAppend How much to append. * @param fTruncate Whether to truncate the file before appending to it. * @param pMkChild The make child structure. * @param pPid Where to return the pid. */ int MkWinChildCreateAppend(const char *pszFilename, char **ppszAppend, size_t cbAppend, int fTruncate, struct child *pMkChild, pid_t *pPid) { size_t cbFilename = strlen(pszFilename) + 1; PWINCHILD pChild = mkWinChildNew(WINCHILDTYPE_APPEND); pChild->pMkChild = pMkChild; pChild->u.Append.fTruncate = fTruncate; pChild->u.Append.pszAppend = *ppszAppend; pChild->u.Append.cbAppend = cbAppend; pChild->u.Append.pszFilename = (char *)memcpy(xmalloc(cbFilename), pszFilename, cbFilename); *ppszAppend = NULL; return mkWinChildPushToCareWorker(pChild, pPid); } /** * Interface used by kSubmit.c for registering stuff to wait on. * * @returns 0 on success, windows status code on failure. * @param hEvent The event object handle to wait on. * @param pvSubmitWorker The argument to pass back to kSubmit to clean up. * @param pStdOut Standard output pipe for the worker. Optional. * @param pStdErr Standard error pipe for the worker. Optional. * @param pMkChild The make child structure. * @param pPid Where to return the pid. */ int MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr, struct child *pMkChild, pid_t *pPid) { PWINCHILD pChild = mkWinChildNew(WINCHILDTYPE_SUBMIT); pChild->pMkChild = pMkChild; pChild->u.Submit.hEvent = (HANDLE)hEvent; pChild->u.Submit.pvSubmitWorker = pvSubmitWorker; pChild->u.Submit.pStdOut = pStdOut; pChild->u.Submit.pStdErr = pStdErr; return mkWinChildPushToCareWorker(pChild, pPid); } /** * Interface used by redirect.c for registering stuff to wait on. * * @returns 0 on success, windows status code on failure. * @param hProcess The process object to wait on. * @param pPid Where to return the pid. */ int MkWinChildCreateRedirect(intptr_t hProcess, pid_t *pPid) { PWINCHILD pChild = mkWinChildNew(WINCHILDTYPE_REDIRECT); pChild->u.Redirect.hProcess = (HANDLE)hProcess; return mkWinChildPushToCareWorker(pChild, pPid); } /** * New interface used by redirect.c for spawning and waitin on a child. * * This interface is only used when kmk_builtin_redirect is already running on * a worker thread. * * @returns exit status. * @param pvWorker The worker instance. * @param pszExecutable The executable image to run. * @param papszArgs Argument vector. * @param fQuotedArgv Whether the argument vector is already quoted and * just need some space to be turned into a command * line. * @param papszEnvVars Environment vector. * @param pszCwd The working directory of the child. Optional. * @param pafReplace Which standard handles to replace. Maybe modified! * @param pahReplace The replacement handles. Maybe modified! * */ int MkWinChildBuiltInExecChild(void *pvWorker, const char *pszExecutable, char **papszArgs, BOOL fQuotedArgv, char **papszEnvVars, const char *pszCwd, BOOL pafReplace[3], HANDLE pahReplace[3]) { PWINCHILDCAREWORKER pWorker = (PWINCHILDCAREWORKER)pvWorker; WCHAR *pwszSearchPath = NULL; WCHAR *pwszzEnvironment = NULL; WCHAR *pwszCommandLine = NULL; WCHAR *pwszImageName = NULL; WCHAR *pwszCwd = NULL; BOOL fNeedShell = FALSE; PWINCHILD pChild; int rc; assert(pWorker->uMagic == WINCHILDCAREWORKER_MAGIC); pChild = pWorker->pCurChild; assert(pChild != NULL && pChild->uMagic == WINCHILD_MAGIC); /* * Convert the CWD first since it's optional and we don't need to clean * up anything here if it fails. */ if (pszCwd) { size_t cchCwd = strlen(pszCwd); int cwcCwd = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszCwd, cchCwd + 1, NULL, 0); pwszCwd = xmalloc((cwcCwd + 1) * sizeof(WCHAR)); /* (+1 in case cwcCwd is 0) */ cwcCwd = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszCwd, cchCwd + 1, pwszCwd, cwcCwd + 1); if (!cwcCwd) { rc = GetLastError(); MkWinChildError(pWorker, 1, _("MultiByteToWideChar failed to convert CWD (%s): %u\n"), pszCwd, (unsigned)rc); return rc; } } /* * Before we search for the image, we convert the environment so we don't * have to traverse it twice to find the PATH. */ rc = mkWinChildcareWorkerConvertEnvironment(pWorker, papszEnvVars ? papszEnvVars : environ, 0/*cbEnvStrings*/, &pwszzEnvironment, &pwszSearchPath); /* * Find the executable and maybe checking if it's a shell script, then * convert it to a command line. */ if (rc == 0) rc = mkWinChildcareWorkerFindImage(pWorker, pszExecutable, pwszSearchPath, pwszzEnvironment, NULL /*pszShell*/, &pwszImageName, &fNeedShell, &pChild->fProbableClExe); if (rc == 0) { assert(!fNeedShell); if (!fQuotedArgv) rc = mkWinChildcareWorkerConvertCommandline(pWorker, papszArgs, 0 /*fFlags*/, &pwszCommandLine); else rc = mkWinChildcareWorkerConvertQuotedArgvToCommandline(pWorker, papszArgs, &pwszCommandLine); /* * Create the child process. */ if (rc == 0) { HANDLE hProcess; rc = mkWinChildcareWorkerCreateProcess(pWorker, pwszImageName, pwszCommandLine, pwszzEnvironment, pwszCwd, pafReplace, pahReplace, TRUE /*fCatchOutput*/, &hProcess); if (rc == 0) { /* * Wait for the child to complete. */ rc = mkWinChildcareWorkerWaitForProcess(pWorker, pChild, hProcess, pwszImageName, TRUE /*fCatchOutput*/); CloseHandle(hProcess); } } } free(pwszCwd); free(pwszCommandLine); free(pwszImageName); free(pwszzEnvironment); return rc; } #endif /* CONFIG_NEW_WIN_CHILDREN */ /** * Interface used to kill process when processing Ctrl-C and fatal errors. * * @returns 0 on success, -1 & errno on error. * @param pid The process to kill (PWINCHILD). * @param iSignal What to kill it with. * @param pMkChild The make child structure for validation. */ int MkWinChildKill(pid_t pid, int iSignal, struct child *pMkChild) { PWINCHILD pChild = (PWINCHILD)pid; if (pChild) { assert(pChild->uMagic == WINCHILD_MAGIC); if (pChild->uMagic == WINCHILD_MAGIC) { switch (pChild->enmType) { case WINCHILDTYPE_PROCESS: assert(pChild->pMkChild == pMkChild); TerminateProcess(pChild->u.Process.hProcess, DBG_TERMINATE_PROCESS); pChild->iSignal = iSignal; break; #ifdef KMK case WINCHILDTYPE_SUBMIT: { pChild->iSignal = iSignal; SetEvent(pChild->u.Submit.hEvent); break; } case WINCHILDTYPE_REDIRECT: TerminateProcess(pChild->u.Redirect.hProcess, DBG_TERMINATE_PROCESS); pChild->iSignal = iSignal; break; case WINCHILDTYPE_BUILT_IN: break; #endif /* KMK */ default: assert(0); } } } return -1; } /** * Wait for a child process to complete * * @returns 0 on success, windows error code on failure. * @param fBlock Whether to block. * @param pPid Where to return the pid if a child process * completed. This is set to zero if none. * @param piExitCode Where to return the exit code. * @param piSignal Where to return the exit signal number. * @param pfCoreDumped Where to return the core dumped indicator. * @param ppMkChild Where to return the associated struct child pointer. */ int MkWinChildWait(int fBlock, pid_t *pPid, int *piExitCode, int *piSignal, int *pfCoreDumped, struct child **ppMkChild) { PWINCHILD pChild; #ifdef DEBUG_STDOUT_CLOSE_ISSUE my_check_stdout ("MkWinChildWait/entry"); #endif *pPid = 0; *piExitCode = -222222; *pfCoreDumped = 0; *ppMkChild = NULL; /* * Wait if necessary. */ if (fBlock && !g_pTailCompletedChildren && g_cPendingChildren > 0) { DWORD dwStatus = WaitForSingleObject(g_hEvtWaitChildren, INFINITE); #ifdef DEBUG_STDOUT_CLOSE_ISSUE my_check_stdout ("MkWinChildWait/wakeup"); #endif if (dwStatus == WAIT_FAILED) return (int)GetLastError(); } /* * Try unlink the last child in the LIFO. */ pChild = g_pTailCompletedChildren; if (!pChild) return 0; pChild = mkWinChildDequeFromLifo(&g_pTailCompletedChildren, pChild); assert(pChild); /* * Set return values and ditch the child structure. */ *pPid = pChild->pid; *piExitCode = pChild->iExitCode; *pfCoreDumped = pChild->fCoreDumped; *ppMkChild = pChild->pMkChild; switch (pChild->enmType) { case WINCHILDTYPE_PROCESS: break; #ifdef KMK case WINCHILDTYPE_BUILT_IN: case WINCHILDTYPE_APPEND: case WINCHILDTYPE_SUBMIT: case WINCHILDTYPE_REDIRECT: break; #endif /* KMK */ default: assert(0); } mkWinChildDelete(pChild); #ifdef KMK /* Flush the volatile directory cache. */ dir_cache_invalid_after_job(); #endif #ifdef DEBUG_STDOUT_CLOSE_ISSUE my_check_stdout ("MkWinChildWait/tail"); #endif return 0; } /** * Get the child completed event handle. * * Needed when w32os.c is waiting for a job token to become available, given * that completed children is the typical source of these tokens (esp. for kmk). * * @returns Zero if no active children, event handle if waiting is required. */ intptr_t MkWinChildGetCompleteEventHandle(void) { /* We don't return the handle if we've got completed children. This is a safe guard against being called twice in a row without any MkWinChildWait call inbetween. */ if (!g_pTailCompletedChildren) return (intptr_t)g_hEvtWaitChildren; return 0; } /** * Emulate execv() for restarting kmk after one or more makefiles has been made. * * Does not return. * * @param papszArgs The arguments. * @param papszEnv The environment. */ void MkWinChildReExecMake(char **papszArgs, char **papszEnv) { PROCESS_INFORMATION ProcInfo; STARTUPINFOW StartupInfo; WCHAR *pwszCommandLine; WCHAR *pwszzEnvironment; WCHAR *pwszPathIgnored; int rc; #ifdef DEBUG_STDOUT_CLOSE_ISSUE my_check_stdout("MkWinChildReExecMake/entry"); #endif /* * Get the executable name. */ WCHAR wszImageName[MKWINCHILD_MAX_PATH]; DWORD cwcImageName = GetModuleFileNameW(GetModuleHandle(NULL), wszImageName, MKWINCHILD_MAX_PATH); if (cwcImageName == 0) ON(fatal, NILF, _("MkWinChildReExecMake: GetModuleFileName failed: %u\n"), GetLastError()); /* * Create the command line and environment. */ rc = mkWinChildcareWorkerConvertCommandline(NULL, papszArgs, 0 /*fFlags*/, &pwszCommandLine); if (rc != 0) ON(fatal, NILF, _("MkWinChildReExecMake: mkWinChildcareWorkerConvertCommandline failed: %u\n"), rc); rc = mkWinChildcareWorkerConvertEnvironment(NULL, papszEnv ? papszEnv : environ, 0 /*cbEnvStrings*/, &pwszzEnvironment, &pwszPathIgnored); if (rc != 0) ON(fatal, NILF, _("MkWinChildReExecMake: mkWinChildcareWorkerConvertEnvironment failed: %u\n"), rc); #ifdef KMK /* * Flush the file system cache to avoid messing up tools fetching * going on in the "exec'ed" make by keeping directories open. */ dir_cache_invalid_all_and_close_dirs(1); #endif /* * Fill out the startup info and try create the process. */ memset(&ProcInfo, 0, sizeof(ProcInfo)); memset(&StartupInfo, 0, sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); GetStartupInfoW(&StartupInfo); if (!CreateProcessW(wszImageName, pwszCommandLine, NULL /*pProcSecAttr*/, NULL /*pThreadSecAttr*/, TRUE /*fInheritHandles*/, CREATE_UNICODE_ENVIRONMENT, pwszzEnvironment, NULL /*pwsz*/, &StartupInfo, &ProcInfo)) ON(fatal, NILF, _("MkWinChildReExecMake: CreateProcessW failed: %u\n"), GetLastError()); CloseHandle(ProcInfo.hThread); /* * Wait for it to complete and forward the status code to our parent. */ for (;;) { DWORD dwExitCode = -2222; DWORD dwStatus = WaitForSingleObject(ProcInfo.hProcess, INFINITE); if ( dwStatus == WAIT_IO_COMPLETION || dwStatus == WAIT_TIMEOUT /* whatever */) continue; /* however unlikely, these aren't fatal. */ /* Get the status code and terminate. */ if (dwStatus == WAIT_OBJECT_0) { if (!GetExitCodeProcess(ProcInfo.hProcess, &dwExitCode)) { ON(fatal, NILF, _("MkWinChildReExecMake: GetExitCodeProcess failed: %u\n"), GetLastError()); dwExitCode = -2222; } } else if (dwStatus) dwExitCode = dwStatus; CloseHandle(ProcInfo.hProcess); #ifdef DEBUG_STDOUT_CLOSE_ISSUE my_check_stdout("MkWinChildReExecMake/exit"); #endif for (;;) exit(dwExitCode); } } #ifdef WITH_RW_LOCK /** Serialization with kmkbuiltin_redirect. */ void MkWinChildExclusiveAcquire(void) { AcquireSRWLockExclusive(&g_RWLock); } /** Serialization with kmkbuiltin_redirect. */ void MkWinChildExclusiveRelease(void) { ReleaseSRWLockExclusive(&g_RWLock); } #endif /* WITH_RW_LOCK */ /** * Implementation of the CLOSE_ON_EXEC macro. * * @returns errno value. * @param fd The file descriptor to hide from children. */ int MkWinChildUnrelatedCloseOnExec(int fd) { if (fd >= 0) { HANDLE hNative = (HANDLE)_get_osfhandle(fd); if (hNative != INVALID_HANDLE_VALUE && hNative != NULL) { if (SetHandleInformation(hNative, HANDLE_FLAG_INHERIT /*clear*/ , 0 /*set*/)) return 0; } return errno; } return EINVAL; } kbuild-3686/src/kmk/w32/imagecache.c0000664000175000017500000001661515053010074017116 0ustar locutuslocutus/* $Id: imagecache.c 3195 2018-03-27 18:09:23Z bird $ */ /** @file * kBuild specific executable image cache for Windows. */ /* * Copyright (c) 2012 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /* No GNU coding style here! */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #include "makeint.h" #include /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ typedef struct EXECCACHEENTRY { /** The name hash value. */ unsigned uHash; /** The name length. */ unsigned cwcName; /** Pointer to the next name with the same hash. */ struct EXECCACHEENTRY *pNext; /** When it was last referenced. */ unsigned uLastRef; /** The module handle, LOAD_LIBRARY_AS_DATAFILE. */ HMODULE hmod1; /** The module handle, DONT_RESOLVE_DLL_REFERENCES. */ HMODULE hmod2; /** The executable path. */ wchar_t wszName[1]; } EXECCACHEENTRY; typedef EXECCACHEENTRY *PEXECCACHEENTRY; /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ /** Critical section serializing all access. */ static CRITICAL_SECTION g_CritSect; /** Set if initialized. */ static int volatile g_fInitialized = 0; /** The number of cached images. */ static unsigned g_cCached; /** Used noting when entries was last used. * Increased on each kmk_cache_exec_image call. */ static unsigned g_uNow; /** The size of the hash table. */ #define EXECCACHE_HASHTAB_SIZE 128 /** The hash table. */ static PEXECCACHEENTRY g_apHashTab[EXECCACHE_HASHTAB_SIZE]; /** A sleepy approach to do-once. */ static void kmk_cache_lazy_init(void) { if (_InterlockedCompareExchange(&g_fInitialized, -1, 0) == 0) { InitializeCriticalSection(&g_CritSect); _InterlockedExchange(&g_fInitialized, 1); } else while (g_fInitialized != 1) Sleep(1); } /* sdbm: This algorithm was created for sdbm (a public-domain reimplementation of ndbm) database library. it was found to do well in scrambling bits, causing better distribution of the keys and fewer splits. it also happens to be a good general hashing function with good distribution. the actual function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below is the faster version used in gawk. [there is even a faster, duff-device version] the magic constant 65599 was picked out of thin air while experimenting with different constants, and turns out to be a prime. this is one of the algorithms used in berkeley db (see sleepycat) and elsewhere. */ static unsigned execcache_calc_hash(const wchar_t *pwsz, size_t *pcch) { wchar_t const * const pwszStart = pwsz; unsigned hash = 0; int ch; while ((ch = *pwsz++) != L'\0') hash = ch + (hash << 6) + (hash << 16) - hash; *pcch = (size_t)(pwsz - pwszStart - 1); return hash; } /** * Caches two memory mappings of the specified image so that it isn't flushed * from the kernel's cache mananger. * * Not sure exactly how much this actually helps, but whatever... * * @param pwszExec The executable. */ extern void kmk_cache_exec_image_w(const wchar_t *pwszExec) { /* * Prepare name lookup and to lazy init. */ size_t cwcName; const unsigned uHash = execcache_calc_hash(pwszExec, &cwcName); PEXECCACHEENTRY *ppCur = &g_apHashTab[uHash % EXECCACHE_HASHTAB_SIZE]; PEXECCACHEENTRY pCur; if (g_fInitialized != 1) kmk_cache_lazy_init(); /* * Do the lookup. */ EnterCriticalSection(&g_CritSect); pCur = *ppCur; while (pCur) { if ( pCur->uHash == uHash && pCur->cwcName == cwcName && !memcmp(pCur->wszName, pwszExec, cwcName * sizeof(wchar_t))) { pCur->uLastRef = ++g_uNow; LeaveCriticalSection(&g_CritSect); return; } ppCur = &pCur->pNext; pCur = pCur->pNext; } LeaveCriticalSection(&g_CritSect); /* * Not found, create a new entry. */ pCur = xmalloc(sizeof(*pCur) + cwcName * sizeof(wchar_t)); pCur->uHash = uHash; pCur->cwcName = (unsigned)cwcName; pCur->pNext = NULL; pCur->uLastRef = ++g_uNow; memcpy(pCur->wszName, pwszExec, (cwcName + 1) * sizeof(wchar_t)); pCur->hmod1 = LoadLibraryExW(pwszExec, NULL, LOAD_LIBRARY_AS_DATAFILE); if (pCur->hmod1 != NULL) pCur->hmod2 = LoadLibraryExW(pwszExec, NULL, DONT_RESOLVE_DLL_REFERENCES); else pCur->hmod2 = NULL; /* * Insert it. * Take into account that we might've been racing other threads, * fortunately we don't evict anything from the cache. */ EnterCriticalSection(&g_CritSect); if (*ppCur != NULL) { /* Find new end of chain and check for duplicate. */ PEXECCACHEENTRY pCur2 = *ppCur; while (pCur2) { if ( pCur->uHash == uHash && pCur->cwcName == cwcName && !memcmp(pCur->wszName, pwszExec, cwcName * sizeof(wchar_t))) break; ppCur = &pCur->pNext; pCur = pCur->pNext; } } if (*ppCur == NULL) { *ppCur = pCur; g_cCached++; LeaveCriticalSection(&g_CritSect); } else { LeaveCriticalSection(&g_CritSect); if (pCur->hmod1 != NULL) FreeLibrary(pCur->hmod1); if (pCur->hmod2 != NULL) FreeLibrary(pCur->hmod2); free(pCur); } } extern void kmk_cache_exec_image_a(const char *pszExec) { wchar_t wszExec[260]; int cwc = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszExec, strlen(pszExec) + 1, wszExec, 260); if (cwc > 0) kmk_cache_exec_image_w(wszExec); } kbuild-3686/src/kmk/w32/w32os.c0000664000175000017500000001404515053010075016021 0ustar locutuslocutus/* Windows32-based operating system interface for GNU Make. Copyright (C) 2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include "makeint.h" #include #include #include #include #include #include "pathstuff.h" #ifndef CONFIG_NEW_WIN_CHILDREN # include "sub_proc.h" #else # include "winchildren.h" #endif #include "w32err.h" #include "os.h" #include "debug.h" /* This section provides OS-specific functions to support the jobserver. */ static char jobserver_semaphore_name[MAX_PATH + 1]; static HANDLE jobserver_semaphore = NULL; unsigned int jobserver_setup (int slots) { #ifndef CONFIG_NEW_WIN_CHILDREN /* sub_proc.c cannot wait for more than MAXIMUM_WAIT_OBJECTS objects * and one of them is the job-server semaphore object. Limit the * number of available job slots to (MAXIMUM_WAIT_OBJECTS - 1). */ if (slots >= MAXIMUM_WAIT_OBJECTS) { slots = MAXIMUM_WAIT_OBJECTS - 1; DB (DB_JOBS, (_("Jobserver slots limited to %d\n"), slots)); } #endif sprintf (jobserver_semaphore_name, "gmake_semaphore_%d", _getpid ()); jobserver_semaphore = CreateSemaphore ( NULL, /* Use default security descriptor */ slots, /* Initial count */ slots, /* Maximum count */ jobserver_semaphore_name); /* Semaphore name */ if (jobserver_semaphore == NULL) { DWORD err = GetLastError (); const char *estr = map_windows32_error_to_string (err); ONS (fatal, NILF, _("creating jobserver semaphore: (Error %ld: %s)"), err, estr); } return 1; } unsigned int jobserver_parse_auth (const char *auth) { jobserver_semaphore = OpenSemaphore ( SEMAPHORE_ALL_ACCESS, /* Semaphore access setting */ FALSE, /* Child processes DON'T inherit */ auth); /* Semaphore name */ if (jobserver_semaphore == NULL) { DWORD err = GetLastError (); const char *estr = map_windows32_error_to_string (err); fatal (NILF, strlen (auth) + INTSTR_LENGTH + strlen (estr), _("internal error: unable to open jobserver semaphore '%s': (Error %ld: %s)"), auth, err, estr); } DB (DB_JOBS, (_("Jobserver client (semaphore %s)\n"), auth)); return 1; } char * jobserver_get_auth () { return xstrdup (jobserver_semaphore_name); } unsigned int jobserver_enabled () { return jobserver_semaphore != NULL; } /* Close jobserver semaphore */ void jobserver_clear () { if (jobserver_semaphore != NULL) { CloseHandle (jobserver_semaphore); jobserver_semaphore = NULL; } } void jobserver_release (int is_fatal) { if (! ReleaseSemaphore ( jobserver_semaphore, /* handle to semaphore */ 1, /* increase count by one */ NULL)) /* not interested in previous count */ { if (is_fatal) { DWORD err = GetLastError (); const char *estr = map_windows32_error_to_string (err); ONS (fatal, NILF, _("release jobserver semaphore: (Error %ld: %s)"), err, estr); } perror_with_name ("release_jobserver_semaphore", ""); } } unsigned int jobserver_acquire_all () { unsigned int tokens = 0; while (1) { DWORD dwEvent = WaitForSingleObject ( jobserver_semaphore, /* Handle to semaphore */ 0); /* DON'T wait on semaphore */ if (dwEvent != WAIT_OBJECT_0) return tokens; ++tokens; } } void jobserver_signal () { } void jobserver_pre_child (int recursive) { } void jobserver_post_child (int recursive) { } void jobserver_pre_acquire () { } /* Returns 1 if we got a token, or 0 if a child has completed. The Windows implementation doesn't support load detection. */ unsigned int jobserver_acquire (int timeout) { #ifndef CONFIG_NEW_WIN_CHILDREN HANDLE handles[MAXIMUM_WAIT_OBJECTS + 1]; /* bird: + 1 to prevent trashing the stack. */ #else HANDLE handles[2]; #endif DWORD dwHandleCount; DWORD dwEvent; /* Add jobserver semaphore to first slot. */ handles[0] = jobserver_semaphore; #ifndef CONFIG_NEW_WIN_CHILDREN /* Build array of handles to wait for. */ dwHandleCount = 1 + process_set_handles (&handles[1]); dwEvent = WaitForMultipleObjects ( dwHandleCount, /* number of objects in array */ handles, /* array of objects */ FALSE, /* wait for any object */ INFINITE); /* wait until object is signalled */ #else /* Add the completed children event as the 2nd one. */ handles[1] = (HANDLE)MkWinChildGetCompleteEventHandle (); if (handles[1] == NULL) return 0; dwHandleCount = 2; dwEvent = WaitForMultipleObjectsEx (dwHandleCount, handles, FALSE /*bWaitAll*/, 256, /* INFINITE - paranoia, only wait 256 ms before checking again. */ TRUE /*bAlertable*/); #endif if (dwEvent == WAIT_FAILED) { DWORD err = GetLastError (); const char *estr = map_windows32_error_to_string (err); ONS (fatal, NILF, _("semaphore or child process wait: (Error %ld: %s)"), err, estr); } /* WAIT_OBJECT_0 indicates that the semaphore was signalled. */ return dwEvent == WAIT_OBJECT_0; } kbuild-3686/src/kmk/w32/Makefile.kup0000664000175000017500000000000015053010075017120 0ustar locutuslocutuskbuild-3686/src/kmk/w32/pathstuff.c0000664000175000017500000002274515053010075017056 0ustar locutuslocutus/* Path conversion for Windows pathnames. Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include "makeint.h" #include #include #include "pathstuff.h" #if 1 /* bird */ # include "nt_fullpath.h" # include #endif /* * Convert delimiter separated vpath to Canonical format. */ char * convert_vpath_to_windows32(char *Path, char to_delim) { char *etok; /* token separator for old Path */ /* * Convert all spaces to delimiters. Note that pathnames which * contain blanks get trounced here. Use 8.3 format as a workaround. */ for (etok = Path; etok && *etok; etok++) if (ISBLANK ((unsigned char) *etok)) *etok = to_delim; return (convert_Path_to_windows32(Path, to_delim)); } /* * Convert delimiter separated path to Canonical format. */ char * convert_Path_to_windows32(char *Path, char to_delim) { char *etok; /* token separator for old Path */ char *p; /* points to element of old Path */ /* is this a multi-element Path ? */ /* FIXME: Perhaps use ":;\"" in strpbrk to convert all quotes to delimiters as well, as a way to handle quoted directories in PATH? */ for (p = Path, etok = strpbrk(p, ":;"); etok; etok = strpbrk(p, ":;")) if ((etok - p) == 1) { if (*(etok - 1) == ';' || *(etok - 1) == ':') { etok[-1] = to_delim; etok[0] = to_delim; p = ++etok; continue; /* ignore empty bucket */ } else if (!isalpha ((unsigned char) *p)) { /* found one to count, handle things like '.' */ *etok = to_delim; p = ++etok; } else if ((*etok == ':') && (etok = strpbrk(etok+1, ":;"))) { /* found one to count, handle drive letter */ *etok = to_delim; p = ++etok; } else /* all finished, force abort */ p += strlen(p); } else if (*p == '"') { /* a quoted directory */ for (p++; *p && *p != '"'; p++) /* skip quoted part */ ; etok = strpbrk(p, ":;"); /* find next delimiter */ if (etok) { *etok = to_delim; p = ++etok; } else p += strlen(p); } else { /* found another one, no drive letter */ *etok = to_delim; p = ++etok; } return Path; } /* * Convert to forward slashes directly (w32ify(filename, 0)). */ char *unix_slashes(char *filename) /* bird */ { char *slash = filename ; while ((slash = strchr(slash, '\\')) != NULL) *slash++ = '/'; return filename; } /* * Resolve and convert to forward slashes directly (w32ify(filename, 1)). * Returns if out of buffer space. */ char *unix_slashes_resolved(const char *src, char *dst, unsigned len) { assert(len >= FILENAME_MAX); *dst = '\0'; /** @todo nt_fullpath_cached needs to return some indication of overflow. */ #if 1 nt_fullpath_cached(src, dst, len); #else _fullpath(dst, src, len); #endif return unix_slashes(dst); } #if 0 /* bird: replaced by unix_slashes and unix_slahes_resolved. */ /* * Convert to forward slashes. Resolve to full pathname optionally */ char * w32ify(const char *filename, int resolve) { static char w32_path[FILENAME_MAX]; #if 1 /* bird */ if (resolve) { nt_fullpath_cached(filename, w32_path, sizeof(w32_path)); } else { w32_path[0] = '\0'; strncat(w32_path, filename, sizeof(w32_path)); } return unix_slashes(w32_path); #else /* !bird */ char *p; if (resolve) { _fullpath(w32_path, filename, sizeof (w32_path)); } else strncpy(w32_path, filename, sizeof (w32_path)); for (p = w32_path; p && *p; p++) if (*p == '\\') *p = '/'; return w32_path; #endif /* !bird */ } #endif char * getcwd_fs(char* buf, int len) { char *p = getcwd(buf, len); if (p) { #if 1 p = unix_slashes(p); #else char *q = w32ify(buf, 0); #if 1 /* bird - UPSTREAM? */ buf[0] = '\0'; strncat(buf, q, len); #else /* !bird */ strncpy(buf, q, len); #endif #endif } return p; } #ifdef unused /* * Convert delimiter separated pathnames (e.g. PATH) or single file pathname * (e.g. c:/foo, c:\bar) to NutC format. If we are handed a string that * _NutPathToNutc() fails to convert, just return the path we were handed * and assume the caller will know what to do with it (It was probably * a mistake to try and convert it anyway due to some of the bizarre things * that might look like pathnames in makefiles). */ char * convert_path_to_nutc(char *path) { int count; /* count of path elements */ char *nutc_path; /* new NutC path */ int nutc_path_len; /* length of buffer to allocate for new path */ char *pathp; /* pointer to nutc_path used to build it */ char *etok; /* token separator for old path */ char *p; /* points to element of old path */ char sep; /* what flavor of separator used in old path */ char *rval; /* is this a multi-element path ? */ for (p = path, etok = strpbrk(p, ":;"), count = 0; etok; etok = strpbrk(p, ":;")) if ((etok - p) == 1) { if (*(etok - 1) == ';' || *(etok - 1) == ':') { p = ++etok; continue; /* ignore empty bucket */ } else if (etok = strpbrk(etok+1, ":;")) /* found one to count, handle drive letter */ p = ++etok, count++; else /* all finished, force abort */ p += strlen(p); } else /* found another one, no drive letter */ p = ++etok, count++; if (count) { count++; /* x1;x2;x3 <- need to count x3 */ /* * Hazard a guess on how big the buffer needs to be. * We have to convert things like c:/foo to /c=/foo. */ nutc_path_len = strlen(path) + (count*2) + 1; nutc_path = xmalloc(nutc_path_len); pathp = nutc_path; *pathp = '\0'; /* * Loop through PATH and convert one elemnt of the path at at * a time. Single file pathnames will fail this and fall * to the logic below loop. */ for (p = path, etok = strpbrk(p, ":;"); etok; etok = strpbrk(p, ":;")) { /* don't trip up on device specifiers or empty path slots */ if ((etok - p) == 1) if (*(etok - 1) == ';' || *(etok - 1) == ':') { p = ++etok; continue; } else if ((etok = strpbrk(etok+1, ":;")) == NULL) break; /* thing found was a WINDOWS32 pathname */ /* save separator */ sep = *etok; /* terminate the current path element -- temporarily */ *etok = '\0'; #ifdef __NUTC__ /* convert to NutC format */ if (_NutPathToNutc(p, pathp, 0) == FALSE) { free(nutc_path); rval = savestring(path, strlen(path)); return rval; } #else *pathp++ = '/'; *pathp++ = p[0]; *pathp++ = '='; *pathp++ = '/'; strcpy(pathp, &p[2]); #endif pathp += strlen(pathp); *pathp++ = ':'; /* use Unix style path separtor for new path */ *pathp = '\0'; /* make sure we are null terminaed */ /* restore path separator */ *etok = sep; /* point p to first char of next path element */ p = ++etok; } } else { nutc_path_len = strlen(path) + 3; nutc_path = xmalloc(nutc_path_len); pathp = nutc_path; *pathp = '\0'; p = path; } /* * OK, here we handle the last element in PATH (e.g. c of a;b;c) * or the path was a single filename and will be converted * here. Note, testing p here assures that we don't trip up * on paths like a;b; which have trailing delimiter followed by * nothing. */ if (*p != '\0') { #ifdef __NUTC__ if (_NutPathToNutc(p, pathp, 0) == FALSE) { free(nutc_path); rval = savestring(path, strlen(path)); return rval; } #else *pathp++ = '/'; *pathp++ = p[0]; *pathp++ = '='; *pathp++ = '/'; strcpy(pathp, &p[2]); #endif } else *(pathp-1) = '\0'; /* we're already done, don't leave trailing : */ rval = savestring(nutc_path, strlen(nutc_path)); free(nutc_path); return rval; } #endif kbuild-3686/src/kmk/w32/compat/0000775000175000017500000000000015053010075016157 5ustar locutuslocutuskbuild-3686/src/kmk/w32/compat/posixfcn.c0000664000175000017500000003517015053010074020161 0ustar locutuslocutus/* Replacements for Posix functions and Posix functionality for MS-Windows. Copyright (C) 2013-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include #include #include #include #include #include "dlfcn.h" #include "makeint.h" #include "job.h" #ifndef NO_OUTPUT_SYNC /* Support for OUTPUT_SYNC and related functionality. */ /* Emulation of fcntl that supports only F_GETFD and F_SETLKW. */ int fcntl (intptr_t fd, int cmd, ...) { va_list ap; va_start (ap, cmd); switch (cmd) { case F_GETFD: va_end (ap); /* Could have used GetHandleInformation, but that isn't supported on Windows 9X. */ if (_get_osfhandle (fd) == -1) return -1; return 0; case F_SETLKW: { void *buf = va_arg (ap, void *); struct flock *fl = (struct flock *)buf; HANDLE hmutex = (HANDLE)fd; static struct flock last_fl; short last_type = last_fl.l_type; va_end (ap); if (hmutex == INVALID_HANDLE_VALUE || !hmutex) return -1; last_fl = *fl; switch (fl->l_type) { case F_WRLCK: { DWORD result; if (last_type == F_WRLCK) { /* Don't call WaitForSingleObject if we already own the mutex, because doing so will require us to call ReleaseMutex an equal number of times, before the mutex is actually released. */ return 0; } result = WaitForSingleObject (hmutex, INFINITE); switch (result) { case WAIT_OBJECT_0: /* We don't care if the mutex owner crashed or exited. */ case WAIT_ABANDONED: return 0; case WAIT_FAILED: case WAIT_TIMEOUT: /* cannot happen, really */ { DWORD err = GetLastError (); /* Invalidate the last command. */ memset (&last_fl, 0, sizeof (last_fl)); switch (err) { case ERROR_INVALID_HANDLE: case ERROR_INVALID_FUNCTION: errno = EINVAL; return -1; default: errno = EDEADLOCK; return -1; } } } } case F_UNLCK: { /* FIXME: Perhaps we should call ReleaseMutex repatedly until it errors out, to make sure the mutext is released even if we somehow managed to to take ownership multiple times? */ BOOL status = ReleaseMutex (hmutex); if (status) return 0; else { DWORD err = GetLastError (); if (err == ERROR_NOT_OWNER) errno = EPERM; else { memset (&last_fl, 0, sizeof (last_fl)); errno = EINVAL; } return -1; } } default: errno = ENOSYS; return -1; } } default: errno = ENOSYS; va_end (ap); return -1; } } static intptr_t mutex_handle = -1; /* Record in a static variable the mutex handle we were requested to use. That nameless mutex was created by the top-level Make, and its handle was passed to us via inheritance. The value of that handle is passed via the command-line arguments, so that we know which handle to use. */ void record_sync_mutex (const char *str) { #ifdef CONFIG_NEW_WIN_CHILDREN HANDLE hmtx = OpenMutexA(SYNCHRONIZE, FALSE /*fInheritable*/, str); if (hmtx) mutex_handle = (intptr_t)hmtx; else { mutex_handle = -1; errno = ENOENT; } #else char *endp; intptr_t hmutex = strtol (str, &endp, 16); if (*endp == '\0') mutex_handle = hmutex; else { mutex_handle = -1; errno = EINVAL; } #endif } /* Create a new mutex or reuse one created by our parent. */ intptr_t #ifdef CONFIG_NEW_WIN_CHILDREN create_mutex (char *mtxname, size_t size) #else create_mutex (void) #endif { #ifndef CONFIG_NEW_WIN_CHILDREN SECURITY_ATTRIBUTES secattr; #endif intptr_t hmutex = -1; /* If we have a mutex handle passed from the parent Make, just use that. */ if (mutex_handle > 0) { #ifdef CONFIG_NEW_WIN_CHILDREN mtxname[0] = '\0'; #endif return mutex_handle; } #ifdef CONFIG_NEW_WIN_CHILDREN /* We're the top-level Make. Child Make processes will open our mutex, since children does not inherit any handles other than the three standard ones. */ snprintf(mtxname, size, "Make-output-%u-%u-%u", GetCurrentProcessId(), GetCurrentThreadId(), GetTickCount()); hmutex = (intptr_t)CreateMutexA (NULL, FALSE /*Locked*/, mtxname); #else /* We are the top-level Make, and we want the handle to be inherited by our child processes. */ secattr.nLength = sizeof (secattr); secattr.lpSecurityDescriptor = NULL; /* use default security descriptor */ secattr.bInheritHandle = TRUE; hmutex = (intptr_t)CreateMutex (&secattr, FALSE, NULL); #endif if (!hmutex) { DWORD err = GetLastError (); fprintf (stderr, "CreateMutex: error %lu\n", err); errno = ENOLCK; hmutex = -1; } mutex_handle = hmutex; return hmutex; } /* Return non-zero if F1 and F2 are 2 streams representing the same file or pipe or device. */ int same_stream (FILE *f1, FILE *f2) { HANDLE fh1 = (HANDLE)_get_osfhandle (fileno (f1)); HANDLE fh2 = (HANDLE)_get_osfhandle (fileno (f2)); /* Invalid file descriptors get treated as different streams. */ if (fh1 && fh1 != INVALID_HANDLE_VALUE && fh2 && fh2 != INVALID_HANDLE_VALUE) { if (fh1 == fh2) return 1; else { DWORD ftyp1 = GetFileType (fh1), ftyp2 = GetFileType (fh2); if (ftyp1 != ftyp2 || ftyp1 == FILE_TYPE_UNKNOWN || ftyp2 == FILE_TYPE_UNKNOWN) return 0; else if (ftyp1 == FILE_TYPE_CHAR) { /* For character devices, check if they both refer to a console. This loses if both handles refer to the null device (FIXME!), but in that case we don't care in the context of Make. */ DWORD conmode1, conmode2; /* Each process on Windows can have at most 1 console, so if both handles are for the console device, they are the same. We also compare the console mode to distinguish between stdin and stdout/stderr. */ if (GetConsoleMode (fh1, &conmode1) && GetConsoleMode (fh2, &conmode2) && conmode1 == conmode2) return 1; } else { /* For disk files and pipes, compare their unique attributes. */ BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2; /* Pipes get zero in the volume serial number, but do appear to have meaningful information in file index attributes. We test file attributes as well, for a good measure. */ if (GetFileInformationByHandle (fh1, &bhfi1) && GetFileInformationByHandle (fh2, &bhfi2)) return (bhfi1.dwVolumeSerialNumber == bhfi2.dwVolumeSerialNumber && bhfi1.nFileIndexLow == bhfi2.nFileIndexLow && bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh && bhfi1.dwFileAttributes == bhfi2.dwFileAttributes); } } } return 0; } /* A replacement for tmpfile, since the MSVCRT implementation creates the file in the root directory of the current drive, which might not be writable by our user. Most of the code borrowed from create_batch_file, see job.c. */ FILE * tmpfile (void) { char temp_path[MAXPATHLEN]; unsigned path_size = GetTempPath (sizeof temp_path, temp_path); int path_is_dot = 0; /* The following variable is static so we won't try to reuse a name that was generated a little while ago, because that file might not be on disk yet, since we use FILE_ATTRIBUTE_TEMPORARY below, which tells the OS it doesn't need to flush the cache to disk. If the file is not yet on disk, we might think the name is available, while it really isn't. This happens in parallel builds, where Make doesn't wait for one job to finish before it launches the next one. */ static unsigned uniq = 0; static int second_loop = 0; const char base[] = "gmake_tmpf"; const unsigned sizemax = sizeof base - 1 + 4 + 10 + 10; unsigned pid = GetCurrentProcessId (); if (path_size == 0) { path_size = GetCurrentDirectory (sizeof temp_path, temp_path); path_is_dot = 1; } ++uniq; if (uniq >= 0x10000 && !second_loop) { /* If we already had 64K batch files in this process, make a second loop through the numbers, looking for free slots, i.e. files that were deleted in the meantime. */ second_loop = 1; uniq = 1; } while (path_size > 0 && path_size + sizemax < sizeof temp_path && !(uniq >= 0x10000 && second_loop)) { HANDLE h; sprintf (temp_path + path_size, "%s%s%u-%x.tmp", temp_path[path_size - 1] == '\\' ? "" : "\\", base, pid, uniq); h = CreateFile (temp_path, /* file name */ GENERIC_READ | GENERIC_WRITE | DELETE, /* desired access */ FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */ NULL, /* default security attributes */ CREATE_NEW, /* creation disposition */ FILE_ATTRIBUTE_NORMAL | /* flags and attributes */ FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL); /* no template file */ if (h == INVALID_HANDLE_VALUE) { const DWORD er = GetLastError (); if (er == ERROR_FILE_EXISTS || er == ERROR_ALREADY_EXISTS) { ++uniq; if (uniq == 0x10000 && !second_loop) { second_loop = 1; uniq = 1; } } /* The temporary path is not guaranteed to exist, or might not be writable by user. Use the current directory as fallback. */ else if (path_is_dot == 0) { path_size = GetCurrentDirectory (sizeof temp_path, temp_path); path_is_dot = 1; } else { errno = EACCES; break; } } else { int fd = _open_osfhandle ((intptr_t)h, 0); return _fdopen (fd, "w+b"); } } if (uniq >= 0x10000) errno = EEXIST; return NULL; } #endif /* !NO_OUTPUT_SYNC */ #if MAKE_LOAD /* Support for dynamic loading of objects. */ static DWORD last_err; void * dlopen (const char *file, int mode) { char dllfn[MAX_PATH], *p; HANDLE dllhandle; if ((mode & ~(RTLD_LAZY | RTLD_NOW | RTLD_GLOBAL)) != 0) { errno = EINVAL; last_err = ERROR_INVALID_PARAMETER; return NULL; } if (!file) dllhandle = GetModuleHandle (NULL); else { /* MSDN says to be sure to use backslashes in the DLL file name. */ strcpy (dllfn, file); for (p = dllfn; *p; p++) if (*p == '/') *p = '\\'; dllhandle = LoadLibrary (dllfn); } if (!dllhandle) last_err = GetLastError (); return dllhandle; } char * dlerror (void) { static char errbuf[1024]; DWORD ret; if (!last_err) return NULL; ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_err, 0, errbuf, sizeof (errbuf), NULL); while (ret > 0 && (errbuf[ret - 1] == '\n' || errbuf[ret - 1] == '\r')) --ret; errbuf[ret] = '\0'; if (!ret) sprintf (errbuf, "Error code %lu", last_err); last_err = 0; return errbuf; } void * dlsym (void *handle, const char *name) { FARPROC addr = NULL; if (!handle || handle == INVALID_HANDLE_VALUE) { last_err = ERROR_INVALID_PARAMETER; return NULL; } addr = GetProcAddress (handle, name); if (!addr) last_err = GetLastError (); return (void *)addr; } int dlclose (void *handle) { if (!handle || handle == INVALID_HANDLE_VALUE) return -1; if (!FreeLibrary (handle)) return -1; return 0; } #endif /* MAKE_LOAD */ /* MS runtime's isatty returns non-zero for any character device, including the null device, which is not what we want. */ int isatty (int fd) { HANDLE fh = (HANDLE) _get_osfhandle (fd); DWORD con_mode; if (fh == INVALID_HANDLE_VALUE) { errno = EBADF; return 0; } if (GetConsoleMode (fh, &con_mode)) return 1; errno = ENOTTY; return 0; } char * ttyname (int fd) { /* This "knows" that Make only asks about stdout and stderr. A more sophisticated implementation should test whether FD is open for input or output. We can do that by looking at the mode returned by GetConsoleMode. */ return "CONOUT$"; } kbuild-3686/src/kmk/w32/compat/Makefile.kup0000664000175000017500000000000015053010075020403 0ustar locutuslocutuskbuild-3686/src/kmk/w32/compat/dirent.c0000664000175000017500000001276315053010075017621 0ustar locutuslocutus/* Directory entry code for Window platforms. Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include #include #include #include #include #include #ifdef KMK_PRF # include #endif #include "dirent.h" DIR* opendir(const char* pDirName) { struct stat sb; DIR* pDir; char* pEndDirName; int nBufferLen; /* sanity checks */ if (!pDirName) { errno = EINVAL; return NULL; } if (stat(pDirName, &sb) != 0) { errno = ENOENT; return NULL; } if ((sb.st_mode & S_IFMT) != S_IFDIR) { errno = ENOTDIR; return NULL; } /* allocate a DIR structure to return */ pDir = (DIR *) malloc(sizeof (DIR)); if (!pDir) return NULL; /* input directory name length */ nBufferLen = strlen(pDirName); /* copy input directory name to DIR buffer */ strcpy(pDir->dir_pDirectoryName, pDirName); /* point to end of the copied directory name */ pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1]; /* if directory name did not end in '/' or '\', add '/' */ if ((*pEndDirName != '/') && (*pEndDirName != '\\')) { pEndDirName++; *pEndDirName = '/'; } /* now append the wildcard character to the buffer */ pEndDirName++; *pEndDirName = '*'; pEndDirName++; *pEndDirName = '\0'; /* other values defaulted */ pDir->dir_nNumFiles = 0; pDir->dir_hDirHandle = INVALID_HANDLE_VALUE; pDir->dir_ulCookie = __DIRENT_COOKIE; #ifdef KMK_PRF fprintf(stderr, "opendir(%s) -> %p\n", pDirName, pDir); #endif return pDir; } void closedir(DIR *pDir) { /* got a valid pointer? */ if (!pDir) { errno = EINVAL; return; } /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) { errno = EINVAL; return; } /* close the WINDOWS32 directory handle */ if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE) FindClose(pDir->dir_hDirHandle); free(pDir); return; } struct dirent * readdir(DIR* pDir) { WIN32_FIND_DATA wfdFindData; if (!pDir) { errno = EINVAL; return NULL; } /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) { errno = EINVAL; return NULL; } if (pDir->dir_nNumFiles == 0) { pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData); if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE) return NULL; } else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData)) return NULL; /* bump count for next call to readdir() or telldir() */ pDir->dir_nNumFiles++; /* fill in struct dirent values */ pDir->dir_sdReturn.d_ino = (ino_t)-1; strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName); return &pDir->dir_sdReturn; } void rewinddir(DIR* pDir) { if (!pDir) { errno = EINVAL; return; } /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) { errno = EINVAL; return; } /* close the WINDOWS32 directory handle */ if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE) if (!FindClose(pDir->dir_hDirHandle)) errno = EBADF; /* reset members which control readdir() */ pDir->dir_hDirHandle = INVALID_HANDLE_VALUE; pDir->dir_nNumFiles = 0; return; } int telldir(DIR* pDir) { if (!pDir) { errno = EINVAL; return -1; } /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) { errno = EINVAL; return -1; } /* return number of times readdir() called */ return pDir->dir_nNumFiles; } void seekdir(DIR* pDir, long nPosition) { if (!pDir) return; /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) return; /* go back to beginning of directory */ rewinddir(pDir); /* loop until we have found position we care about */ for (--nPosition; nPosition && readdir(pDir); nPosition--); /* flag invalid nPosition value */ if (nPosition) errno = EINVAL; return; } kbuild-3686/src/kmk/w32/subproc/0000775000175000017500000000000015053010075016351 5ustar locutuslocutuskbuild-3686/src/kmk/w32/subproc/misc.c0000664000175000017500000000453415053010075017456 0ustar locutuslocutus/* Process handling for Windows Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include #include #include #include #include #include "proc.h" /* * Description: Convert a NULL string terminated UNIX environment block to * an environment block suitable for a windows32 system call * * Returns: TRUE= success, FALSE=fail * * Notes/Dependencies: the environment block is sorted in case-insensitive * order, is double-null terminated, and is a char *, not a char ** */ int _cdecl compare(const void *a1, const void *a2) { return _stricoll(*((char**)a1),*((char**)a2)); } bool_t arr2envblk(char **arr, char **envblk_out, int *envsize_needed) { char **tmp; int size_needed; int arrcnt; char *ptr; arrcnt = 0; while (arr[arrcnt]) { arrcnt++; } tmp = (char**) calloc(arrcnt + 1, sizeof(char *)); if (!tmp) { return FALSE; } arrcnt = 0; size_needed = *envsize_needed = 0; while (arr[arrcnt]) { tmp[arrcnt] = arr[arrcnt]; size_needed += strlen(arr[arrcnt]) + 1; arrcnt++; } size_needed++; *envsize_needed = size_needed; qsort((void *) tmp, (size_t) arrcnt, sizeof (char*), compare); ptr = *envblk_out = calloc(size_needed, 1); if (!ptr) { free(tmp); return FALSE; } arrcnt = 0; while (tmp[arrcnt]) { strcpy(ptr, tmp[arrcnt]); ptr += strlen(tmp[arrcnt]) + 1; arrcnt++; } free(tmp); return TRUE; } kbuild-3686/src/kmk/w32/subproc/proc.h0000664000175000017500000000172115053010074017465 0ustar locutuslocutus/* Definitions for Windows Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #ifndef _PROC_H #define _PROC_H typedef int bool_t; #define E_SCALL 101 #define E_IO 102 #define E_NO_MEM 103 #define E_FORK 104 extern bool_t arr2envblk(char **arr, char **envblk_out, int *envsize_needed); #endif kbuild-3686/src/kmk/w32/subproc/w32err.c0000664000175000017500000000623615053010074017647 0ustar locutuslocutus/* Error handling for Windows Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include #include #include "makeint.h" #include "w32err.h" /* * Description: the windows32 version of perror() * * Returns: a pointer to a static error * * Notes/Dependencies: I got this from * comp.os.ms-windows.programmer.win32 */ const char * map_windows32_error_to_string (DWORD ercode) { /* * We used to have an MSVC-specific '__declspec (thread)' qualifier * here, with the following comment: * * __declspec (thread) necessary if you will use multiple threads on MSVC * * However, Make was never multithreaded on Windows (except when * Ctrl-C is hit, in which case the main thread is stopped * immediately, so it doesn't matter in this context). The functions * on sub_proc.c that started and stopped additional threads were * never used, and are now #ifdef'ed away. Until we need more than * one thread, we have no problems with the following buffer being * static. (If and when we do need it to be in thread-local storage, * the corresponding GCC qualifier is '__thread'.) */ static char szMessageBuffer[128]; /* Fill message buffer with a default message in * case FormatMessage fails */ #ifdef KMK /* Avoid unnecessary unsafe USER32.DLL sprintf. */ snprintf (szMessageBuffer, sizeof(szMessageBuffer), "Error %ld\n", ercode); #else wsprintf (szMessageBuffer, "Error %ld\n", ercode); #endif /* * Special code for winsock error handling. */ if (ercode > WSABASEERR) { #if 0 HMODULE hModule = GetModuleHandle("wsock32"); if (hModule != NULL) { FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, hModule, ercode, LANG_NEUTRAL, szMessageBuffer, sizeof(szMessageBuffer), NULL); FreeLibrary(hModule); } #else O (fatal, NILF, szMessageBuffer); #endif } else { /* * Default system message handling */ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ercode, LANG_NEUTRAL, szMessageBuffer, sizeof(szMessageBuffer), NULL); } return szMessageBuffer; } kbuild-3686/src/kmk/w32/subproc/NMakefile0000664000175000017500000000353215053010075020132 0ustar locutuslocutus# NOTE: If you have no 'make' program at all to process this makefile, run # 'build.bat' instead. # # Copyright (C) 1996-2016 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) any later # version. # # GNU Make 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, see . # # NMakefile for GNU Make (subproc library) # LIB = lib CC = cl MAKE = nmake OUTDIR=. MAKEFILE=NMakefile CFLAGS_any = /nologo /MT /W4 /GX /Z7 /YX /D WIN32 /D WINDOWS32 /D _WINDOWS -I. -I../include -I../../ CFLAGS_debug = $(CFLAGS_any) /Od /D _DEBUG /FR.\WinDebug\ /Fp.\WinDebug\subproc.pch /Fo.\WinDebug/ CFLAGS_release = $(CFLAGS_any) /O2 /FR.\WinRel\ /Fp.\WinRel\subproc.pch /Fo.\WinRel/ all: Release Debug Release: $(MAKE) /f $(MAKEFILE) OUTDIR=WinRel CFLAGS="$(CFLAGS_release)" WinRel/subproc.lib Debug: $(MAKE) /f $(MAKEFILE) OUTDIR=WinDebug CFLAGS="$(CFLAGS_debug)" WinDebug/subproc.lib clean: rmdir /s /q WinRel WinDebug erase *.pdb $(OUTDIR): if not exist .\$@\nul mkdir .\$@ OBJS = $(OUTDIR)/misc.obj $(OUTDIR)/w32err.obj $(OUTDIR)/sub_proc.obj $(OUTDIR)/subproc.lib: $(OUTDIR) $(OBJS) $(LIB) -out:$@ @<< $(OBJS) << .c{$(OUTDIR)}.obj: $(CC) $(CFLAGS) /c $< $(OUTDIR)/misc.obj: misc.c proc.h $(OUTDIR)/sub_proc.obj: sub_proc.c ../include/sub_proc.h ../include/w32err.h proc.h $(OUTDIR)/w32err.obj: w32err.c ../include/w32err.h kbuild-3686/src/kmk/w32/subproc/Makefile.kup0000664000175000017500000000000015053010074020574 0ustar locutuslocutuskbuild-3686/src/kmk/w32/subproc/sub_proc.c0000664000175000017500000015734215053010074020344 0ustar locutuslocutus/* Process handling for Windows. Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include #include #include #include /* for _get_osfhandle */ #ifdef _MSC_VER # include /* for intptr_t */ #else # include #endif #include #include /* for msvc _beginthreadex, _endthreadex */ #include #include #include "makeint.h" #include "filedef.h" #include "variable.h" #include "sub_proc.h" #include "proc.h" #include "w32err.h" #include "debug.h" #ifdef KMK # include # include "kmkbuiltin.h" extern void kmk_cache_exec_image_a(const char *); /* imagecache.c */ #endif static char *make_command_line(char *shell_name, char *exec_path, char **argv); typedef struct sub_process_t { #ifdef KMK enum { kRegular = 0, kSubmit, kSubProcFreed } enmType; intptr_t clue; #endif intptr_t sv_stdin[2]; intptr_t sv_stdout[2]; intptr_t sv_stderr[2]; int using_pipes; char *inp; DWORD incnt; char * volatile outp; volatile DWORD outcnt; char * volatile errp; volatile DWORD errcnt; pid_t pid; int exit_code; int signal; long last_err; long lerrno; } sub_process; static long process_file_io_private(sub_process *pproc, BOOL fNeedToWait); /* bird */ /* keep track of children so we can implement a waitpid-like routine */ static sub_process *proc_array[MAXIMUM_WAIT_OBJECTS]; static int proc_index = 0; static int fake_exits_pending = 0; /* * Fill a HANDLE list with handles to wait for. */ DWORD process_set_handles(HANDLE *handles) { DWORD count = 0; int i; /* Build array of handles to wait for */ for (i = 0; i < proc_index; i++) { /* Don't wait on child processes that have already finished */ if (fake_exits_pending && proc_array[i]->exit_code) continue; handles[count++] = (HANDLE) proc_array[i]->pid; } return count; } #ifndef KMK /* Inefficient! */ /* * When a process has been waited for, adjust the wait state * array so that we don't wait for it again */ static void process_adjust_wait_state(sub_process* pproc) { int i; if (!proc_index) return; for (i = 0; i < proc_index; i++) if (proc_array[i]->pid == pproc->pid) break; if (i < proc_index) { proc_index--; if (i != proc_index) memmove(&proc_array[i], &proc_array[i+1], (proc_index-i) * sizeof(sub_process*)); proc_array[proc_index] = NULL; } } #endif /* !KMK */ /* * Waits for any of the registered child processes to finish. */ static sub_process * process_wait_for_any_private(int block, DWORD* pdwWaitStatus) { HANDLE handles[MAXIMUM_WAIT_OBJECTS]; DWORD retval, which; int i; if (!proc_index) return NULL; /* build array of handles to wait for */ for (i = 0; i < proc_index; i++) { handles[i] = (HANDLE) proc_array[i]->pid; if (fake_exits_pending && proc_array[i]->exit_code) break; } /* wait for someone to exit */ if (!fake_exits_pending) { #ifdef KMK l_wait_again: #endif retval = WaitForMultipleObjects(proc_index, handles, FALSE, (block ? INFINITE : 0)); which = retval - WAIT_OBJECT_0; } else { fake_exits_pending--; retval = !WAIT_FAILED; which = i; } /* If the pointer is not NULL, set the wait status result variable. */ if (pdwWaitStatus) *pdwWaitStatus = retval; /* return pointer to process */ if ((retval == WAIT_TIMEOUT) || (retval == WAIT_FAILED)) { return NULL; } else { sub_process* pproc = proc_array[which]; #ifdef KMK if (pproc->enmType == kSubmit) { /* Try get the result from kSubmit.c. This may not succeed if the whole result hasn't arrived yet, in which we just restart the wait. */ if (kSubmitSubProcGetResult(pproc->clue, &pproc->exit_code, &pproc->signal) != 0) { goto l_wait_again; } } #endif #ifndef KMK /* Inefficient! */ process_adjust_wait_state(pproc); #else proc_index--; if ((int)which < proc_index) proc_array[which] = proc_array[proc_index]; proc_array[proc_index] = NULL; #endif return pproc; } } /* * Terminate a process. */ BOOL process_kill(HANDLE proc, int signal) { sub_process* pproc = (sub_process*) proc; #ifdef KMK if (pproc->enmType == kRegular) { #endif pproc->signal = signal; return (TerminateProcess((HANDLE) pproc->pid, signal)); #ifdef KMK } else if (pproc->enmType == kSubmit) return kSubmitSubProcKill(pproc->clue, signal) == 0; assert(0); return FALSE; #endif } /* * Use this function to register processes you wish to wait for by * calling process_file_io(NULL) or process_wait_any(). This must be done * because it is possible for callers of this library to reuse the same * handle for multiple processes launches :-( */ void process_register(HANDLE proc) { #ifdef KMK assert(((sub_process *)proc)->enmType == kRegular); #endif if (proc_index < MAXIMUM_WAIT_OBJECTS) proc_array[proc_index++] = (sub_process *) proc; } #ifdef KMK /** * Interface used by kmkbuiltin/kSubmit.c to register stuff going down in a * worker process. * * @returns 0 on success, -1 if there are too many sub-processes already. * @param hEvent The event semaphore to wait on. * @param clue The clue to base. * @param pPid Where to return the pid that job.c expects. */ int process_kmk_register_submit(HANDLE hEvent, intptr_t clue, pid_t *pPid) { if (proc_index < MAXIMUM_WAIT_OBJECTS) { sub_process *pSubProc = (sub_process *)xcalloc(sizeof(*pSubProc)); pSubProc->enmType = kSubmit; pSubProc->clue = clue; pSubProc->pid = (intptr_t)hEvent; proc_array[proc_index++] = pSubProc; *pPid = (intptr_t)pSubProc; return 0; } return -1; } /** * Interface used by kmkbuiltin/kRedirect.c to register a spawned process. * * @returns 0 on success, -1 if there are too many sub-processes already. * @param hProcess The process handle. * @param pPid Where to return the pid that job.c expects. */ int process_kmk_register_redirect(HANDLE hProcess, pid_t *pPid) { if (proc_index < MAXIMUM_WAIT_OBJECTS) { sub_process *pSubProc = (sub_process *)xcalloc(sizeof(*pSubProc)); pSubProc->enmType = kRegular; pSubProc->pid = (intptr_t)hProcess; proc_array[proc_index++] = pSubProc; *pPid = (intptr_t)pSubProc; return 0; } return -1; } #endif /* KMK */ /* * Return the number of processes that we are still waiting for. */ int process_used_slots(void) { return proc_index; } /* * Public function which works kind of like waitpid(). Wait for any * of the children to die and return results. To call this function, * you must do 1 of things: * * x = process_easy(...); * * or * * x = process_init_fd(); * process_register(x); * * or * * x = process_init(); * process_register(x); * * You must NOT then call process_pipe_io() because this function is * not capable of handling automatic notification of any child * death. */ HANDLE process_wait_for_any(int block, DWORD* pdwWaitStatus) { sub_process* pproc = process_wait_for_any_private(block, pdwWaitStatus); if (!pproc) return NULL; else { /* * Ouch! can't tell caller if this fails directly. Caller * will have to use process_last_err() */ #ifdef KMK /* Invalidate negative directory cache entries now that a job has completed and possibly created new files that was missing earlier. */ dir_cache_invalid_after_job (); if (pproc->enmType == kRegular) { (void)process_file_io_private(pproc, FALSE); } #else (void) process_file_io(pproc); #endif return ((HANDLE) pproc); } } long process_signal(HANDLE proc) { if (proc == INVALID_HANDLE_VALUE) return 0; return (((sub_process *)proc)->signal); } long process_last_err(HANDLE proc) { if (proc == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE; return (((sub_process *)proc)->last_err); } long process_exit_code(HANDLE proc) { if (proc == INVALID_HANDLE_VALUE) return EXIT_FAILURE; return (((sub_process *)proc)->exit_code); } void process_noinherit(int fd) { HANDLE fh = (HANDLE)_get_osfhandle(fd); if (fh && fh != INVALID_HANDLE_VALUE) SetHandleInformation(fh, HANDLE_FLAG_INHERIT, 0); } /* 2006-02: All the following functions are currently unused. All of them would crash gmake if called with argument INVALID_HANDLE_VALUE. Hence whoever wants to use one of this functions must invent and implement a reasonable error handling for this function. char * process_outbuf(HANDLE proc) { return (((sub_process *)proc)->outp); } char * process_errbuf(HANDLE proc) { return (((sub_process *)proc)->errp); } int process_outcnt(HANDLE proc) { return (((sub_process *)proc)->outcnt); } int process_errcnt(HANDLE proc) { return (((sub_process *)proc)->errcnt); } void process_pipes(HANDLE proc, int pipes[3]) { pipes[0] = ((sub_process *)proc)->sv_stdin[0]; pipes[1] = ((sub_process *)proc)->sv_stdout[0]; pipes[2] = ((sub_process *)proc)->sv_stderr[0]; return; } */ HANDLE process_init() { sub_process *pproc; /* * open file descriptors for attaching stdin/stdout/sterr */ HANDLE stdin_pipes[2]; HANDLE stdout_pipes[2]; HANDLE stderr_pipes[2]; SECURITY_ATTRIBUTES inherit; BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; pproc = malloc(sizeof(*pproc)); memset(pproc, 0, sizeof(*pproc)); /* We can't use NULL for lpSecurityDescriptor because that uses the default security descriptor of the calling process. Instead we use a security descriptor with no DACL. This allows nonrestricted access to the associated objects. */ if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd), SECURITY_DESCRIPTOR_REVISION)) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; return((HANDLE)pproc); } inherit.nLength = sizeof(inherit); inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd); inherit.bInheritHandle = TRUE; // By convention, parent gets pipe[0], and child gets pipe[1] // This means the READ side of stdin pipe goes into pipe[1] // and the WRITE side of the stdout and stderr pipes go into pipe[1] if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE || CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE || CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; return((HANDLE)pproc); } // // Mark the parent sides of the pipes as non-inheritable // if (SetHandleInformation(stdin_pipes[0], HANDLE_FLAG_INHERIT, 0) == FALSE || SetHandleInformation(stdout_pipes[0], HANDLE_FLAG_INHERIT, 0) == FALSE || SetHandleInformation(stderr_pipes[0], HANDLE_FLAG_INHERIT, 0) == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; return((HANDLE)pproc); } pproc->sv_stdin[0] = (intptr_t) stdin_pipes[0]; pproc->sv_stdin[1] = (intptr_t) stdin_pipes[1]; pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0]; pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1]; pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0]; pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1]; pproc->using_pipes = 1; pproc->lerrno = 0; return((HANDLE)pproc); } HANDLE process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh) { sub_process *pproc; pproc = malloc(sizeof(*pproc)); if (pproc) { memset(pproc, 0, sizeof(*pproc)); /* * Just pass the provided file handles to the 'child * side' of the pipe, bypassing pipes altogether. */ pproc->sv_stdin[1] = (intptr_t) stdinh; pproc->sv_stdout[1] = (intptr_t) stdouth; pproc->sv_stderr[1] = (intptr_t) stderrh; pproc->last_err = pproc->lerrno = 0; } return((HANDLE)pproc); } static HANDLE find_file(const char *exec_path, const char *path_var, char *full_fname, DWORD full_len) { HANDLE exec_handle; char *fname; char *ext; DWORD req_len; int i; static const char *extensions[] = /* Should .com come before no-extension case? */ { ".exe", ".cmd", ".bat", "", ".com", NULL }; fname = xmalloc(strlen(exec_path) + 5); strcpy(fname, exec_path); ext = fname + strlen(fname); for (i = 0; extensions[i]; i++) { strcpy(ext, extensions[i]); if (((req_len = SearchPath (path_var, fname, NULL, full_len, full_fname, NULL)) > 0 /* For compatibility with previous code, which used OpenFile, and with Windows operation in general, also look in various default locations, such as Windows directory and Windows System directory. Warning: this also searches PATH in the Make's environment, which might not be what the Makefile wants, but it seems to be OK as a fallback, after the previous SearchPath failed to find on child's PATH. */ || (req_len = SearchPath (NULL, fname, NULL, full_len, full_fname, NULL)) > 0) && req_len <= full_len && (exec_handle = CreateFile(full_fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) { free(fname); return(exec_handle); } } free(fname); return INVALID_HANDLE_VALUE; } /* * Return non-zero of FNAME specifies a batch file and its name * includes embedded whitespace. */ static int batch_file_with_spaces(const char *fname) { size_t fnlen = strlen(fname); return (fnlen > 4 && (_strnicmp(fname + fnlen - 4, ".bat", 4) == 0 || _strnicmp(fname + fnlen - 4, ".cmd", 4) == 0) /* The set of characters in the 2nd arg to strpbrk should be the same one used by make_command_line below to decide whether an argv[] element needs quoting. */ && strpbrk(fname, " \t") != NULL); } /* * Description: Create the child process to be helped * * Returns: success <=> 0 * * Notes/Dependencies: */ long process_begin( HANDLE proc, char **argv, char **envp, char *exec_path, char *as_user) { sub_process *pproc = (sub_process *)proc; char *shell_name = 0; int file_not_found=0; HANDLE exec_handle; char exec_fname[MAX_PATH]; const char *path_var = NULL; char **ep; char buf[MAX_PATH]; DWORD bytes_returned; DWORD flags; char *command_line; STARTUPINFO startInfo; PROCESS_INFORMATION procInfo; char *envblk=NULL; int envsize_needed = 0; int pass_null_exec_path = 0; #ifdef KMK size_t exec_path_len; extern int process_priority; assert (pproc->enmType == kRegular); #endif /* * Shell script detection... if the exec_path starts with #! then * we want to exec shell-script-name exec-path, not just exec-path * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not * hard-code the path to the shell or perl or whatever: Instead, we * assume it's in the path somewhere (generally, the NT tools * bin directory) */ #ifdef KMK /* kmk performance: Don't bother looking for shell scripts in .exe files. */ exec_path_len = strlen(exec_path); if (exec_path_len > 4 && exec_path[exec_path_len - 4] == '.' && !stricmp(exec_path + exec_path_len - 3, "exe")) { exec_handle = INVALID_HANDLE_VALUE; exec_fname[0] = '\0'; } else { #endif /* KMK */ /* Use the Makefile's value of PATH to look for the program to execute, because it could be different from Make's PATH (e.g., if the target sets its own value. */ if (envp) for (ep = envp; *ep; ep++) { if (strncmp (*ep, "PATH=", 5) == 0 || strncmp (*ep, "Path=", 5) == 0) { path_var = *ep + 5; break; } } exec_handle = find_file(exec_path, path_var, exec_fname, sizeof(exec_fname)); #ifdef KMK } #endif /* * If we couldn't open the file, just assume that Windows will be * somehow able to find and execute it. If the first character * of the command is '/', assume they set SHELL to a Unixy shell * that have some magic mounts known only to it, and run the whole * command via $SHELL -c "COMMAND" instead. */ if (exec_handle == INVALID_HANDLE_VALUE) { if (exec_path[0] == '/') { char *new_argv0; char **argvi = argv; int arglen = 0; strcpy(buf, variable_expand ("$(SHELL)")); shell_name = &buf[0]; strcpy(exec_fname, "-c"); /* Construct a single command string in argv[0]. */ while (*argvi) { arglen += strlen(*argvi) + 1; argvi++; } new_argv0 = xmalloc(arglen + 1); new_argv0[0] = '\0'; for (argvi = argv; *argvi; argvi++) { strcat(new_argv0, *argvi); strcat(new_argv0, " "); } /* Remove the extra blank at the end. */ new_argv0[arglen-1] = '\0'; free(argv[0]); argv[0] = new_argv0; argv[1] = NULL; } else file_not_found++; } else { /* Attempt to read the first line of the file */ if (ReadFile( exec_handle, buf, sizeof(buf) - 1, /* leave room for trailing NULL */ &bytes_returned, 0) == FALSE || bytes_returned < 2) { pproc->last_err = GetLastError(); pproc->lerrno = E_IO; CloseHandle(exec_handle); return(-1); } if (buf[0] == '#' && buf[1] == '!') { /* * This is a shell script... Change the command line from * exec_path args to shell_name exec_path args */ char *p; /* Make sure buf is NULL terminated */ buf[bytes_returned] = 0; /* * Depending on the file system type, etc. the first line * of the shell script may end with newline or newline-carriage-return * Whatever it ends with, cut it off. */ p= strchr(buf, '\n'); if (p) *p = 0; p = strchr(buf, '\r'); if (p) *p = 0; /* * Find base name of shell */ shell_name = strrchr( buf, '/'); if (shell_name) { shell_name++; } else { shell_name = &buf[2];/* skipping "#!" */ } } CloseHandle(exec_handle); } flags = 0; if (file_not_found) command_line = make_command_line( shell_name, exec_path, argv); else { /* If exec_fname includes whitespace, CreateProcess behaves erratically and unreliably, and often fails if argv[0] also includes whitespace (and thus will be quoted by make_command_line below). So in that case, we don't pass exec_fname as the 1st arg to CreateProcess, but instead replace argv[0] with exec_fname (to keep its leading directories and extension as found by find_file), and pass NULL to CreateProcess as its 1st arg. This works around the bugs in CreateProcess, which are probably caused by its passing the command to cmd.exe with some incorrect quoting. */ if (!shell_name && batch_file_with_spaces(exec_fname) && _stricmp(exec_path, argv[0]) == 0) { char *new_argv, *p; char **argvi; int arglen, i; pass_null_exec_path = 1; /* Rewrite argv[] replacing argv[0] with exec_fname. */ for (argvi = argv + 1, arglen = strlen(exec_fname) + 1; *argvi; argvi++) { arglen += strlen(*argvi) + 1; } new_argv = xmalloc(arglen); p = strcpy(new_argv, exec_fname) + strlen(exec_fname) + 1; for (argvi = argv + 1, i = 1; *argvi; argvi++, i++) { strcpy(p, *argvi); argv[i] = p; p += strlen(*argvi) + 1; } argv[i] = NULL; free (argv[0]); argv[0] = new_argv; } command_line = make_command_line( shell_name, exec_fname, argv); } if ( command_line == NULL ) { pproc->last_err = 0; pproc->lerrno = E_NO_MEM; return(-1); } if (envp) { if (arr2envblk(envp, &envblk, &envsize_needed) == FALSE) { pproc->lerrno = E_NO_MEM; free( command_line ); if ((pproc->last_err == ERROR_INVALID_PARAMETER || pproc->last_err == ERROR_MORE_DATA) && envsize_needed > 32*1024) { fprintf (stderr, "CreateProcess failed, probably because environment is too large (%d bytes).\n", envsize_needed); } pproc->last_err = 0; return(-1); } } if (shell_name || file_not_found || pass_null_exec_path) { exec_path = 0; /* Search for the program in %Path% */ } else { exec_path = exec_fname; } /* * Set up inherited stdin, stdout, stderr for child */ memset(&startInfo, '\0', sizeof(startInfo)); GetStartupInfo(&startInfo); #ifndef KMK startInfo.dwFlags = STARTF_USESTDHANDLES; #endif startInfo.lpReserved = 0; startInfo.cbReserved2 = 0; startInfo.lpReserved2 = 0; #ifndef KMK startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1]; startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1]; startInfo.hStdError = (HANDLE)pproc->sv_stderr[1]; #else if ( ((HANDLE)pproc->sv_stdin[1] != INVALID_HANDLE_VALUE && pproc->sv_stdin[1]) || ((HANDLE)pproc->sv_stdout[1] != INVALID_HANDLE_VALUE && pproc->sv_stdout[1]) || ((HANDLE)pproc->sv_stderr[1] != INVALID_HANDLE_VALUE && pproc->sv_stderr[1]) ) { startInfo.dwFlags = STARTF_USESTDHANDLES; startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1]; startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1]; startInfo.hStdError = (HANDLE)pproc->sv_stderr[1]; } else { startInfo.dwFlags = 0; startInfo.hStdInput = 0; startInfo.hStdOutput = 0; startInfo.hStdError = 0; } #endif if (as_user) { free(envblk); return -1; } else { DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n", exec_path ? exec_path : "NULL", command_line ? command_line : "NULL")); #ifdef KMK if (exec_fname[0]) kmk_cache_exec_image_a(exec_fname); else if (exec_path) kmk_cache_exec_image_a(exec_path); else if (argv[0]) kmk_cache_exec_image_a(argv[0]); switch (process_priority) { case 1: flags |= CREATE_SUSPENDED | IDLE_PRIORITY_CLASS; break; case 2: flags |= CREATE_SUSPENDED | BELOW_NORMAL_PRIORITY_CLASS; break; case 3: flags |= CREATE_SUSPENDED | NORMAL_PRIORITY_CLASS; break; case 4: flags |= CREATE_SUSPENDED | HIGH_PRIORITY_CLASS; break; case 5: flags |= CREATE_SUSPENDED | REALTIME_PRIORITY_CLASS; break; } #endif if (CreateProcess( exec_path, command_line, NULL, 0, /* default security attributes for thread */ TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */ flags, envblk, 0, /* default starting directory */ &startInfo, &procInfo) == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_FORK; fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", exec_path ? exec_path : "NULL", command_line); free(envblk); free( command_line ); return(-1); } #ifdef KMK switch (process_priority) { case 1: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_IDLE); break; case 2: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_BELOW_NORMAL); break; case 3: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_NORMAL); break; case 4: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_HIGHEST); break; case 5: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_TIME_CRITICAL); break; } ResumeThread(procInfo.hThread); #endif } pproc->pid = (pid_t)procInfo.hProcess; /* Close the thread handle -- we'll just watch the process */ CloseHandle(procInfo.hThread); /* Close the halves of the pipes we don't need */ if ((HANDLE)pproc->sv_stdin[1] != INVALID_HANDLE_VALUE && pproc->sv_stdin[1]) CloseHandle((HANDLE)pproc->sv_stdin[1]); if ((HANDLE)pproc->sv_stdout[1] != INVALID_HANDLE_VALUE && pproc->sv_stdout[1]) CloseHandle((HANDLE)pproc->sv_stdout[1]); if ((HANDLE)pproc->sv_stderr[1] != INVALID_HANDLE_VALUE && pproc->sv_stderr[1]) CloseHandle((HANDLE)pproc->sv_stderr[1]); pproc->sv_stdin[1] = 0; pproc->sv_stdout[1] = 0; pproc->sv_stderr[1] = 0; free( command_line ); free(envblk); pproc->lerrno=0; return 0; } #if 0 /* unused */ static DWORD proc_stdin_thread(sub_process *pproc) { DWORD in_done; for (;;) { if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt, &in_done, NULL) == FALSE) _endthreadex(0); // This if should never be true for anonymous pipes, but gives // us a chance to change I/O mechanisms later if (in_done < pproc->incnt) { pproc->incnt -= in_done; pproc->inp += in_done; } else { _endthreadex(0); } } return 0; // for compiler warnings only.. not reached } static DWORD proc_stdout_thread(sub_process *pproc) { DWORD bufsize = 1024; char c; DWORD nread; pproc->outp = malloc(bufsize); if (pproc->outp == NULL) _endthreadex(0); pproc->outcnt = 0; for (;;) { if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL) == FALSE) { /* map_windows32_error_to_string(GetLastError());*/ _endthreadex(0); } if (nread == 0) _endthreadex(0); if (pproc->outcnt + nread > bufsize) { bufsize += nread + 512; pproc->outp = realloc(pproc->outp, bufsize); if (pproc->outp == NULL) { pproc->outcnt = 0; _endthreadex(0); } } pproc->outp[pproc->outcnt++] = c; } return 0; } static DWORD proc_stderr_thread(sub_process *pproc) { DWORD bufsize = 1024; char c; DWORD nread; pproc->errp = malloc(bufsize); if (pproc->errp == NULL) _endthreadex(0); pproc->errcnt = 0; for (;;) { if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) { map_windows32_error_to_string(GetLastError()); _endthreadex(0); } if (nread == 0) _endthreadex(0); if (pproc->errcnt + nread > bufsize) { bufsize += nread + 512; pproc->errp = realloc(pproc->errp, bufsize); if (pproc->errp == NULL) { pproc->errcnt = 0; _endthreadex(0); } } pproc->errp[pproc->errcnt++] = c; } return 0; } /* * Purpose: collects output from child process and returns results * * Description: * * Returns: * * Notes/Dependencies: */ long process_pipe_io( HANDLE proc, char *stdin_data, int stdin_data_len) { sub_process *pproc = (sub_process *)proc; bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE; HANDLE childhand = (HANDLE) pproc->pid; HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL; unsigned int dwStdin, dwStdout, dwStderr; HANDLE wait_list[4]; DWORD wait_count; DWORD wait_return; HANDLE ready_hand; bool_t child_dead = FALSE; BOOL GetExitCodeResult; #ifdef KMK assert (pproc->enmType == kRegular); #endif /* * Create stdin thread, if needed */ pproc->inp = stdin_data; pproc->incnt = stdin_data_len; if (!pproc->inp) { stdin_eof = TRUE; CloseHandle((HANDLE)pproc->sv_stdin[0]); pproc->sv_stdin[0] = 0; } else { tStdin = (HANDLE) _beginthreadex( 0, 1024, (unsigned (__stdcall *) (void *))proc_stdin_thread, pproc, 0, &dwStdin); if (tStdin == 0) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done; } } /* * Assume child will produce stdout and stderr */ tStdout = (HANDLE) _beginthreadex( 0, 1024, (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0, &dwStdout); tStderr = (HANDLE) _beginthreadex( 0, 1024, (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0, &dwStderr); if (tStdout == 0 || tStderr == 0) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done; } /* * Wait for all I/O to finish and for the child process to exit */ while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) { wait_count = 0; if (!stdin_eof) { wait_list[wait_count++] = tStdin; } if (!stdout_eof) { wait_list[wait_count++] = tStdout; } if (!stderr_eof) { wait_list[wait_count++] = tStderr; } if (!child_dead) { wait_list[wait_count++] = childhand; } wait_return = WaitForMultipleObjects(wait_count, wait_list, FALSE, /* don't wait for all: one ready will do */ child_dead? 1000 :INFINITE); /* after the child dies, subthreads have one second to collect all remaining output */ if (wait_return == WAIT_FAILED) { /* map_windows32_error_to_string(GetLastError());*/ pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done; } ready_hand = wait_list[wait_return - WAIT_OBJECT_0]; if (ready_hand == tStdin) { CloseHandle((HANDLE)pproc->sv_stdin[0]); pproc->sv_stdin[0] = 0; CloseHandle(tStdin); tStdin = 0; stdin_eof = TRUE; } else if (ready_hand == tStdout) { CloseHandle((HANDLE)pproc->sv_stdout[0]); pproc->sv_stdout[0] = 0; CloseHandle(tStdout); tStdout = 0; stdout_eof = TRUE; } else if (ready_hand == tStderr) { CloseHandle((HANDLE)pproc->sv_stderr[0]); pproc->sv_stderr[0] = 0; CloseHandle(tStderr); tStderr = 0; stderr_eof = TRUE; } else if (ready_hand == childhand) { DWORD ierr; GetExitCodeResult = GetExitCodeProcess(childhand, &ierr); if (ierr == CONTROL_C_EXIT) { pproc->signal = SIGINT; } else { pproc->exit_code = ierr; } if (GetExitCodeResult == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done; } child_dead = TRUE; } else { /* ?? Got back a handle we didn't query ?? */ pproc->last_err = 0; pproc->lerrno = E_FAIL; goto done; } } done: if (tStdin != 0) CloseHandle(tStdin); if (tStdout != 0) CloseHandle(tStdout); if (tStderr != 0) CloseHandle(tStderr); if (pproc->lerrno) return(-1); else return(0); } #endif /* unused */ #ifndef KMK /* unused */ /* * Purpose: collects output from child process and returns results * * Description: * * Returns: * * Notes/Dependencies: */ long process_file_io( HANDLE proc) { sub_process *pproc; if (proc == NULL) pproc = process_wait_for_any_private(1, 0); else pproc = (sub_process *)proc; /* some sort of internal error */ if (!pproc) return -1; return process_file_io_private(proc, TRUE); } #endif /* !KMK - unused */ /* private function, avoid some kernel calls. (bird) */ static long process_file_io_private( sub_process *pproc, BOOL fNeedToWait) { HANDLE childhand; DWORD wait_return; BOOL GetExitCodeResult; DWORD ierr; childhand = (HANDLE) pproc->pid; /* * This function is poorly named, and could also be used just to wait * for child death if you're doing your own pipe I/O. If that is * the case, close the pipe handles here. */ if (pproc->sv_stdin[0]) { CloseHandle((HANDLE)pproc->sv_stdin[0]); pproc->sv_stdin[0] = 0; } if (pproc->sv_stdout[0]) { CloseHandle((HANDLE)pproc->sv_stdout[0]); pproc->sv_stdout[0] = 0; } if (pproc->sv_stderr[0]) { CloseHandle((HANDLE)pproc->sv_stderr[0]); pproc->sv_stderr[0] = 0; } #ifdef KMK if (childhand == NULL || childhand == INVALID_HANDLE_VALUE) { goto done2; } #endif /* * Wait for the child process to exit */ if (fNeedToWait) { /* bird */ wait_return = WaitForSingleObject(childhand, INFINITE); if (wait_return != WAIT_OBJECT_0) { /* map_windows32_error_to_string(GetLastError());*/ pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done2; } } /* bird */ GetExitCodeResult = GetExitCodeProcess(childhand, &ierr); if (ierr == CONTROL_C_EXIT) { pproc->signal = SIGINT; } else { pproc->exit_code = ierr; } if (GetExitCodeResult == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; } done2: if (pproc->lerrno) return(-1); else return(0); } /* * Description: Clean up any leftover handles, etc. It is up to the * caller to manage and free the input, output, and stderr buffers. */ void process_cleanup( HANDLE proc) { sub_process *pproc = (sub_process *)proc; int i; #ifdef KMK if (pproc->enmType == kRegular) { #endif if (pproc->using_pipes) { for (i= 0; i <= 1; i++) { if ((HANDLE)pproc->sv_stdin[i] && (HANDLE)pproc->sv_stdin[i] != INVALID_HANDLE_VALUE) CloseHandle((HANDLE)pproc->sv_stdin[i]); if ((HANDLE)pproc->sv_stdout[i] && (HANDLE)pproc->sv_stdout[i] != INVALID_HANDLE_VALUE) CloseHandle((HANDLE)pproc->sv_stdout[i]); if ((HANDLE)pproc->sv_stderr[i] && (HANDLE)pproc->sv_stderr[i] != INVALID_HANDLE_VALUE) CloseHandle((HANDLE)pproc->sv_stderr[i]); } } if ((HANDLE)pproc->pid) CloseHandle((HANDLE)pproc->pid); #ifdef KMK } else if (pproc->enmType == kSubmit) { kSubmitSubProcCleanup(pproc->clue); } else { assert(0); return; } pproc->enmType = kSubProcFreed; #endif free(pproc); } /* * Description: * Create a command line buffer to pass to CreateProcess * * Returns: the buffer or NULL for failure * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ... * Otherwise: argv[0] argv[1] argv[2] ... * * Notes/Dependencies: * CreateProcess does not take an argv, so this command creates a * command line for the executable. */ static char * make_command_line( char *shell_name, char *full_exec_path, char **argv) { int argc = 0; char** argvi; int* enclose_in_quotes = NULL; int* enclose_in_quotes_i; unsigned int bytes_required = 0; char* command_line; char* command_line_i; int cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */ int have_sh = 0; /* HAVE_CYGWIN_SHELL */ #undef HAVE_CYGWIN_SHELL /* bird: paranoia */ #ifdef HAVE_CYGWIN_SHELL have_sh = (shell_name != NULL || strstr(full_exec_path, "sh.exe")); cygwin_mode = 1; #endif if (shell_name && full_exec_path) { bytes_required = strlen(shell_name) + 1 + strlen(full_exec_path); /* * Skip argv[0] if any, when shell_name is given. * The special case of "-c" in full_exec_path means * argv[0] is not the shell name, but the command string * to pass to the shell. */ if (*argv && strcmp(full_exec_path, "-c")) argv++; /* * Add one for the intervening space. */ if (*argv) bytes_required++; } argvi = argv; while (*(argvi++)) argc++; if (argc) { enclose_in_quotes = (int*) calloc(1, argc * sizeof(int)); if (!enclose_in_quotes) { return NULL; } } /* We have to make one pass through each argv[i] to see if we need * to enclose it in ", so we might as well figure out how much * memory we'll need on the same pass. */ argvi = argv; enclose_in_quotes_i = enclose_in_quotes; while(*argvi) { char* p = *argvi; unsigned int backslash_count = 0; /* * We have to enclose empty arguments in ". */ if (!(*p)) *enclose_in_quotes_i = 1; while(*p) { switch (*p) { case '\"': /* * We have to insert a backslash for each " * and each \ that precedes the ". */ bytes_required += (backslash_count + 1); backslash_count = 0; break; #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) case '\\': backslash_count++; break; #endif /* * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so * that argv in always equals argv out. This was removed. Say you have * such a program named glob.exe. You enter * glob '*' * at the sh command prompt. Obviously the intent is to make glob do the * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?', * then the command line that glob would see would be * glob "*" * and the _setargv in SETARGV.OBJ would _not_ expand the *. */ case ' ': case '\t': *enclose_in_quotes_i = 1; /* fall through */ default: backslash_count = 0; break; } /* * Add one for each character in argv[i]. */ bytes_required++; p++; } if (*enclose_in_quotes_i) { /* * Add one for each enclosing ", * and one for each \ that precedes the * closing ". */ bytes_required += (backslash_count + 2); } /* * Add one for the intervening space. */ if (*(++argvi)) bytes_required++; enclose_in_quotes_i++; } /* * Add one for the terminating NULL. */ bytes_required++; #ifdef KMK /* for the space before the final " in case we need it. */ bytes_required++; #endif command_line = (char*) malloc(bytes_required); if (!command_line) { free(enclose_in_quotes); return NULL; } command_line_i = command_line; if (shell_name && full_exec_path) { while(*shell_name) { *(command_line_i++) = *(shell_name++); } *(command_line_i++) = ' '; while(*full_exec_path) { *(command_line_i++) = *(full_exec_path++); } if (*argv) { *(command_line_i++) = ' '; } } argvi = argv; enclose_in_quotes_i = enclose_in_quotes; while(*argvi) { char* p = *argvi; unsigned int backslash_count = 0; if (*enclose_in_quotes_i) { *(command_line_i++) = '\"'; } while(*p) { if (*p == '\"') { if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */ /* instead of a \", cygwin likes "" */ *(command_line_i++) = '\"'; } else { /* * We have to insert a backslash for the " * and each \ that precedes the ". */ backslash_count++; while(backslash_count) { *(command_line_i++) = '\\'; backslash_count--; }; } #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) } else if (*p == '\\') { backslash_count++; } else { backslash_count = 0; #endif } /* * Copy the character. */ *(command_line_i++) = *(p++); } if (*enclose_in_quotes_i) { #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) /* * Add one \ for each \ that precedes the * closing ". */ while(backslash_count--) { *(command_line_i++) = '\\'; }; #endif #ifdef KMK /* * ash it put off by echo "hello world" ending up as: * G:/.../kmk_ash.exe -c "echo ""hello world""" * It wants a space before the last '"'. * (The 'test_shell' goals in Makefile.kmk tests this problem.) */ if (command_line_i[-1] == '\"' /* && cygwin_mode && have_sh*/ && !argvi[1]) { *(command_line_i++) = ' '; } #endif *(command_line_i++) = '\"'; } /* * Append an intervening space. */ if (*(++argvi)) { *(command_line_i++) = ' '; } enclose_in_quotes_i++; } /* * Append the terminating NULL. */ *command_line_i = '\0'; free(enclose_in_quotes); return command_line; } /* * Description: Given an argv and optional envp, launch the process * using the default stdin, stdout, and stderr handles. * Also, register process so that process_wait_for_any_private() * can be used via process_file_io(NULL) or * process_wait_for_any(). * * Returns: * * Notes/Dependencies: */ HANDLE process_easy( char **argv, char **envp, int outfd, int errfd) { HANDLE hIn = INVALID_HANDLE_VALUE; HANDLE hOut = INVALID_HANDLE_VALUE; HANDLE hErr = INVALID_HANDLE_VALUE; HANDLE hProcess, tmpIn, tmpOut, tmpErr; DWORD e; if (proc_index >= MAXIMUM_WAIT_OBJECTS) { DB (DB_JOBS, ("process_easy: All process slots used up\n")); return INVALID_HANDLE_VALUE; } #ifdef KMK /* We can effort here by lettering CreateProcess/kernel do the standard handle duplication. */ if (outfd != -1 || errfd != -1) { #endif /* Standard handles returned by GetStdHandle can be NULL or INVALID_HANDLE_VALUE if the parent process closed them. If that happens, we open the null device and pass its handle to CreateProcess as the corresponding handle to inherit. */ tmpIn = GetStdHandle(STD_INPUT_HANDLE); if (DuplicateHandle(GetCurrentProcess(), tmpIn, GetCurrentProcess(), &hIn, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { tmpIn = CreateFile("NUL", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (tmpIn != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), tmpIn, GetCurrentProcess(), &hIn, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) CloseHandle(tmpIn); } if (hIn == INVALID_HANDLE_VALUE) { fprintf(stderr, "process_easy: DuplicateHandle(In) failed (e=%ld)\n", e); return INVALID_HANDLE_VALUE; } } if (outfd >= 0) tmpOut = (HANDLE)_get_osfhandle (outfd); else tmpOut = GetStdHandle (STD_OUTPUT_HANDLE); if (DuplicateHandle(GetCurrentProcess(), tmpOut, GetCurrentProcess(), &hOut, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { tmpOut = CreateFile("NUL", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (tmpOut != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), tmpOut, GetCurrentProcess(), &hOut, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) CloseHandle(tmpOut); } if (hOut == INVALID_HANDLE_VALUE) { fprintf(stderr, "process_easy: DuplicateHandle(Out) failed (e=%ld)\n", e); return INVALID_HANDLE_VALUE; } } if (errfd >= 0) tmpErr = (HANDLE)_get_osfhandle (errfd); else tmpErr = GetStdHandle(STD_ERROR_HANDLE); if (DuplicateHandle(GetCurrentProcess(), tmpErr, GetCurrentProcess(), &hErr, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { tmpErr = CreateFile("NUL", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (tmpErr != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), tmpErr, GetCurrentProcess(), &hErr, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) CloseHandle(tmpErr); } if (hErr == INVALID_HANDLE_VALUE) { fprintf(stderr, "process_easy: DuplicateHandle(Err) failed (e=%ld)\n", e); return INVALID_HANDLE_VALUE; } } #ifdef KMK /* saving effort */ } #endif hProcess = process_init_fd(hIn, hOut, hErr); if (process_begin(hProcess, argv, envp, argv[0], NULL)) { fake_exits_pending++; /* process_begin() failed: make a note of that. */ if (!((sub_process*) hProcess)->last_err) ((sub_process*) hProcess)->last_err = -1; #ifdef KMK if (!((sub_process*) hProcess)->exit_code) #endif ((sub_process*) hProcess)->exit_code = process_last_err(hProcess); /* close up unused handles */ if (hIn != INVALID_HANDLE_VALUE) CloseHandle(hIn); if (hOut != INVALID_HANDLE_VALUE) CloseHandle(hOut); if (hErr != INVALID_HANDLE_VALUE) CloseHandle(hErr); } process_register(hProcess); return hProcess; } kbuild-3686/src/kmk/Makefile.am0000664000175000017500000002331415053010075016320 0ustar locutuslocutus# This is a -*-Makefile-*-, or close enough # # Copyright (C) 1997-2016 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) any later # version. # # GNU Make 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, see . AUTOMAKE_OPTIONS = dist-bzip2 silent-rules std-options ACLOCAL_AMFLAGS = -I config MAKE_HOST = @MAKE_HOST@ # Only process if target is MS-Windows if WINDOWSENV MAYBE_W32 = w32 W32INC = -I $(top_srcdir)/w32/include W32LIB = -Lw32 -lw32 ossrc = else ossrc = posixos.c endif # we can safely drop doc and po when bootstrapping kmk. # SUBDIRS = glob config po doc $(MAYBE_W32) SUBDIRS = glob config $(MAYBE_W32) bin_PROGRAMS = kmk kmk_redirect include_HEADERS = gnumake.h if USE_CUSTOMS remote = remote-cstms.c else remote = remote-stub.c endif kmk_SOURCES = ar.c arscan.c commands.c default.c dir.c expand.c file.c \ function.c getopt.c getopt1.c guile.c implicit.c job.c load.c \ loadapi.c main.c misc.c $(ossrc) output.c read.c remake.c \ rule.c signame.c strcache.c variable.c version.c vpath.c \ hash.c $(remote) \ \ expreval.c \ incdep.c \ strcache2.c \ alloccache.c \ kbuild.c \ kbuild-object.c \ electric.c \ ../lib/md5.c \ ../lib/kDep.c \ ../lib/kbuild_version.c \ ../lib/dos2unix.c \ ../lib/maybe_con_fwrite.c \ ../lib/version_compare.c \ \ kmkbuiltin.c \ kmkbuiltin/append.c \ kmkbuiltin/cat.c \ kmkbuiltin/chmod.c \ kmkbuiltin/cmp.c \ kmkbuiltin/cmp_util.c \ kmkbuiltin/cp.c \ kmkbuiltin/cp_utils.c \ kmkbuiltin/echo.c \ kmkbuiltin/expr.c \ kmkbuiltin/install.c \ kmkbuiltin/kDepIDB.c \ kmkbuiltin/kDepObj.c \ kmkbuiltin/ln.c \ kmkbuiltin/md5sum.c \ kmkbuiltin/mkdir.c \ kmkbuiltin/mv.c \ kmkbuiltin/printf.c \ kmkbuiltin/redirect.c \ kmkbuiltin/rm.c \ kmkbuiltin/rmdir.c \ kmkbuiltin/sleep.c \ kmkbuiltin/test.c \ kmkbuiltin/touch.c \ \ kmkbuiltin/err.c \ kmkbuiltin/getopt_r.c \ kmkbuiltin/getopt1_r.c \ kmkbuiltin/fts.c \ kmkbuiltin/setmode.c \ kmkbuiltin/strmode.c \ kmkbuiltin/strlcpy.c \ kmkbuiltin/osdep.c \ kmkbuiltin/kbuild_protection.c \ kmkbuiltin/common-env-and-cwd-opt.c kmk_redirect_SOURCES = kmkbuiltin/redirect.c \ kmkbuiltin/common-env-and-cwd-opt.c \ kmkbuiltin/err.c \ ../lib/kbuild_version.c kmk_redirect_CFLAGS = -UKMK -DKMK_BUILTIN_STANDALONE EXTRA_kmk_SOURCES = vmsjobs.c remote-stub.c remote-cstms.c noinst_HEADERS = commands.h dep.h filedef.h job.h makeint.h rule.h variable.h \ debug.h getopt.h gettext.h hash.h output.h os.h #kmk_LDADD = @LIBOBJS@ @ALLOCA@ $(GLOBLIB) @GETLOADAVG_LIBS@ @LIBINTL@ kmk_LDADD = @LIBOBJS@ @ALLOCA@ $(GLOBLIB) @GETLOADAVG_LIBS@ \ $(GUILE_LIBS) # Only process if target is MS-Windows if WINDOWSENV kmk_LDADD += $(W32LIB) endif man_MANS = make.1 # org - DEFS = -DLOCALEDIR=\"$(localedir)\" -DLIBDIR=\"$(libdir)\" -DINCLUDEDIR=\"$(includedir)\" @DEFS@ DEFS = \ -DNO_ARCHIVES \ -DEXPERIMENTAL \ -DCONFIG_WITH_TOUPPER_TOLOWER \ -DCONFIG_WITH_DEFINED \ -DCONFIG_WITH_EXPLICIT_MULTITARGET \ -DCONFIG_WITH_DOT_MUST_MAKE \ -DCONFIG_WITH_PREPEND_ASSIGNMENT \ -DCONFIG_WITH_LOCAL_VARIABLES \ -DCONFIG_WITH_2ND_TARGET_EXPANSION \ -DCONFIG_WITH_ALLOC_CACHES \ -DCONFIG_WITH_STRCACHE2 \ \ -DKMK \ -DKMK_HELPERS \ -DCONFIG_NO_DEFAULT_SUFFIXES \ -DCONFIG_NO_DEFAULT_PATTERN_RULES \ -DCONFIG_NO_DEFAULT_TERMINAL_RULES \ -DCONFIG_NO_DEFAULT_SUFFIX_RULES \ -DCONFIG_NO_DEFAULT_VARIABLES \ -DCONFIG_WITH_EXTENDED_NOTPARALLEL \ -DCONFIG_WITH_INCLUDEDEP \ -DCONFIG_WITHOUT_THREADS \ -DCONFIG_WITH_VALUE_LENGTH \ \ -DCONFIG_WITH_ABSPATHEX \ -DCONFIG_WITH_COMMANDS_FUNC \ -DCONFIG_WITH_DATE \ -DCONFIG_WITH_DEFINED_FUNCTIONS \ -DCONFIG_WITH_EVALPLUS \ -DCONFIG_WITH_FILE_SIZE \ -DCONFIG_WITH_LOOP_FUNCTIONS \ -DCONFIG_WITH_MATH \ -DCONFIG_WITH_NANOTS \ -DCONFIG_WITH_ROOT_FUNC \ -DCONFIG_WITH_RSORT \ -DCONFIG_WITH_STACK \ -DCONFIG_WITH_STRING_FUNCTIONS \ -DCONFIG_WITH_WHERE_FUNCTION \ -DCONFIG_WITH_WHICH \ -DCONFIG_WITH_XARGS \ \ -DCONFIG_WITH_COMPARE \ -DCONFIG_WITH_SET_CONDITIONALS \ -DCONFIG_WITH_IF_CONDITIONALS \ -DCONFIG_WITH_PRINTF \ -DCONFIG_WITH_MINIMAL_STATS \ -DCONFIG_PRETTY_COMMAND_PRINTING \ -DCONFIG_WITH_PRINT_STATS_SWITCH \ -DCONFIG_WITH_PRINT_TIME_SWITCH \ -DCONFIG_WITH_RDONLY_VARIABLE_VALUE \ -DCONFIG_WITH_LAZY_DEPS_VARS \ \ -DKBUILD_TYPE=\"$(KBUILD_TYPE)\" \ -DKBUILD_HOST=\"$(KBUILD_TARGET)\" \ -DKBUILD_HOST_ARCH=\"$(KBUILD_TARGET_ARCH)\" \ -DKBUILD_HOST_CPU=\"$(KBUILD_TARGET_CPU)\" \ \ -DKBUILD_SVN_REV=1 \ -DKBUILD_VERSION_MAJOR=0 \ -DKBUILD_VERSION_MINOR=1 \ -DKBUILD_VERSION_PATCH=9998 \ \ -DCONFIG_WITH_KMK_BUILTIN \ @DEFS@ AM_CPPFLAGS = $(GLOBINC) -I$(srcdir)/../lib -I$(srcdir)/../lib/kStuff/include AM_CFLAGS = $(GUILE_CFLAGS) # Only process if target is MS-Windows if WINDOWSENV AM_CPPFLAGS += $(W32INC) endif # Extra stuff to include in the distribution. EXTRA_DIST = ChangeLog README build.sh.in $(man_MANS) \ README.customs README.OS2 \ SCOPTIONS SMakefile \ README.Amiga Makefile.ami config.ami make.lnk amiga.c amiga.h \ README.DOS Makefile.DOS configure.bat dosbuild.bat configh.dos\ README.W32 NMakefile config.h.W32 build_w32.bat subproc.bat \ make_msvc_net2003.sln make_msvc_net2003.vcproj \ README.VMS makefile.vms makefile.com config.h-vms \ vmsdir.h vmsfunctions.c vmsify.c vms_exit.c vms_progname.c \ vms_export_symbol.c vms_export_symbol_test.com \ gmk-default.scm gmk-default.h # This is built during configure, but behind configure's back DISTCLEANFILES = build.sh # --------------- Internationalization Section localedir = $(datadir)/locale # --------------- Local INSTALL Section # If necessary, change the gid of the app and turn on the setgid flag. # # Whether or not make needs to be installed setgid. # The value should be either 'true' or 'false'. # On many systems, the getloadavg function (used to implement the '-l' # switch) will not work unless make is installed setgid kmem. # inst_setgid = @NEED_SETGID@ # Install make setgid to this group so it can get the load average. # inst_group = @KMEM_GROUP@ install-exec-local: @if $(inst_setgid); then \ app=$(DESTDIR)$(bindir)/`echo $(bin_PROGRAMS)|sed '$(transform)'`; \ if chgrp $(inst_group) $$app && chmod g+s $$app; then \ echo "chgrp $(inst_group) $$app && chmod g+s $$app"; \ else \ echo "$$app needs to be owned by group $(inst_group) and setgid;"; \ echo "otherwise the '-l' option will probably not work."; \ echo "You may need special privileges to complete the installation"; \ echo "of $$app."; \ fi; \ else true; fi # --------------- Generate the Guile default module content guile.$(OBJEXT): gmk-default.h gmk-default.h: $(srcdir)/gmk-default.scm (echo 'static const char *const GUILE_module_defn = " '\\ \ && sed -e 's/;.*//' -e '/^[ \t]*$$/d' -e 's/"/\\"/g' -e 's/$$/ \\/' \ $(srcdir)/gmk-default.scm \ && echo '";') > $@ # --------------- Local DIST Section # Install the w32 and tests subdirectories # dist-hook: (cd $(srcdir); \ sub=`find w32 tests -follow \( -name .git -o -name .deps -o -name work -o -name .gitignore -o -name \*.orig -o -name \*.rej -o -name \*~ -o -name Makefile \) -prune -o -type f -print`; \ tar chf - $$sub) \ | (cd $(distdir); tar xfBp -) # --------------- Local CHECK Section check-local: check-regression check-loadavg @banner=" Regression PASSED: GNU Make $(VERSION) ($(MAKE_HOST)) built with $(CC) "; \ dashes=`echo "$$banner" | sed s/./=/g`; \ echo; \ echo "$$dashes"; \ echo "$$banner"; \ echo "$$dashes"; \ echo .PHONY: check-loadavg check-regression check-loadavg: loadavg$(EXEEXT) @echo The system uptime program believes the load average to be: -uptime @echo The GNU load average checking code thinks: -./loadavg$(EXEEXT) # The loadavg function is invoked during "make check" to test getloadavg. check_PROGRAMS = loadavg nodist_loadavg_SOURCES = getloadavg.c loadavg_CPPFLAGS = -DTEST loadavg_LDADD = @GETLOADAVG_LIBS@ # > check-regression # # Look for the make test suite, and run it if found and we can find perl. # If we're building outside the tree, we use symlinks to make a local copy of # the test suite. Unfortunately the test suite itself isn't localizable yet. # MAKETESTFLAGS = check-regression: tests/config-flags.pm @if test -f '$(srcdir)/tests/run_make_tests'; then \ ulimit -n 128; \ if $(PERL) -v >/dev/null 2>&1; then \ case `cd '$(srcdir)'; pwd` in `pwd`) : ;; \ *) test -d tests || mkdir tests; \ rm -f srctests; \ if ln -s '$(srcdir)/tests' srctests; then \ for f in run_make_tests run_make_tests.pl test_driver.pl scripts; do \ rm -f tests/$$f; ln -s ../srctests/$$f tests; \ done; fi ;; \ esac; \ echo "cd tests && $(PERL) ./run_make_tests.pl -srcdir $(abs_srcdir) -make ../make$(EXEEXT) $(MAKETESTFLAGS)"; \ cd tests && $(PERL) ./run_make_tests.pl -srcdir '$(abs_srcdir)' -make '../make$(EXEEXT)' $(MAKETESTFLAGS); \ else \ echo "Can't find a working Perl ($(PERL)); the test suite requires Perl."; \ fi; \ else \ echo "Can't find the GNU Make test suite ($(srcdir)/tests)."; \ fi # --------------- Maintainer's Section # Tell automake that I haven't forgotten about this file and it will be # created before we build a distribution (see maintMakefile in the Git # distribution). README: @MAINT_MAKEFILE@ kbuild-3686/src/kmk/vms_exit.c0000664000175000017500000000577015053010075016274 0ustar locutuslocutus/* vms_exit.c * * Wrapper for the VMS exit() command to tranlate UNIX codes to be * encoded for POSIX, but also have VMS severity levels. * The posix_exit() variant only sets a severity level for status code 1. * * Author: John E. Malmberg */ /* Copyright (C) 2014-2016 Free Software Foundation, Inc. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ /* Per copyright assignment agreement with the Free Software Foundation this software may be available under under other license agreements and copyrights. */ #include #include void decc$exit (int status); #ifndef C_FACILITY_NO # define C_FACILITY_NO 0x350000 #endif /* Lowest legal non-success VMS exit code is 8 */ /* GNU make only defines codes 0, 1, 2 */ /* So assume any exit code > 8 is a VMS exit code */ #ifndef MAX_EXPECTED_EXIT_CODE # define MAX_EXPECTED_EXIT_CODE 7 #endif /* Build a Posix Exit with VMS severity */ void vms_exit (int status) { int vms_status; /* Fake the __posix_exit with severity added */ /* Undocumented correct way to do this. */ vms_status = 0; /* The default DECC definition is not compatible with doing a POSIX_EXIT */ /* So fix it. */ if (status == EXIT_FAILURE) status = MAKE_FAILURE; /* Trivial case exit success */ if (status == 0) decc$exit (STS$K_SUCCESS); /* Is this a VMS status then just take it */ if (status > MAX_EXPECTED_EXIT_CODE) { /* Make sure that the message inhibit is set since message has */ /* already been displayed. */ vms_status = status | STS$M_INHIB_MSG; decc$exit (vms_status); } /* Unix status codes are limited to 1 byte, so anything larger */ /* is a probably a VMS exit code and needs to be passed through */ /* A lower value can be set for a macro. */ /* Status 0 is always passed through as it is converted to SS$_NORMAL */ /* Always set the message inhibit bit */ vms_status = C_FACILITY_NO | 0xA000 | STS$M_INHIB_MSG; vms_status |= (status << 3); /* STS$K_ERROR is for status that stops makefile that a simple */ /* Rerun of the makefile will not fix. */ if (status == MAKE_FAILURE) vms_status |= STS$K_ERROR; else if (status == MAKE_TROUBLE) { /* Make trouble is for when make was told to do nothing and */ /* found that a target was not up to date. Since a second */ /* of make will produce the same condition, this is of */ /* Error severity */ vms_status |= STS$K_ERROR; } decc$exit (vms_status); } kbuild-3686/src/kmk/dir-nt-bird.c0000664000175000017500000006336215053010075016552 0ustar locutuslocutus/* $Id: dir-nt-bird.c 3680 2025-08-12 23:32:04Z bird $ */ /** @file * Reimplementation of dir.c for NT using kFsCache. * * This should perform better on NT, especially on machines "infected" * by antivirus programs. */ /* * Copyright (c) 2016 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #include /* locking */ #include "nt/kFsCache.h" #include "makeint.h" #if defined(KMK) && !defined(__OS2__) # include "glob/glob.h" #else # include #endif #include #include "kmkbuiltin.h" #include "kmkbuiltin/err.h" #include "nt_fullpath.h" /* for the time being - will be implemented here later on. */ /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ /** User data key indicating that it's an impossible file to make. * See file_impossible() and file_impossible_p(). */ #define KMK_DIR_NT_IMPOSSIBLE_KEY (~(KUPTR)7) /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ /** * glob directory stream. */ typedef struct KMKNTOPENDIR { /** Reference to the directory. */ PKFSDIR pDir; /** Index of the next directory entry (child) to return. */ KU32 idxNext; /** The structure in which to return the directory entry. */ struct dirent DirEnt; } KMKNTOPENDIR; /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ /** The cache.*/ PKFSCACHE g_pFsCache = NULL; /** Number of times dir_cache_invalid_missing was called. */ static KU32 volatile g_cInvalidates = 0; /** Set by dir_cache_volatile_dir to indicate that the user has marked the * volatile parts of the file system with custom revisioning and we only need to * flush these. This is very handy when using a separate output directory * from the sources. */ static KBOOL g_fFsCacheIsUsingCustomRevision = K_FALSE; /** The ID of the main thread. We currently only let it access the cache. */ static DWORD g_idMainThread = 0; void hash_init_directories(void) { g_idMainThread = GetCurrentThreadId(); g_pFsCache = kFsCacheCreate(0); if (g_pFsCache) return; fputs("kFsCacheCreate failed!", stderr); exit(9); } /** * Checks if @a pszName exists in directory @a pszDir. * * @returns 1 if it does, 0 if it doesn't. * * @param pszDir The directory. * @param pszName The name. * * If empty string, just check if the directory exists. * * If NULL, just read the whole cache the directory into * the cache (we always do that). */ int dir_file_exists_p(const char *pszDir, const char *pszName) { int fRc = 0; KFSLOOKUPERROR enmError; PKFSOBJ pDirObj = kFsCacheLookupA(g_pFsCache, pszDir, &enmError); assert(GetCurrentThreadId() == g_idMainThread); if (pDirObj) { if (pDirObj->bObjType == KFSOBJ_TYPE_DIR) { if (pszName != 0) { /* Empty filename is just checking out the directory. */ if (*pszName == '\0') fRc = 1; else { PKFSOBJ pNameObj = kFsCacheLookupRelativeToDirA(g_pFsCache, (PKFSDIR)pDirObj, pszName, strlen(pszName), 0/*fFlags*/, &enmError, NULL); if (pNameObj) { fRc = pNameObj->bObjType == KFSOBJ_TYPE_MISSING; kFsCacheObjRelease(g_pFsCache, pNameObj); } } } } kFsCacheObjRelease(g_pFsCache, pDirObj); } return fRc; } /** * Checks if a file exists. * * @returns 1 if it does exist, 0 if it doesn't. * @param pszPath The path to check out. * @note Multi-thread safe. */ int file_exists_p(const char *pszPath) { int fRc; KFSLOOKUPERROR enmError; PKFSOBJ pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError); if (pPathObj) { fRc = pPathObj->bObjType != KFSOBJ_TYPE_MISSING; kFsCacheObjRelease(g_pFsCache, pPathObj); } else fRc = 0; return fRc; } /** * Checks if a file exists and is a regular file, given a UTF-16 string. * * @returns 1 if it regular file, 0 if doesn't exist or isn't a file * @param pwszPath The UTF-16 path to check out. * @note Multi-thread safe. */ int utf16_regular_file_p(const wchar_t *pwszPath) { int fRc; KFSLOOKUPERROR enmError; PKFSOBJ pPathObj = kFsCacheLookupW(g_pFsCache, pwszPath, &enmError); if (pPathObj) { fRc = pPathObj->bObjType == KFSOBJ_TYPE_FILE; kFsCacheObjRelease(g_pFsCache, pPathObj); } else fRc = 0; return fRc; } /** * Just a way for vpath.c to get a correctly cased path, I think. * * @returns Directory path in string cache. * @param pszDir The directory. */ const char *dir_name(const char *pszDir) { char szTmp[MAX_PATH]; assert(GetCurrentThreadId() == g_idMainThread); nt_fullpath(pszDir, szTmp, sizeof(szTmp)); return strcache_add(szTmp); } /** * Makes future file_impossible_p calls return 1 for pszPath. */ void file_impossible(const char *pszPath) { KFSLOOKUPERROR enmError; PKFSOBJ pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError); assert(GetCurrentThreadId() == g_idMainThread); if (pPathObj) { kFsCacheObjAddUserData(g_pFsCache, pPathObj, KMK_DIR_NT_IMPOSSIBLE_KEY, sizeof(KFSUSERDATA)); kFsCacheObjRelease(g_pFsCache, pPathObj); } } /** * Makes future file_impossible_p calls return 1 for pszPath. */ int file_impossible_p(const char *pszPath) { int fRc; KFSLOOKUPERROR enmError; PKFSOBJ pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError); assert(GetCurrentThreadId() == g_idMainThread); if (pPathObj) { fRc = kFsCacheObjGetUserData(g_pFsCache, pPathObj, KMK_DIR_NT_IMPOSSIBLE_KEY) != NULL; kFsCacheObjRelease(g_pFsCache, pPathObj); } else fRc = 0; return fRc; } /** * opendir for glob. * * @returns Pointer to DIR like handle, NULL if directory not found. * @param pszDir The directory to enumerate. */ static __ptr_t dir_glob_opendir(const char *pszDir) { KFSLOOKUPERROR enmError; PKFSOBJ pDirObj = kFsCacheLookupA(g_pFsCache, pszDir, &enmError); assert(GetCurrentThreadId() == g_idMainThread); if (pDirObj) { if (pDirObj->bObjType == KFSOBJ_TYPE_DIR) { if (kFsCacheDirEnsurePopuplated(g_pFsCache, (PKFSDIR)pDirObj, NULL)) { KMKNTOPENDIR *pDir = xmalloc(sizeof(*pDir)); pDir->pDir = (PKFSDIR)pDirObj; pDir->idxNext = 0; return pDir; } } kFsCacheObjRelease(g_pFsCache, pDirObj); } return NULL; } /** * readdir for glob. * * @returns Pointer to DIR like handle, NULL if directory not found. * @param pDir Directory enum handle by dir_glob_opendir. */ static struct dirent *dir_glob_readdir(__ptr_t pvDir) { KMKNTOPENDIR *pDir = (KMKNTOPENDIR *)pvDir; KU32 const cChildren = pDir->pDir->cChildren; assert(GetCurrentThreadId() == g_idMainThread); while (pDir->idxNext < cChildren) { PKFSOBJ pEntry = pDir->pDir->papChildren[pDir->idxNext++]; /* Don't return missing objects. */ if (pEntry->bObjType != KFSOBJ_TYPE_MISSING) { /* Copy the name that fits, trying to avoid names with spaces. If neither fits, skip the name. */ if ( pEntry->cchName < sizeof(pDir->DirEnt.d_name) && ( pEntry->pszShortName == pEntry->pszName || memchr(pEntry->pszName, ' ', pEntry->cchName) == NULL)) { pDir->DirEnt.d_namlen = pEntry->cchName; memcpy(pDir->DirEnt.d_name, pEntry->pszName, pEntry->cchName + 1); } else if (pEntry->cchShortName < sizeof(pDir->DirEnt.d_name)) { pDir->DirEnt.d_namlen = pEntry->cchShortName; memcpy(pDir->DirEnt.d_name, pEntry->pszShortName, pEntry->cchShortName + 1); } else continue; pDir->DirEnt.d_reclen = offsetof(struct dirent, d_name) + pDir->DirEnt.d_namlen; if (pEntry->bObjType == KFSOBJ_TYPE_DIR) pDir->DirEnt.d_type = DT_DIR; else if (pEntry->bObjType == KFSOBJ_TYPE_FILE) pDir->DirEnt.d_type = DT_REG; else pDir->DirEnt.d_type = DT_UNKNOWN; return &pDir->DirEnt; } } /* * Fake the '.' and '..' directories because they're not part of papChildren above. */ if (pDir->idxNext < cChildren + 2) { pDir->idxNext++; pDir->DirEnt.d_type = DT_DIR; pDir->DirEnt.d_namlen = pDir->idxNext - cChildren; pDir->DirEnt.d_reclen = offsetof(struct dirent, d_name) + pDir->DirEnt.d_namlen; pDir->DirEnt.d_name[0] = '.'; pDir->DirEnt.d_name[1] = '.'; pDir->DirEnt.d_name[pDir->DirEnt.d_namlen] = '\0'; return &pDir->DirEnt; } return NULL; } /** * closedir for glob. * * @param pDir Directory enum handle by dir_glob_opendir. */ static void dir_glob_closedir(__ptr_t pvDir) { KMKNTOPENDIR *pDir = (KMKNTOPENDIR *)pvDir; assert(GetCurrentThreadId() == g_idMainThread); kFsCacheObjRelease(g_pFsCache, &pDir->pDir->Obj); pDir->pDir = NULL; free(pDir); } /** * stat for glob. * * @returns 0 on success, -1 + errno on failure. * @param pszPath The path to stat. * @param pStat Where to return the info. */ static int dir_glob_stat(const char *pszPath, struct stat *pStat) { KFSLOOKUPERROR enmError; PKFSOBJ pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError); assert(GetCurrentThreadId() == g_idMainThread); /** @todo follow symlinks vs. on symlink! */ if (pPathObj) { if (pPathObj->bObjType != KFSOBJ_TYPE_MISSING) { kHlpAssert(pPathObj->fHaveStats); /* currently always true. */ *pStat = pPathObj->Stats; kFsCacheObjRelease(g_pFsCache, pPathObj); return 0; } kFsCacheObjRelease(g_pFsCache, pPathObj); } errno = ENOENT; return -1; } /** * lstat for glob. * * @returns 0 on success, -1 + errno on failure. * @param pszPath The path to stat. * @param pStat Where to return the info. */ static int dir_glob_lstat(const char *pszPath, struct stat *pStat) { KFSLOOKUPERROR enmError; PKFSOBJ pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError); assert(GetCurrentThreadId() == g_idMainThread); if (pPathObj) { if (pPathObj->bObjType != KFSOBJ_TYPE_MISSING) { kHlpAssert(pPathObj->fHaveStats); /* currently always true. */ *pStat = pPathObj->Stats; kFsCacheObjRelease(g_pFsCache, pPathObj); return 0; } kFsCacheObjRelease(g_pFsCache, pPathObj); errno = ENOENT; } else errno = enmError == KFSLOOKUPERROR_NOT_DIR || enmError == KFSLOOKUPERROR_PATH_COMP_NOT_DIR ? ENOTDIR : ENOENT; return -1; } /** * Checks if @a pszDir exists and is a directory. * * @returns 1 if is directory, 0 if isn't or doesn't exists. * @param pszDir The alleged directory. */ static int dir_globl_dir_exists_p(const char *pszDir) { int fRc; KFSLOOKUPERROR enmError; PKFSOBJ pDirObj = kFsCacheLookupA(g_pFsCache, pszDir, &enmError); assert(GetCurrentThreadId() == g_idMainThread); if (pDirObj) { fRc = pDirObj->bObjType == KFSOBJ_TYPE_DIR; kFsCacheObjRelease(g_pFsCache, pDirObj); } else fRc = 0; return fRc; } /** * Sets up pGlob with the necessary callbacks. * * @param pGlob Structure to populate. */ void dir_setup_glob(glob_t *pGlob) { assert(GetCurrentThreadId() == g_idMainThread); pGlob->gl_opendir = dir_glob_opendir; pGlob->gl_readdir = dir_glob_readdir; pGlob->gl_closedir = dir_glob_closedir; pGlob->gl_stat = dir_glob_stat; #ifdef __EMX__ /* The FreeBSD implementation actually uses gl_lstat!! */ pGlob->gl_lstat = dir_glob_lstat; #else pGlob->gl_exists = file_exists_p; pGlob->gl_isdir = dir_globl_dir_exists_p; #endif } /** * Print statitstics. */ void print_dir_stats(void) { FILE *pOut = stdout; KU32 cMisses; fputs("\n" "# NT dir cache stats:\n", pOut); fprintf(pOut, "# %" KSIZE_PRI_U " objects, taking up %" KSIZE_PRI_U "(%#" KSIZE_PRI_X ") bytes, avg %" KSIZE_PRI_U " bytes\n", g_pFsCache->cObjects, g_pFsCache->cbObjects, g_pFsCache->cbObjects, g_pFsCache->cbObjects / g_pFsCache->cObjects); fprintf(pOut, "# %" KSIZE_PRI_U " A path hashes, taking up %" KSIZE_PRI_U " (%#" KSIZE_PRI_X ") bytes, avg %" KSIZE_PRI_U " bytes, %" KSIZE_PRI_U " collision\n", g_pFsCache->cAnsiPaths, g_pFsCache->cbAnsiPaths, g_pFsCache->cbAnsiPaths, g_pFsCache->cbAnsiPaths / K_MAX(g_pFsCache->cAnsiPaths, 1), g_pFsCache->cAnsiPathCollisions); #ifdef KFSCACHE_CFG_UTF16 fprintf(pOut, "# %" KSIZE_PRI_U " W path hashes, taking up %" KSIZE_PRI_U " (%#" KSIZE_PRI_X ") bytes, avg %" KSIZE_PRI_U " bytes, %" KSIZE_PRI_U " collisions\n", g_pFsCache->cUtf16Paths, g_pFsCache->cbUtf16Paths, g_pFsCache->cbUtf16Paths, g_pFsCache->cbUtf16Paths / K_MAX(g_pFsCache->cUtf16Paths, 1), g_pFsCache->cUtf16PathCollisions); #endif fprintf(pOut, "# %" KSIZE_PRI_U " child hash tables, total of %" KSIZE_PRI_U " entries, %" KSIZE_PRI_U " children inserted, %" KSIZE_PRI_U " collisions\n", g_pFsCache->cChildHashTabs, g_pFsCache->cChildHashEntriesTotal, g_pFsCache->cChildHashed, g_pFsCache->cChildHashCollisions); cMisses = g_pFsCache->cLookups - g_pFsCache->cPathHashHits - g_pFsCache->cWalkHits; fprintf(pOut, "# %" KSIZE_PRI_U " lookups: %" KSIZE_PRI_U " (%" KU64_PRI " %%) path hash hits, %" KSIZE_PRI_U " (%" KU64_PRI "%%) walks hits, %" KU32_PRI " (%" KU64_PRI "%%) misses\n", g_pFsCache->cLookups, g_pFsCache->cPathHashHits, g_pFsCache->cPathHashHits * (KU64)100 / K_MAX(g_pFsCache->cLookups, 1), g_pFsCache->cWalkHits, g_pFsCache->cWalkHits * (KU64)100 / K_MAX(g_pFsCache->cLookups, 1), cMisses, cMisses * (KU64)100 / K_MAX(g_pFsCache->cLookups, 1)); fprintf(pOut, "# %" KSIZE_PRI_U " child searches, %" KSIZE_PRI_U " (%" KU64_PRI "%%) hash hits\n", g_pFsCache->cChildSearches, g_pFsCache->cChildHashHits, g_pFsCache->cChildHashHits * (KU64)100 / K_MAX(g_pFsCache->cChildSearches, 1)); } void print_dir_data_base(void) { /** @todo. */ } /* duplicated in kWorker.c * Note! Tries avoid to produce a result with spaces since they aren't supported by makefiles. */ void nt_fullpath_cached(const char *pszPath, char *pszFull, size_t cbFull) { KFSLOOKUPERROR enmError; PKFSOBJ pPathObj; KFSCACHE_LOCK(g_pFsCache); /* let's start out being careful. */ pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError); if (pPathObj) { KSIZE off = pPathObj->cchParent; if (off > 0) { KSIZE offEnd = off + pPathObj->cchName; if (offEnd < cbFull) { PKFSDIR pAncestor; pszFull[offEnd] = '\0'; memcpy(&pszFull[off], pPathObj->pszName, pPathObj->cchName); for (pAncestor = pPathObj->pParent; off > 0; pAncestor = pAncestor->Obj.pParent) { kHlpAssert(off > 1); kHlpAssert(pAncestor != NULL); kHlpAssert(pAncestor->Obj.cchName > 0); pszFull[--off] = '/'; #ifdef KFSCACHE_CFG_SHORT_NAMES if ( pAncestor->Obj.pszName == pAncestor->Obj.pszShortName || memchr(pAncestor->Obj.pszName, ' ', pAncestor->Obj.cchName) == NULL) #endif { off -= pAncestor->Obj.cchName; kHlpAssert(pAncestor->Obj.cchParent == off); memcpy(&pszFull[off], pAncestor->Obj.pszName, pAncestor->Obj.cchName); } #ifdef KFSCACHE_CFG_SHORT_NAMES else { /* * The long name constains a space, so use the alternative name instead. * Most likely the alternative name differs in length, usually it's shorter, * so we have to shift the part of the path we've already assembled * accordingly. */ KSSIZE cchDelta = (KSSIZE)pAncestor->Obj.cchShortName - (KSSIZE)pAncestor->Obj.cchName; if (cchDelta != 0) { if ((KSIZE)(offEnd + cchDelta) >= cbFull) goto l_fallback; memmove(&pszFull[off + cchDelta], &pszFull[off], offEnd + 1 - off); off += cchDelta; offEnd += cchDelta; } off -= pAncestor->Obj.cchShortName; kHlpAssert(pAncestor->Obj.cchParent == off); memcpy(&pszFull[off], pAncestor->Obj.pszShortName, pAncestor->Obj.cchShortName); } #endif } kFsCacheObjRelease(g_pFsCache, pPathObj); KFSCACHE_UNLOCK(g_pFsCache); return; } } else { if ((size_t)pPathObj->cchName + 1 < cbFull) { /* Assume no spaces here. */ memcpy(pszFull, pPathObj->pszName, pPathObj->cchName); pszFull[pPathObj->cchName] = '/'; pszFull[pPathObj->cchName + 1] = '\0'; kFsCacheObjRelease(g_pFsCache, pPathObj); KFSCACHE_UNLOCK(g_pFsCache); return; } } /* do fallback. */ #ifdef KFSCACHE_CFG_SHORT_NAMES l_fallback: #endif kHlpAssertFailed(); kFsCacheObjRelease(g_pFsCache, pPathObj); } KFSCACHE_UNLOCK(g_pFsCache); nt_fullpath(pszPath, pszFull, cbFull); } /** * Special stat call used by remake.c * * @returns 0 on success, -1 + errno on failure. * @param pszPath The path to stat. * @param pStat Where to return the mtime field only. */ int stat_only_mtime(const char *pszPath, struct stat *pStat) { /* Currently a little expensive, so just hit the file system once the jobs starts comming in. */ assert(GetCurrentThreadId() == g_idMainThread); if (g_cInvalidates == 0) { KFSLOOKUPERROR enmError; PKFSOBJ pPathObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError); if (pPathObj) { if (pPathObj->bObjType != KFSOBJ_TYPE_MISSING) { kHlpAssert(pPathObj->fHaveStats); /* currently always true. */ pStat->st_mtime = pPathObj->Stats.st_mtime; kFsCacheObjRelease(g_pFsCache, pPathObj); return 0; } kFsCacheObjRelease(g_pFsCache, pPathObj); errno = ENOENT; } else errno = enmError == KFSLOOKUPERROR_NOT_DIR || enmError == KFSLOOKUPERROR_PATH_COMP_NOT_DIR ? ENOTDIR : ENOENT; return -1; } return birdStatModTimeOnly(pszPath, &pStat->st_mtim, 1 /*fFollowLink*/); } /** * Do cache invalidation after a job completes. */ void dir_cache_invalid_after_job(void) { assert(GetCurrentThreadId() == g_idMainThread); g_cInvalidates++; if (g_fFsCacheIsUsingCustomRevision) kFsCacheInvalidateCustomBoth(g_pFsCache); else kFsCacheInvalidateAll(g_pFsCache); } /** * Invalidate the whole directory cache * * Used by $(dircache-ctl invalidate) * @note Multi-thread safe. */ void dir_cache_invalid_all(void) { g_cInvalidates++; kFsCacheInvalidateAll(g_pFsCache); } /** * Invalidate the whole directory cache and closes all open handles. * * Used by $(dircache-ctl invalidate-and-close-dirs) * @param including_root Also close the root directory. * @note Multi-thread safe. */ void dir_cache_invalid_all_and_close_dirs(int including_root) { g_cInvalidates++; kFsCacheInvalidateAllAndCloseDirs(g_pFsCache, !!including_root); } /** * Invalidate missing bits of the directory cache. * * Used by $(dircache-ctl invalidate-missing) * @note Multi-thread safe. */ void dir_cache_invalid_missing(void) { g_cInvalidates++; kFsCacheInvalidateAll(g_pFsCache); } /** * Invalidate the volatile bits of the directory cache. * * Used by $(dircache-ctl invalidate-missing) * @note Multi-thread safe. */ void dir_cache_invalid_volatile(void) { g_cInvalidates++; if (g_fFsCacheIsUsingCustomRevision) kFsCacheInvalidateCustomBoth(g_pFsCache); else kFsCacheInvalidateAll(g_pFsCache); } /** * Used by $(dircache-ctl ) to mark a directory subtree or file as volatile. * * The first call changes the rest of the cache to be considered non-volatile. * * @returns 0 on success, -1 on failure. * @param pszDir The directory (or file for what that is worth). */ int dir_cache_volatile_dir(const char *pszDir) { KFSLOOKUPERROR enmError; PKFSOBJ pObj = kFsCacheLookupA(g_pFsCache, pszDir, &enmError); assert(GetCurrentThreadId() == g_idMainThread); if (pObj) { KBOOL fRc = kFsCacheSetupCustomRevisionForTree(g_pFsCache, pObj); kFsCacheObjRelease(g_pFsCache, pObj); if (fRc) { g_fFsCacheIsUsingCustomRevision = K_TRUE; return 0; } OS(error, reading_file, "failed to mark '%s' as volatile", pszDir); } else OS(error, reading_file, "failed to mark '%s' as volatile (not found)", pszDir); return -1; } /** * Invalidates a deleted directory so the cache can close handles to it. * * Used by kmk_builtin_rm and kmk_builtin_rmdir. * * @returns 0 on success, -1 on failure. * @param pszDir The directory to invalidate as deleted. */ int dir_cache_deleted_directory(const char *pszDir) { assert(GetCurrentThreadId() == g_idMainThread); if (kFsCacheInvalidateDeletedDirectoryA(g_pFsCache, pszDir)) return 0; return -1; } int kmk_builtin_dircache(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { assert(GetCurrentThreadId() == g_idMainThread); if (argc >= 2) { const char *pszCmd = argv[1]; if (strcmp(pszCmd, "invalidate") == 0) { if (argc == 2) { dir_cache_invalid_all(); return 0; } errx(pCtx, 2, "the 'invalidate' command takes no arguments!\n"); } else if (strcmp(pszCmd, "invalidate-missing") == 0) { if (argc == 2) { dir_cache_invalid_missing (); return 0; } errx(pCtx, 2, "the 'invalidate-missing' command takes no arguments!\n"); } else if (strcmp(pszCmd, "volatile") == 0) { int i; for (i = 2; i < argc; i++) dir_cache_volatile_dir(argv[i]); return 0; } else if (strcmp(pszCmd, "deleted") == 0) { int i; for (i = 2; i < argc; i++) dir_cache_deleted_directory(argv[i]); return 0; } else errx(pCtx, 2, "Invalid command '%s'!\n", pszCmd); } else errx(pCtx, 2, "No command given!\n"); K_NOREF(envp); return 2; } kbuild-3686/src/kmk/output.c0000664000175000017500000016540715053010075016002 0ustar locutuslocutus/* Output to stdout / stderr for GNU make Copyright (C) 2013-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #if defined (KBUILD_OS_WINDOWS) && (defined(KMK) || defined(DEBUG_STDOUT_CLOSE_ISSUE)) # include "nt/ntstuff.h" # include "nt/nthlp.h" # include #endif #include "makeint.h" #include "job.h" /* GNU make no longer supports pre-ANSI89 environments. */ #include #include #include #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_FCNTL_H # include #else # include #endif #ifdef WINDOWS32 # include # include # ifndef CONFIG_NEW_WIN_CHILDREN # include "sub_proc.h" # else # include "w32/winchildren.h" # endif #endif /* WINDOWS32 */ #ifdef KBUILD_OS_WINDOWS # include "console.h" #endif struct output *output_context = NULL; unsigned int stdio_traced = 0; #define OUTPUT_NONE (-1) #define OUTPUT_ISSET(_out) ((_out)->out >= 0 || (_out)->err >= 0) #ifdef HAVE_FCNTL_H # define STREAM_OK(_s) ((fcntl (fileno (_s), F_GETFD) != -1) || (errno != EBADF)) #else # define STREAM_OK(_s) 1 #endif #ifdef DEBUG_STDOUT_CLOSE_ISSUE /* fflush wrapper w/ error checking + reporting for stdout. This is to debug the mysterious 'kmk: write error: stdout' errors. */ int g_fStdOutError = 0; # ifdef KBUILD_OS_WINDOWS static void my_output_pipe_info (HANDLE hStdOut, const char *pszWhere) { MY_IO_STATUS_BLOCK Ios = {0} ; struct MY_FILE_PIPE_INFORMATION { ULONG ReadMode; ULONG CompletionMode; } Info1 = {0}; MY_NTSTATUS rcNt1 = g_pfnNtQueryInformationFile(hStdOut, &Ios, &Info1, sizeof(Info1), MyFilePipeInformation); struct MY_FILE_PIPE_LOCAL_INFORMATION { ULONG NamedPipeType; ULONG NamedPipeConfiguration; ULONG MaximumInstances; ULONG CurrentInstances; ULONG InboundQuota; ULONG ReadDataAvailable; ULONG OutboundQuota; ULONG WriteQuotaAvailable; ULONG NamedPipeState; ULONG NamedPipeEnd; } Info2 = {0}; MY_NTSTATUS rcNt2 = g_pfnNtQueryInformationFile(hStdOut, &Ios, &Info2, sizeof(Info2), MyFilePipeLocalInformation); union { BYTE ab[1024]; MY_FILE_NAME_INFORMATION NameInfo; } uBuf = {{0}}; MY_NTSTATUS rcNt3 = g_pfnNtQueryInformationFile(hStdOut, &Ios, &uBuf, sizeof(uBuf) - sizeof(WCHAR), MyFileNameInformation); DWORD dwMode = 0; MY_NTSTATUS rcNt4 = g_pfnNtQueryInformationFile(hStdOut, &Ios, &dwMode, sizeof(dwMode), MyFileModeInformation); fprintf(stderr, "kmk[%u/%u]: stdout pipeinfo at %s: fmode=%#x pipemode=%#x complmode=%#x type=%#x cfg=%#x instances=%u/%u inquota=%#x readable=%#x outquota=%#x writable=%#x state=%#x end=%#x hStdOut=%p %S rcNt=%#x/%#x/%#x/%#x\n", makelevel, _getpid(), pszWhere, dwMode, Info1.ReadMode, Info1.CompletionMode, Info2.NamedPipeType, Info2.NamedPipeConfiguration, Info2.CurrentInstances, Info2.MaximumInstances, Info2.InboundQuota, Info2.ReadDataAvailable, Info2.OutboundQuota, Info2.WriteQuotaAvailable, Info2.NamedPipeState, Info2.NamedPipeEnd, hStdOut, uBuf.NameInfo.FileName, rcNt1, rcNt2, rcNt3, rcNt4); } # endif /* KBUILD_OS_WINDOWS */ static void my_stdout_error (const char *pszOperation, const char *pszMessage) { # ifdef KBUILD_OS_WINDOWS DWORD const dwErr = GetLastError (); # endif int const iErrNo = errno; int const fdFile = fileno (stdout); # ifdef KBUILD_OS_WINDOWS HANDLE const hNative = (HANDLE)_get_osfhandle (_fileno (stdout)); DWORD const dwType = GetFileType (hNative); unsigned int uDosErr = _doserrno; if ((dwType & ~FILE_TYPE_REMOTE) == FILE_TYPE_PIPE) my_output_pipe_info (hNative, "error"); fprintf (stderr, "kmk[%u/%u]: stdout error: %s: %s! (lasterr=%u errno=%d fileno=%d uDosErr=%u native=%p type=%#x)\n", makelevel, _getpid(), pszOperation, pszMessage, dwErr, iErrNo, fdFile, uDosErr, hNative, dwType); # else fprintf (stderr, "kmk[%u]: stdout error: %s: %s! (lasterr=%u errno=%d fileno=%d)\n", makelevel, pszOperation, pszMessage, dwErr, iErrNo, fdFile); # endif } /* Preserves errno and win32 last error. */ void my_check_stdout (const char *pszWhere) { if (!g_fStdOutError) { # ifdef KBUILD_OS_WINDOWS DWORD const dwErrSaved = GetLastError(); # endif int const iErrNoSaved = errno; if (ferror (stdout)) { my_stdout_error (pszWhere, "error pending!"); g_fStdOutError = 1; } errno = iErrNoSaved; # ifdef KBUILD_OS_WINDOWS SetLastError(dwErrSaved); # endif } } # ifdef KBUILD_OS_WINDOWS /* generic fwrite wrapper */ __declspec(dllexport) size_t __cdecl fwrite(void const *pvBuf, size_t cbItem, size_t cItems, FILE *pFile) { size_t cbWritten; if (pFile == stdout) my_check_stdout("fwrite/entry"); _lock_file(pFile); cbWritten = _fwrite_nolock(pvBuf, cbItem, cItems, pFile); _unlock_file(pFile); if (pFile == stdout) my_check_stdout("fwrite/exit"); return cbWritten; } void * const __imp_fwrite = (void *)(uintptr_t)fwrite; /* generic fflush wrapper */ __declspec(dllexport) int __cdecl fflush(FILE *pFile) { int rc; if (pFile == stdout || !pFile) my_check_stdout("fflush/entry"); if (pFile) { _lock_file(pFile); rc = _fflush_nolock(pFile); _unlock_file(pFile); } if (pFile == stdout || !pFile) my_check_stdout("fflush/exit"); return rc; } void * const __imp_fflush = (void *)(uintptr_t)fflush; # else static int my_fflush (FILE *pFile) { if (pFile == stdout && !g_fStdOutError) { if (!ferror (pFile)) { int rcRet = fflush (pFile); g_fStdOutError = ferror (pFile); if (rcRet != EOF && !g_fStdOutError) { /* likely */ } else if (rcRet == EOF) my_stdout_error ("fflush(stdout)", "flush failed!"); else my_stdout_error ("fflush(stdout)", "error pending after successful flush!"); return rcRet; } else { my_stdout_error ("fflush(stdout)", "error pending on entry!"); g_fStdOutError = 1; } } return fflush (pFile); } # undef fflush # define fflush(a_pFile) my_fflush(a_pFile) # endif #endif /* DEBUG_STDOUT_CLOSE_ISSUE */ #if defined(KBUILD_OS_WINDOWS) && defined(KMK) /* Windows Asynchronous (Overlapping) Pipe Hack -------------------------------------------- If a write pipe is opened with FILE_FLAG_OVERLAPPED or equivalent flags, concurrent WriteFile calls on that pipe may run into a race causing the wrong thread to be worken up on completion. Since the write is still pending, the number of bytes written hasn't been set and is still zero. This leads to UCRT setting errno = ENOSPC and may cause stack corruption when the write is finally completed and the IO_STATUS_BLOCK is written by the kernel. To work around this problem, we detect asynchronous pipes attached to stdout and stderr and replaces them with standard pipes and threads pumping output. The thread deals properly with the async writes. */ /* Data for the pipe workaround hacks. */ struct win_pipe_hacks { /* 1 (stdout) or 2 (stderr). */ int fd; int volatile fShutdown; /** Event handle for overlapped I/O. */ HANDLE hEvt; /* The original pipe that's in overlapping state (write end). */ HANDLE hDstPipe; /* The replacement pipe (read end). */ HANDLE hSrcPipe; /** The thread pumping bytes between the two pipes. */ HANDLE hThread; /** Putting the overlapped I/O structure here is safer. */ OVERLAPPED Overlapped; } g_pipe_workarounds[2] = { { 1, 0, NULL, NULL, NULL, NULL, { 0, 0, {{ 0, 0}}} }, { 2, 0, NULL, NULL, NULL, NULL, { 0, 0, {{ 0, 0}}} }, }; /* Thread function that pumps bytes between our pipe and the parents pipe. */ static unsigned __stdcall win_pipe_pump_thread (void *user) { unsigned const idx = (unsigned)(intptr_t)user; int fQuit = 0; do { /* Read from the source pipe (our). */ char achBuf[4096]; DWORD cbRead = 0; if (ReadFile (g_pipe_workarounds[idx].hSrcPipe, achBuf, sizeof(achBuf), &cbRead, NULL)) { for (unsigned iWrite = 0, off = 0; off < cbRead && !fQuit; iWrite++) { /* Write the data we've read to the origianl pipe, using overlapped I/O. This should work fine even if hDstPipe wasn't opened in overlapped I/O mode. */ g_pipe_workarounds[idx].Overlapped.Internal = 0; g_pipe_workarounds[idx].Overlapped.InternalHigh = 0; g_pipe_workarounds[idx].Overlapped.Offset = 0xffffffff /*FILE_WRITE_TO_END_OF_FILE*/; g_pipe_workarounds[idx].Overlapped.OffsetHigh = (DWORD)-1; g_pipe_workarounds[idx].Overlapped.hEvent = g_pipe_workarounds[idx].hEvt; DWORD cbWritten = 0; if (!WriteFile (g_pipe_workarounds[idx].hDstPipe, &achBuf[off], cbRead - off, &cbWritten, &g_pipe_workarounds[idx].Overlapped)) { if ((fQuit = GetLastError () != ERROR_IO_PENDING)) break; if ((fQuit = !GetOverlappedResult (g_pipe_workarounds[idx].hDstPipe, &g_pipe_workarounds[idx].Overlapped, &cbWritten, TRUE))) break; } off += cbWritten; if (cbWritten == 0 && iWrite > 15) { DWORD fState = 0; if ( GetNamedPipeHandleState(g_pipe_workarounds[idx].hDstPipe, &fState, NULL, NULL, NULL, NULL, 0) && (fState & (PIPE_WAIT | PIPE_NOWAIT)) == PIPE_NOWAIT) { fState &= ~PIPE_NOWAIT; fState |= PIPE_WAIT; if ( SetNamedPipeHandleState(g_pipe_workarounds[idx].hDstPipe, &fState, NULL, NULL) && iWrite == 16) continue; } Sleep(iWrite & 15); } } } else break; } while (!g_pipe_workarounds[idx].fShutdown && !fQuit); /* Cleanup. */ CloseHandle (g_pipe_workarounds[idx].hSrcPipe); g_pipe_workarounds[idx].hSrcPipe = NULL; CloseHandle (g_pipe_workarounds[idx].hDstPipe); g_pipe_workarounds[idx].hDstPipe = NULL; CloseHandle (g_pipe_workarounds[idx].hEvt); g_pipe_workarounds[idx].hEvt = NULL; return 0; } /* Shuts down the thread pumping bytes between our pipe and the parents pipe. */ static void win_pipe_hack_terminate (void) { for (unsigned idx = 0; idx < 2; idx++) if (g_pipe_workarounds[idx].hThread != NULL) { g_pipe_workarounds[idx].fShutdown++; if (g_pipe_workarounds[idx].hSrcPipe != NULL) CancelIoEx (g_pipe_workarounds[idx].hSrcPipe, NULL); } for (unsigned idx = 0; idx < 2; idx++) if (g_pipe_workarounds[idx].hThread != NULL) for (unsigned msWait = 64; msWait <= 1000; msWait *= 2) /* wait almost 2 seconds. */ { if (g_pipe_workarounds[idx].hSrcPipe != NULL) CancelIoEx (g_pipe_workarounds[idx].hSrcPipe, NULL); DWORD dwWait = WaitForSingleObject (g_pipe_workarounds[idx].hThread, msWait); if (dwWait == WAIT_OBJECT_0) { CloseHandle (g_pipe_workarounds[idx].hThread); g_pipe_workarounds[idx].hThread = NULL; break; } } } /* Applies the asynchronous pipe hack to a standard handle. The hPipe argument is the handle, and idx is 0 for stdout and 1 for stderr. */ static void win_pipe_hack_apply (HANDLE hPipe, int idx, int fSameObj) { /* Create a normal pipe and assign it to an CRT file descriptor. The handles will be created as not inheritable, but the _dup2 call below will duplicate the write handle with inhertiance enabled. */ HANDLE hPipeR = NULL; HANDLE hPipeW = NULL; if (CreatePipe (&hPipeR, &hPipeW, NULL, 0x1000)) { int fdTmp = _open_osfhandle ((intptr_t)hPipeW, _O_TEXT); if (fdTmp >= 0) { int const fOldMode = _setmode (idx + 1, _O_TEXT); if (fOldMode != _O_TEXT && fOldMode != -1) { _setmode (idx + 1, fOldMode); _setmode (fdTmp, fOldMode); } /* Create the event sempahore. */ HANDLE hEvt = CreateEventW (NULL, FALSE, FALSE, NULL); if (hEvt != NULL && hEvt != INVALID_HANDLE_VALUE) { /* Duplicate the pipe, as the _dup2 call below will (probably) close it. */ HANDLE hDstPipe = NULL; if (DuplicateHandle (GetCurrentProcess (), hPipe, GetCurrentProcess (), &hDstPipe, 0, FALSE, DUPLICATE_SAME_ACCESS)) { /* Create a thread for safely pumping bytes between the pipes. */ g_pipe_workarounds[idx].hEvt = hEvt; g_pipe_workarounds[idx].fShutdown = 0; g_pipe_workarounds[idx].hDstPipe = hDstPipe; g_pipe_workarounds[idx].hSrcPipe = hPipeR; HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, win_pipe_pump_thread, (void *)(intptr_t)idx, 0, NULL); if (hThread != NULL && hThread != INVALID_HANDLE_VALUE) { g_pipe_workarounds[idx].hThread = hThread; /* Now that the thread is operating, replace the file descriptors(s). This involves DuplicateHandle and will call SetStdHandle. */ if (_dup2 (fdTmp, idx + 1) == 0) { if ( fSameObj && _dup2 (fdTmp, idx + 2) != 0) { fprintf (stderr, "%s: warning: _dup2(%d,%d) failed - fSameObj=1: %s (%d, %u)", program, fdTmp, idx + 2, strerror (errno), errno, GetLastError ()); fSameObj = 0; } /* Boost the thread priority. */ int const iPrioOld = GetThreadPriority (hThread); int const iPrioNew = iPrioOld < THREAD_PRIORITY_NORMAL ? THREAD_PRIORITY_NORMAL : iPrioOld < THREAD_PRIORITY_HIGHEST ? THREAD_PRIORITY_HIGHEST : iPrioOld; if (iPrioOld != iPrioNew) SetThreadPriority (hThread, iPrioNew); /* Update the standard handle and close the temporary file descriptor. */ close (fdTmp); return; } g_pipe_workarounds[idx].fShutdown = 1; fprintf (stderr, "%s: warning: _dup2(%d,%d) failed: %s (%d, %u)", program, fdTmp, idx + 1, strerror (errno), errno, GetLastError ()); for (unsigned msWait = 64; msWait <= 1000; msWait *= 2) /* wait almost 2 seconds. */ { if (g_pipe_workarounds[idx].hSrcPipe != NULL) CancelIoEx (g_pipe_workarounds[idx].hSrcPipe, NULL); DWORD dwWait = WaitForSingleObject (hThread, msWait); if (dwWait == WAIT_OBJECT_0) break; } CloseHandle (g_pipe_workarounds[idx].hThread); } else fprintf (stderr, "%s: warning: _beginthreadex failed: %s (%d, %u)", program, strerror (errno), errno, GetLastError ()); CloseHandle (hDstPipe); } else fprintf (stderr, "%s: warning: DuplicateHandle failed: %u", program, GetLastError ()); } else fprintf (stderr, "%s: warning: CreateEventW failed: %u", program, GetLastError ()); close (fdTmp); } else { fprintf (stderr, "%s: warning: _open_osfhandle failed: %s (%d, %u)", program, strerror (errno), errno, GetLastError ()); CloseHandle (hPipeW); } CloseHandle (hPipeR); } else fprintf (stderr, "%s: warning: CreatePipe failed: %u", program, GetLastError()); } /* Check if the two handles refers to the same pipe. */ int win_pipe_is_same_object (HANDLE hPipe1, HANDLE hPipe2) { if (hPipe1 == NULL || hPipe1 == INVALID_HANDLE_VALUE) return 0; if (hPipe1 == hPipe2) return 1; /* Since windows 10 there is an API for this. */ typedef BOOL (WINAPI *PFNCOMPAREOBJECTHANDLES)(HANDLE, HANDLE); static int s_fInitialized = 0; static PFNCOMPAREOBJECTHANDLES s_pfnCompareObjectHandles = NULL; PFNCOMPAREOBJECTHANDLES pfnCompareObjectHandles = s_pfnCompareObjectHandles; if (!pfnCompareObjectHandles && !s_fInitialized) { pfnCompareObjectHandles = (PFNCOMPAREOBJECTHANDLES)GetProcAddress (GetModuleHandleW (L"kernelbase.dll"), "CompareObjectHandles"); s_pfnCompareObjectHandles = pfnCompareObjectHandles; s_fInitialized = 1; } if (pfnCompareObjectHandles) return pfnCompareObjectHandles (hPipe1, hPipe2); /* Otherwise we use FileInternalInformation, assuming ofc that the two are local pipes. */ birdResolveImportsWorker(); MY_IO_STATUS_BLOCK Ios = {0}; MY_FILE_INTERNAL_INFORMATION Info1; MY_NTSTATUS rcNt = g_pfnNtQueryInformationFile (hPipe1, &Ios, &Info1, sizeof(Info1), MyFileInternalInformation); if (!NT_SUCCESS (rcNt)) return 0; MY_FILE_INTERNAL_INFORMATION Info2; rcNt = g_pfnNtQueryInformationFile (hPipe2, &Ios, &Info2, sizeof(Info2), MyFileInternalInformation); if (!NT_SUCCESS (rcNt)) return 0; return Info1.IndexNumber.QuadPart == Info2.IndexNumber.QuadPart; } /* Predicate function that checks if the hack is required. */ static int win_pipe_hack_needed (HANDLE hPipe, const char *pszEnvVarOverride) { birdResolveImportsWorker (); /* Check the environment variable override first. Setting it to '0' disables the hack, setting to anything else (other than an empty string) forces the hack to be enabled. */ const char * const pszValue = getenv (pszEnvVarOverride); if (pszValue && *pszValue != '\0') return *pszValue != '0'; /* Check whether it is a pipe next. */ DWORD const fType = GetFileType (hPipe) & ~FILE_TYPE_REMOTE; if (fType != FILE_TYPE_PIPE) return 0; /* Check if the pipe is synchronous or overlapping. If it's overlapping we must apply the workaround. */ MY_IO_STATUS_BLOCK Ios = {0}; DWORD fFlags = 0; MY_NTSTATUS rcNt = g_pfnNtQueryInformationFile (hPipe, &Ios, &fFlags, sizeof(fFlags), MyFileModeInformation); if ( NT_SUCCESS(rcNt) && !(fFlags & (FILE_SYNCHRONOUS_IO_NONALERT | FILE_SYNCHRONOUS_IO_ALERT))) return 1; #if 1 /* We could also check if the pipe is in NOWAIT mode, but since we've got code elsewhere for switching them to WAIT mode, we probably don't need to do that... */ if ( GetNamedPipeHandleStateW (hPipe, &fFlags, NULL, NULL, NULL, NULL, 0) && (fFlags & PIPE_NOWAIT)) return 1; #endif return 0; } /** Initializes the pipe hack. */ static void win_pipe_hack_init (void) { HANDLE const hStdOut = (HANDLE)_get_osfhandle (_fileno (stdout)); int const fStdOutNeeded = win_pipe_hack_needed (hStdOut, "KMK_PIPE_HACK_STDOUT"); HANDLE const hStdErr = (HANDLE)_get_osfhandle (_fileno (stderr)); int const fStdErrNeeded = win_pipe_hack_needed (hStdErr, "KMK_PIPE_HACK_STDERR"); /* To avoid getting too mixed up output in a 'kmk |& tee log' situation, we must try figure out if the two handles refer to the same pipe object. */ int const fSameObj = fStdOutNeeded && fStdErrNeeded && win_pipe_is_same_object (hStdOut, hStdOut); /* Apply the hack as needed. */ if (fStdOutNeeded) win_pipe_hack_apply (hStdOut, 0, fSameObj); if (fStdErrNeeded && !fSameObj) win_pipe_hack_apply (hStdErr, 1, 0); if (getenv ("KMK_PIPE_HACK_DEBUG")) fprintf (stderr, "fStdOutNeeded=%d fStdErrNeeded=%d fSameObj=%d\n", fStdOutNeeded, fStdErrNeeded, fSameObj); } #endif /* KBUILD_OS_WINDOWS && KMK */ #if defined(KMK) && !defined(NO_OUTPUT_SYNC) /* Non-negative if we're counting output lines. This is used by die_with_job_output to decide whether the initial build error needs to be repeated because there was too much output from parallel jobs between it and the actual make termination. */ int output_metered = -1; static void meter_output_block (char const *buffer, size_t len) { while (len > 0) { char *nl = (char *)memchr (buffer, '\n', len); size_t linelen; if (nl) { linelen = nl - buffer + 1; output_metered++; } else linelen = len; output_metered += linelen / 132; /* advance */ buffer += linelen; len -= linelen; } } #endif #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY # define MEMBUF_MIN_SEG_SIZE 4096 # define MEMBUF_MAX_SEG_SIZE (512*1024) # define MEMBUF_MAX_MOVE_LEN ( MEMBUF_MIN_SEG_SIZE \ - offsetof (struct output_segment, runs) \ - sizeof (struct output_run)) # define MEMBUF_MAX_TOTAL ( sizeof (void *) <= 4 \ ? (size_t)512*1024 : (size_t)16*1024*1024 ) static void *acquire_semaphore (void); static void release_semaphore (void *); static int log_working_directory (int); /* Is make's stdout going to the same place as stderr? Also, did we already sync_init (== -1)? */ static int combined_output = -1; /* Helper for membuf_reset and output_reset */ static membuf_reset (struct output *out) { struct output_segment *seg; while ((seg = out->out.head_seg)) { out->out.head_seg = seg->next; free (seg); } out->out.tail_seg = NULL; out->out.tail_run = NULL; out->out.head_run = NULL; out->out.left = 0; out->out.total = 0; while ((seg = out->err.head_seg)) { out->err.head_seg = seg->next; free (seg); } out->err.tail_seg = NULL; out->err.tail_run = NULL; out->err.head_run = NULL; out->err.left = 0; out->err.total = 0; out->seqno = 0; } /* Used by die_with_job_output to suppress output when it shouldn't be repeated. */ void output_reset (struct output *out) { if (out && (out->out.total || out->err.total)) membuf_reset (out); } /* Internal worker for output_dump and membuf_dump_most. */ static void membuf_dump (struct output *out) { if (out->out.total || out->err.total) { int traced = 0; struct output_run *err_run; struct output_run *out_run; FILE *prevdst; /* Try to acquire the semaphore. If it fails, dump the output unsynchronized; still better than silently discarding it. We want to keep this lock for as little time as possible. */ void *sem = acquire_semaphore (); # if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS) int prev_mode_out = _setmode (fileno (stdout), _O_BINARY); int prev_mode_err = _setmode (fileno (stderr), _O_BINARY); # endif # ifndef KMK /* this drives me bananas. */ /* Log the working directory for this dump. */ if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE) traced = log_working_directory (1); # endif /* Work the out and err sequences in parallel. */ out_run = out->out.head_run; err_run = out->err.head_run; prevdst = NULL; while (err_run || out_run) { FILE *dst; const void *src; size_t len; if (out_run && (!err_run || out_run->seqno <= err_run->seqno)) { src = out_run + 1; len = out_run->len; dst = stdout; out_run = out_run->next; } else { src = err_run + 1; len = err_run->len; dst = stderr; err_run = err_run->next; } if (dst != prevdst) fflush (prevdst); prevdst = dst; #ifdef KMK if (output_metered < 0) { /* likely */ } else meter_output_block (src, len); #endif # if 0 /* for debugging */ while (len > 0) { const char *nl = (const char *)memchr (src, '\n', len); size_t line_len = nl ? nl - (const char *)src + 1 : len; char *tmp = (char *)xmalloc (1 + line_len + 1 + 1); tmp[0] = '{'; memcpy (&tmp[1], src, line_len); tmp[1 + line_len] = '}'; # ifdef KBUILD_OS_WINDOWS maybe_con_fwrite (tmp, 1 + line_len + 1, 1, dst); # else fwrite (tmp, 1 + line_len + 1, 1, dst); # endif free (tmp); src = (const char *)src + line_len; len -= line_len; } #else # ifdef KBUILD_OS_WINDOWS maybe_con_fwrite (src, len, 1, dst); # else fwrite (src, len, 1, dst); # endif # endif } if (prevdst) fflush (prevdst); # ifndef KMK /* this drives me bananas. */ if (traced) log_working_directory (0); # endif /* Exit the critical section. */ # if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS) if (prev_mode_out != -1) _setmode (fileno (stdout), prev_mode_out); if (prev_mode_err != -1) _setmode (fileno (stderr), prev_mode_err); # endif if (sem) release_semaphore (sem); # ifdef KMK if (!out->dont_truncate) { /* likely */ } else return; # endif /* Free the segments and reset the state. */ membuf_reset (out); } else assert (out->out.head_seg == NULL && out->err.head_seg == NULL); } /* Writes up to LEN bytes to the given segment. Returns how much was actually written. */ static size_t membuf_write_segment (struct output_membuf *membuf, struct output_segment *seg, const char *src, size_t len, unsigned int *pseqno) { size_t written = 0; if (seg && membuf->left > 0) { struct output_run *run = membuf->tail_run; char *dst = (char *)(run + 1) + run->len; assert ((uintptr_t)run - (uintptr_t)seg < seg->size); /* If the sequence number didn't change, then we can append to the current run without further considerations. */ if (run->seqno == *pseqno) written = len; /* If the current run does not end with a newline, don't start a new run till we encounter one. */ else if (dst[-1] != '\n') { char const *srcnl = (const char *)memchr (src, '\n', len); written = srcnl ? srcnl - src + 1 : len; } /* Try create a new empty run and append to it. */ else { size_t const offnextrun = ( (uintptr_t)dst - (uintptr_t)(seg) + sizeof(void *) - 1) & ~(sizeof(void *) - 1); if (offnextrun > seg->size - sizeof (struct output_run) * 2) return 0; /* need new segment */ run = run->next = (struct output_run *)((char *)seg + offnextrun); run->next = NULL; run->seqno = ++(*pseqno); run->len = 0; membuf->tail_run = run; membuf->left = seg->size - (offnextrun + sizeof (*run)); dst = (char *)(run + 1); written = len; } /* Append to the current run. */ if (written > membuf->left) written = membuf->left; memcpy (dst, src, written); run->len += written; membuf->left -= written; } return written; } /* Helper for membuf_write_new_segment and membuf_dump_most that figures out now much data needs to be moved from the previous run in order to make it end with a newline. */ static size_t membuf_calc_move_len (struct output_run *tail_run) { size_t to_move = 0; if (tail_run) { const char *data = (const char *)(tail_run + 1); size_t off = tail_run->len; while (off > 0 && data[off - 1] != '\n') off--; to_move = tail_run->len - off; if (to_move >= MEMBUF_MAX_MOVE_LEN) to_move = 0; } return to_move; } /* Allocates a new segment and writes to it. This will take care to make sure the previous run terminates with a newline so that we pass whole lines to fwrite when dumping. */ static size_t membuf_write_new_segment (struct output_membuf *membuf, const char *src, size_t len, unsigned int *pseqno) { struct output_run *prev_run = membuf->tail_run; struct output_segment *prev_seg = membuf->tail_seg; size_t const to_move = membuf_calc_move_len (prev_run); struct output_segment *new_seg; size_t written; char *dst; /* Figure the the segment size. We start with MEMBUF_MIN_SEG_SIZE and double it each time till we reach MEMBUF_MAX_SEG_SIZE. */ size_t const offset_runs = offsetof (struct output_segment, runs); size_t segsize = !prev_seg ? MEMBUF_MIN_SEG_SIZE : prev_seg->size >= MEMBUF_MAX_SEG_SIZE ? MEMBUF_MAX_SEG_SIZE : prev_seg->size * 2; while ( segsize < to_move + len + offset_runs + sizeof (struct output_run) * 2 && segsize < MEMBUF_MAX_SEG_SIZE) segsize *= 2; /* Allocate the segment and link it and the first run. */ new_seg = (struct output_segment *)xmalloc (segsize); new_seg->size = segsize; new_seg->next = NULL; new_seg->runs[0].next = NULL; if (!prev_seg) { membuf->head_seg = new_seg; membuf->head_run = &new_seg->runs[0]; } else { prev_seg->next = new_seg; prev_run->next = &new_seg->runs[0]; } membuf->tail_seg = new_seg; membuf->tail_run = &new_seg->runs[0]; membuf->total += segsize; membuf->left = segsize - sizeof (struct output_run) - offset_runs; /* Initialize and write data to the first run. */ dst = (char *)&new_seg->runs[0]; /* Try bypass gcc array size cleverness. */ dst += sizeof (struct output_run); assert (MEMBUF_MAX_MOVE_LEN < MEMBUF_MIN_SEG_SIZE); if (to_move > 0) { /* Move to_move bytes from the previous run in hope that we'll get a newline to soon. Afterwards call membuf_segment_write to work SRC. */ assert (prev_run != NULL); assert (membuf->left >= to_move); prev_run->len -= to_move; new_seg->runs[0].len = to_move; new_seg->runs[0].seqno = prev_run->seqno; memcpy (dst, (const char *)(prev_run + 1) + prev_run->len, to_move); membuf->left -= to_move; written = membuf_write_segment (membuf, new_seg, src, len, pseqno); } else { /* Create a run with up to LEN from SRC. */ written = len; if (written > membuf->left) written = membuf->left; new_seg->runs[0].len = written; new_seg->runs[0].seqno = ++(*pseqno); memcpy (dst, src, written); membuf->left -= written; } return written; } /* Worker for output_write that will dump most of the output when we hit MEMBUF_MAX_TOTAL on either of the two membuf structures, then free all the output segments. Incomplete lines will be held over to the next buffers and copied into new segments. */ static void membuf_dump_most (struct output *out) { size_t out_to_move = membuf_calc_move_len (out->out.tail_run); size_t err_to_move = membuf_calc_move_len (out->err.tail_run); if (!out_to_move && !err_to_move) membuf_dump (out); else { /* Allocate a stack buffer for holding incomplete lines. This should be fine since we're only talking about max 2 * MEMBUF_MAX_MOVE_LEN. The -1 on the sequence numbers, ise because membuf_write_new_segment will increment them before use. */ unsigned int out_seqno = out_to_move ? out->out.tail_run->seqno - 1 : 0; unsigned int err_seqno = err_to_move ? out->err.tail_run->seqno - 1 : 0; char *tmp = alloca (out_to_move + err_to_move); if (out_to_move) { out->out.tail_run->len -= out_to_move; memcpy (tmp, (char *)(out->out.tail_run + 1) + out->out.tail_run->len, out_to_move); } if (err_to_move) { out->err.tail_run->len -= err_to_move; memcpy (tmp + out_to_move, (char *)(out->err.tail_run + 1) + out->err.tail_run->len, err_to_move); } membuf_dump (out); if (out_to_move) { size_t written = membuf_write_new_segment (&out->out, tmp, out_to_move, &out_seqno); assert (written == out_to_move); (void)written; } if (err_to_move) { size_t written = membuf_write_new_segment (&out->err, tmp + out_to_move, err_to_move, &err_seqno); assert (written == err_to_move); (void)written; } } } /* write/fwrite like function, binary mode. */ ssize_t output_write_bin (struct output *out, int is_err, const char *src, size_t len) { size_t ret = len; if (!out || !out->syncout) { FILE *f = is_err ? stderr : stdout; # if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS) /* On DOS platforms we need to disable \n -> \r\n converts that is common on standard output/error. Also optimize for console output. */ int saved_errno; int fd = fileno (f); int prev_mode = _setmode (fd, _O_BINARY); maybe_con_fwrite (src, len, 1, f); if (fflush (f) == EOF) ret = -1; saved_errno = errno; _setmode (fd, prev_mode); errno = saved_errno; # else fwrite (src, len, 1, f); if (fflush (f) == EOF) ret = -1; # endif } else { struct output_membuf *membuf = is_err ? &out->err : &out->out; while (len > 0) { size_t runlen = membuf_write_segment (membuf, membuf->tail_seg, src, len, &out->seqno); if (!runlen) { if (membuf->total < MEMBUF_MAX_TOTAL) runlen = membuf_write_new_segment (membuf, src, len, &out->seqno); else membuf_dump_most (out); } /* advance */ len -= runlen; src += runlen; } } return ret; } #endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */ /* write/fwrite like function, text mode. */ ssize_t output_write_text (struct output *out, int is_err, const char *src, size_t len) { #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY # if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS) ssize_t ret = len; if (!out || !out->syncout) { /* ASSUME fwrite does the desired conversion. */ FILE *f = is_err ? stderr : stdout; # ifdef KBUILD_OS_WINDOWS if (maybe_con_fwrite (src, len, 1, f) < 0) ret = -1; # else fwrite (src, len, 1, f); # endif if (fflush (f) == EOF) ret = -1; } else { /* Work the buffer line by line, replacing each \n with \r\n. */ while (len > 0) { const char *nl = memchr (src, '\n', len); size_t line_len = nl ? nl - src : len; output_write_bin (out, is_err, src, line_len); if (!nl) break; output_write_bin (out, is_err, "\r\n", 2); len -= line_len + 1; src += line_len + 1; } } return ret; # else return output_write_bin (out, is_err, src, len); # endif #else ssize_t ret = len; if (! out || ! out->syncout) { FILE *f = is_err ? stderr : stdout; # ifdef KBUILD_OS_WINDOWS maybe_con_fwrite(src, len, 1, f); # else fwrite (src, len, 1, f); # endif fflush (f); } else { int fd = is_err ? out->err : out->out; int r; EINTRLOOP (r, lseek (fd, 0, SEEK_END)); while (1) { EINTRLOOP (r, write (fd, src, len)); if ((size_t)r == len || r <= 0) break; len -= r; src += r; } } return ret; #endif } /* Write a string to the current STDOUT or STDERR. */ static void _outputs (struct output *out, int is_err, const char *msg) { #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY output_write_text (out, is_err, msg, strlen (msg)); #else /* !CONFIG_WITH_OUTPUT_IN_MEMORY */ if (! out || ! out->syncout) { FILE *f = is_err ? stderr : stdout; # ifdef KBUILD_OS_WINDOWS maybe_con_fwrite(msg, strlen(msg), 1, f); # else fputs (msg, f); # endif fflush (f); } else { int fd = is_err ? out->err : out->out; int len = strlen (msg); int r; EINTRLOOP (r, lseek (fd, 0, SEEK_END)); while (1) { EINTRLOOP (r, write (fd, msg, len)); if (r == len || r <= 0) break; len -= r; msg += r; } } #endif /* !CONFIG_WITH_OUTPUT_IN_MEMORY */ } /* Write a message indicating that we've just entered or left (according to ENTERING) the current directory. */ static int log_working_directory (int entering) { static char *buf = NULL; static unsigned int len = 0; unsigned int need; const char *fmt; char *p; /* Get enough space for the longest possible output. */ need = strlen (program) + INTSTR_LENGTH + 2 + 1; if (starting_directory) need += strlen (starting_directory); /* Use entire sentences to give the translators a fighting chance. */ if (makelevel == 0) if (starting_directory == 0) if (entering) fmt = _("%s: Entering an unknown directory\n"); else fmt = _("%s: Leaving an unknown directory\n"); else if (entering) fmt = _("%s: Entering directory '%s'\n"); else fmt = _("%s: Leaving directory '%s'\n"); else if (starting_directory == 0) if (entering) fmt = _("%s[%u]: Entering an unknown directory\n"); else fmt = _("%s[%u]: Leaving an unknown directory\n"); else if (entering) fmt = _("%s[%u]: Entering directory '%s'\n"); else fmt = _("%s[%u]: Leaving directory '%s'\n"); need += strlen (fmt); if (need > len) { buf = xrealloc (buf, need); len = need; } p = buf; if (print_data_base_flag) { *(p++) = '#'; *(p++) = ' '; } if (makelevel == 0) if (starting_directory == 0) sprintf (p, fmt , program); else sprintf (p, fmt, program, starting_directory); else if (starting_directory == 0) sprintf (p, fmt, program, makelevel); else sprintf (p, fmt, program, makelevel, starting_directory); _outputs (NULL, 0, buf); return 1; } /* Set a file descriptor to be in O_APPEND mode. If it fails, just ignore it. */ static void set_append_mode (int fd) { #if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND) int flags = fcntl (fd, F_GETFL, 0); if (flags >= 0) fcntl (fd, F_SETFL, flags | O_APPEND); #endif } #ifndef NO_OUTPUT_SYNC /* Semaphore for use in -j mode with output_sync. */ static sync_handle_t sync_handle = -1; #define FD_NOT_EMPTY(_f) ((_f) != OUTPUT_NONE && lseek ((_f), 0, SEEK_END) > 0) /* Set up the sync handle. Disables output_sync on error. */ static int sync_init (void) { int combined_output = 0; #ifdef WINDOWS32 # ifdef CONFIG_NEW_WIN_CHILDREN if (STREAM_OK (stdout)) { if (STREAM_OK (stderr)) { char mtxname[256]; sync_handle = create_mutex (mtxname, sizeof (mtxname)); if (sync_handle != -1) { prepare_mutex_handle_string (mtxname); return same_stream (stdout, stderr); } perror_with_name ("output-sync suppressed: ", "create_mutex"); } else perror_with_name ("output-sync suppressed: ", "stderr"); } else perror_with_name ("output-sync suppressed: ", "stdout"); output_sync = OUTPUT_SYNC_NONE; # else /* !CONFIG_NEW_WIN_CHILDREN */ if ((!STREAM_OK (stdout) && !STREAM_OK (stderr)) || (sync_handle = create_mutex ()) == -1) { perror_with_name ("output-sync suppressed: ", "stderr"); output_sync = 0; } else { combined_output = same_stream (stdout, stderr); prepare_mutex_handle_string (sync_handle); } # endif /* !CONFIG_NEW_WIN_CHILDREN */ #else if (STREAM_OK (stdout)) { struct stat stbuf_o, stbuf_e; sync_handle = fileno (stdout); combined_output = (fstat (fileno (stdout), &stbuf_o) == 0 && fstat (fileno (stderr), &stbuf_e) == 0 && stbuf_o.st_dev == stbuf_e.st_dev && stbuf_o.st_ino == stbuf_e.st_ino); } else if (STREAM_OK (stderr)) sync_handle = fileno (stderr); else { perror_with_name ("output-sync suppressed: ", "stderr"); output_sync = 0; } #endif return combined_output; } #ifndef CONFIG_WITH_OUTPUT_IN_MEMORY /* Support routine for output_sync() */ static void pump_from_tmp (int from, FILE *to) { # ifdef KMK char buffer[8192]; # else static char buffer[8192]; #endif # if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS) int prev_mode; /* "from" is opened by open_tmpfd, which does it in binary mode, so we need the mode of "to" to match that. */ prev_mode = _setmode (fileno (to), O_BINARY); #endif if (lseek (from, 0, SEEK_SET) == -1) perror ("lseek()"); while (1) { int len; EINTRLOOP (len, read (from, buffer, sizeof (buffer))); if (len < 0) perror ("read()"); if (len <= 0) break; #ifdef KMK if (output_metered < 0) { /* likely */ } else meter_output_block (buffer, len); #endif if (fwrite (buffer, len, 1, to) < 1) { perror ("fwrite()"); break; } fflush (to); } # if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS) /* Switch "to" back to its original mode, so that log messages by Make have the same EOL format as without --output-sync. */ _setmode (fileno (to), prev_mode); #endif } #endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */ /* Obtain the lock for writing output. */ static void * acquire_semaphore (void) { static struct flock fl; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 1; if (fcntl (sync_handle, F_SETLKW, &fl) != -1) return &fl; #ifdef KBUILD_OS_DARWIN /* F_SETLKW isn't supported on pipes */ if (errno != EBADF) #endif perror ("fcntl()"); return NULL; } /* Release the lock for writing output. */ static void release_semaphore (void *sem) { struct flock *flp = (struct flock *)sem; flp->l_type = F_UNLCK; if (fcntl (sync_handle, F_SETLKW, flp) == -1) perror ("fcntl()"); } #ifndef CONFIG_WITH_OUTPUT_IN_MEMORY /* Returns a file descriptor to a temporary file. The file is automatically closed/deleted on exit. Don't use a FILE* stream. */ int output_tmpfd (void) { int fd = -1; FILE *tfile = tmpfile (); if (! tfile) { #ifdef KMK if (output_context && output_context->syncout) output_context->syncout = 0; /* Avoid inifinit recursion. */ #endif pfatal_with_name ("tmpfile"); } /* Create a duplicate so we can close the stream. */ fd = dup (fileno (tfile)); if (fd < 0) { #ifdef KMK if (output_context && output_context->syncout) output_context->syncout = 0; /* Avoid inifinit recursion. */ #endif pfatal_with_name ("dup"); } fclose (tfile); set_append_mode (fd); return fd; } /* Adds file descriptors to the child structure to support output_sync; one for stdout and one for stderr as long as they are open. If stdout and stderr share a device they can share a temp file too. Will reset output_sync on error. */ static void setup_tmpfile (struct output *out) { /* Is make's stdout going to the same place as stderr? */ static int combined_output = -1; if (combined_output < 0) { #ifdef KMK /* prevent infinite recursion if sync_init() calls perror_with_name. */ combined_output = 0; #endif combined_output = sync_init (); } if (STREAM_OK (stdout)) { int fd = output_tmpfd (); if (fd < 0) goto error; CLOSE_ON_EXEC (fd); out->out = fd; } if (STREAM_OK (stderr)) { if (out->out != OUTPUT_NONE && combined_output) out->err = out->out; else { int fd = output_tmpfd (); if (fd < 0) goto error; CLOSE_ON_EXEC (fd); out->err = fd; } } return; /* If we failed to create a temp file, disable output sync going forward. */ error: output_close (out); output_sync = OUTPUT_SYNC_NONE; } #endif /* !CONFIG_WITH_OUTPUT_IN_MEMORY */ /* Synchronize the output of jobs in -j mode to keep the results of each job together. This is done by holding the results in temp files, one for stdout and potentially another for stderr, and only releasing them to "real" stdout/stderr when a semaphore can be obtained. */ void output_dump (struct output *out) { #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY membuf_dump (out); #else int outfd_not_empty = FD_NOT_EMPTY (out->out); int errfd_not_empty = FD_NOT_EMPTY (out->err); if (outfd_not_empty || errfd_not_empty) { # ifndef KMK /* this drives me bananas. */ int traced = 0; # endif /* Try to acquire the semaphore. If it fails, dump the output unsynchronized; still better than silently discarding it. We want to keep this lock for as little time as possible. */ void *sem = acquire_semaphore (); # ifndef KMK /* this drives me bananas. */ /* Log the working directory for this dump. */ if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE) traced = log_working_directory (1); # endif if (outfd_not_empty) pump_from_tmp (out->out, stdout); if (errfd_not_empty && out->err != out->out) pump_from_tmp (out->err, stderr); # ifndef KMK /* this drives me bananas. */ if (traced) log_working_directory (0); # endif /* Exit the critical section. */ if (sem) release_semaphore (sem); # ifdef KMK if (!out->dont_truncate) { /* likely */ } else return; # endif /* Truncate and reset the output, in case we use it again. */ if (out->out != OUTPUT_NONE) { int e; lseek (out->out, 0, SEEK_SET); EINTRLOOP (e, ftruncate (out->out, 0)); } if (out->err != OUTPUT_NONE && out->err != out->out) { int e; lseek (out->err, 0, SEEK_SET); EINTRLOOP (e, ftruncate (out->err, 0)); } } #endif } # if defined(KMK) && !defined(CONFIG_WITH_OUTPUT_IN_MEMORY) /* Used by die_with_job_output to suppress output when it shouldn't be repeated. */ void output_reset (struct output *out) { if (out) { if (out->out != OUTPUT_NONE) { int e; lseek (out->out, 0, SEEK_SET); EINTRLOOP (e, ftruncate (out->out, 0)); } if (out->err != OUTPUT_NONE && out->err != out->out) { int e; lseek (out->err, 0, SEEK_SET); EINTRLOOP (e, ftruncate (out->err, 0)); } } } # endif #endif /* NO_OUTPUT_SYNC */ /* Provide support for temporary files. */ #ifndef HAVE_STDLIB_H # ifdef HAVE_MKSTEMP int mkstemp (char *template); # else char *mktemp (char *template); # endif #endif FILE * output_tmpfile (char **name, const char *template) { #ifdef HAVE_FDOPEN int fd; #endif #if defined HAVE_MKSTEMP || defined HAVE_MKTEMP # define TEMPLATE_LEN strlen (template) #else # define TEMPLATE_LEN L_tmpnam #endif *name = xmalloc (TEMPLATE_LEN + 1); strcpy (*name, template); #if defined HAVE_MKSTEMP && defined HAVE_FDOPEN /* It's safest to use mkstemp(), if we can. */ fd = mkstemp (*name); if (fd == -1) return 0; return fdopen (fd, "w"); #else # ifdef HAVE_MKTEMP (void) mktemp (*name); # else (void) tmpnam (*name); # endif # ifdef HAVE_FDOPEN /* Can't use mkstemp(), but guard against a race condition. */ EINTRLOOP (fd, open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600)); if (fd == -1) return 0; return fdopen (fd, "w"); # else /* Not secure, but what can we do? */ return fopen (*name, "w"); # endif #endif } /* This code is stolen from gnulib. If/when we abandon the requirement to work with K&R compilers, we can remove this (and perhaps other parts of GNU make!) and migrate to using gnulib directly. This is called only through atexit(), which means die() has already been invoked. So, call exit() here directly. Apparently that works...? */ /* Close standard output, exiting with status 'exit_failure' on failure. If a program writes *anything* to stdout, that program should close stdout and make sure that it succeeds before exiting. Otherwise, suppose that you go to the extreme of checking the return status of every function that does an explicit write to stdout. The last printf can succeed in writing to the internal stream buffer, and yet the fclose(stdout) could still fail (due e.g., to a disk full error) when it tries to write out that buffered data. Thus, you would be left with an incomplete output file and the offending program would exit successfully. Even calling fflush is not always sufficient, since some file systems (NFS and CODA) buffer written/flushed data until an actual close call. Besides, it's wasteful to check the return value from every call that writes to stdout -- just let the internal stream state record the failure. That's what the ferror test is checking below. It's important to detect such failures and exit nonzero because many tools (most notably 'make' and other build-management systems) depend on being able to detect failure in other tools via their exit status. */ static void close_stdout (void) { int prev_fail = ferror (stdout); #ifdef DEBUG_STDOUT_CLOSE_ISSUE if (prev_fail) my_stdout_error ("close_stdout", "error pending on entry!"); errno = 0; SetLastError (0); #endif int fclose_fail = fclose (stdout); if (prev_fail || fclose_fail) { #ifdef DEBUG_STDOUT_CLOSE_ISSUE if (fclose_fail) my_stdout_error ("close_stdout", "fclose failed!"); #endif if (fclose_fail) perror_with_name (_("write error: stdout"), ""); else O (error, NILF, _("write error: stdout")); exit (MAKE_TROUBLE); } #if defined(KBUILD_OS_WINDOWS) && defined(KMK) win_pipe_hack_terminate (); #endif } void output_init (struct output *out) { #if defined(KBUILD_OS_WINDOWS) && defined(KMK) /* Apply workaround for asynchronous pipes on windows on first call. */ static int s_not_first_call = 0; if (!s_not_first_call) { s_not_first_call = 1; win_pipe_hack_init (); } #endif #ifdef DEBUG_STDOUT_CLOSE_ISSUE if (STREAM_OK (stdout) && ferror (stdout)) my_stdout_error (out ? "output_init(out)" : "output_init(NULL)", "error pending entry!"); #endif if (out) { #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY out->out.head_seg = NULL; out->out.tail_seg = NULL; out->out.head_run = NULL; out->out.tail_run = NULL; out->err.head_seg = NULL; out->err.tail_seg = NULL; out->err.head_run = NULL; out->err.tail_run = NULL; out->err.total = 0; out->out.total = 0; out->seqno = 0; #else out->out = out->err = OUTPUT_NONE; #endif out->syncout = !!output_sync; #ifdef KMK out->dont_truncate = 0; #endif return; } /* Configure this instance of make. Be sure stdout is line-buffered. */ #ifdef HAVE_SETVBUF # ifdef SETVBUF_REVERSED setvbuf (stdout, _IOLBF, xmalloc (BUFSIZ), BUFSIZ); # else /* setvbuf not reversed. */ /* Some buggy systems lose if we pass 0 instead of allocating ourselves. */ setvbuf (stdout, 0, _IOLBF, BUFSIZ); # endif /* setvbuf reversed. */ #elif HAVE_SETLINEBUF setlinebuf (stdout); #endif /* setlinebuf missing. */ /* Force stdout/stderr into append mode. This ensures parallel jobs won't lose output due to overlapping writes. */ set_append_mode (fileno (stdout)); set_append_mode (fileno (stderr)); #ifdef DEBUG_STDOUT_CLOSE_ISSUE if (ferror (stdout)) my_stdout_error ("output_init", "error pending on exit!"); # ifdef KBUILD_OS_WINDOWS { HANDLE const hStdOut = (HANDLE)_get_osfhandle(_fileno(stdout)); DWORD const dwType = GetFileType(hStdOut); birdResolveImportsWorker(); if ((dwType & ~FILE_TYPE_REMOTE) == FILE_TYPE_PIPE) { my_output_pipe_info (hStdOut, "output_init"); # if 0 DWORD cbOutBuf = 0; DWORD cbInBuf = 0; BOOL const fRc2 = GetNamedPipeInfo(hStdOut, NULL, &cbOutBuf, &cbInBuf, NULL); if (cbInBuf != 0x1000) { DWORD dwMode = 0; if (GetNamedPipeHandleStateW(hStdOut, &dwMode, NULL, NULL, NULL, NULL, 0)) { dwMode &= ~PIPE_WAIT; dwMode |= PIPE_NOWAIT; if (!SetNamedPipeHandleState(hStdOut, &dwMode, NULL, NULL)) fprintf(stderr, "SetNamedPipeHandleState failed: %u\n", GetLastError()); else { GetNamedPipeHandleStateW(hStdOut, &dwMode, NULL, NULL, NULL, NULL, 0); fprintf(stderr, "SetNamedPipeHandleState succeeded: %#x\n", dwMode); } } } # endif # endif } } #endif #ifdef HAVE_ATEXIT if (STREAM_OK (stdout)) atexit (close_stdout); #endif } void output_close (struct output *out) { if (! out) { if (stdio_traced) log_working_directory (0); return; } #ifndef NO_OUTPUT_SYNC output_dump (out); #endif #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY assert (out->out.total == 0); assert (out->out.head_seg == NULL); assert (out->err.total == 0); assert (out->err.head_seg == NULL); #else if (out->out >= 0) close (out->out); if (out->err >= 0 && out->err != out->out) close (out->err); #endif output_init (out); } /* We're about to generate output: be sure it's set up. */ void output_start (void) { #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY /* If we're syncing output make sure the sempahore (win) is set up. */ if (output_context && output_context->syncout) if (combined_output < 0) { combined_output = 0; combined_output = sync_init (); } #else #ifndef NO_OUTPUT_SYNC /* If we're syncing output make sure the temporary file is set up. */ if (output_context && output_context->syncout) if (! OUTPUT_ISSET(output_context)) setup_tmpfile (output_context); #endif #endif #ifndef KMK /* If we're not syncing this output per-line or per-target, make sure we emit the "Entering..." message where appropriate. */ if (output_sync == OUTPUT_SYNC_NONE || output_sync == OUTPUT_SYNC_RECURSE) #else /* Indiscriminately output "Entering..." and "Leaving..." message for each command line or target is plain annoying! And when there is no recursion it's actually inappropriate. Haven't got a simple way of detecting that, so back to the old behavior for now. [bird] */ #endif if (! stdio_traced && print_directory_flag) stdio_traced = log_working_directory (1); } void outputs (int is_err, const char *msg) { if (! msg || *msg == '\0') return; output_start (); _outputs (output_context, is_err, msg); } static struct fmtstring { char *buffer; size_t size; } fmtbuf = { NULL, 0 }; static char * get_buffer (size_t need) { /* Make sure we have room. NEED includes space for \0. */ if (need > fmtbuf.size) { fmtbuf.size += need * 2; fmtbuf.buffer = xrealloc (fmtbuf.buffer, fmtbuf.size); } fmtbuf.buffer[need-1] = '\0'; return fmtbuf.buffer; } /* Print a message on stdout. */ void message (int prefix, size_t len, const char *fmt, ...) { va_list args; char *p; len += strlen (fmt) + strlen (program) + INTSTR_LENGTH + 4 + 1 + 1; p = get_buffer (len); if (prefix) { if (makelevel == 0) sprintf (p, "%s: ", program); else sprintf (p, "%s[%u]: ", program, makelevel); p += strlen (p); } va_start (args, fmt); vsprintf (p, fmt, args); va_end (args); strcat (p, "\n"); assert (fmtbuf.buffer[len-1] == '\0'); outputs (0, fmtbuf.buffer); } /* Print an error message. */ void error (const floc *flocp, size_t len, const char *fmt, ...) { va_list args; char *p; len += (strlen (fmt) + strlen (program) + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0) + INTSTR_LENGTH + 4 + 1 + 1); p = get_buffer (len); if (flocp && flocp->filenm) sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset); else if (makelevel == 0) sprintf (p, "%s: ", program); else sprintf (p, "%s[%u]: ", program, makelevel); p += strlen (p); va_start (args, fmt); vsprintf (p, fmt, args); va_end (args); strcat (p, "\n"); assert (fmtbuf.buffer[len-1] == '\0'); outputs (1, fmtbuf.buffer); } /* Print an error message and exit. */ void fatal (const floc *flocp, size_t len, const char *fmt, ...) { va_list args; const char *stop = _(". Stop.\n"); char *p; len += (strlen (fmt) + strlen (program) + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0) + INTSTR_LENGTH + 8 + strlen (stop) + 1); p = get_buffer (len); if (flocp && flocp->filenm) sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno + flocp->offset); else if (makelevel == 0) sprintf (p, "%s: *** ", program); else sprintf (p, "%s[%u]: *** ", program, makelevel); p += strlen (p); va_start (args, fmt); vsprintf (p, fmt, args); va_end (args); strcat (p, stop); assert (fmtbuf.buffer[len-1] == '\0'); outputs (1, fmtbuf.buffer); die (MAKE_FAILURE); } /* Print an error message from errno. */ void perror_with_name (const char *str, const char *name) { const char *err = strerror (errno); OSSS (error, NILF, _("%s%s: %s"), str, name, err); } /* Print an error message from errno and exit. */ void pfatal_with_name (const char *name) { const char *err = strerror (errno); OSS (fatal, NILF, _("%s: %s"), name, err); /* NOTREACHED */ } kbuild-3686/src/kmk/vmsify.c0000664000175000017500000004430515053010076015751 0ustar locutuslocutus/* vmsify.c -- Module for vms <-> unix file name conversion Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ /* Written by Klaus Kämpf (kkaempf@progis.de) of proGIS Software, Aachen, Germany */ #include #include #include #include "makeint.h" #if VMS #include #include #include #include #include #include #include #include /* Initialize a string descriptor (struct dsc$descriptor_s) for an arbitrary string. ADDR is a pointer to the first character of the string, and LEN is the length of the string. */ #define INIT_DSC_S(dsc, addr, len) do { \ (dsc).dsc$b_dtype = DSC$K_DTYPE_T; \ (dsc).dsc$b_class = DSC$K_CLASS_S; \ (dsc).dsc$w_length = (len); \ (dsc).dsc$a_pointer = (addr); \ } while (0) /* Initialize a string descriptor (struct dsc$descriptor_s) for a NUL-terminated string. S is a pointer to the string; the length is determined by calling strlen(). */ #define INIT_DSC_CSTRING(dsc, s) INIT_DSC_S(dsc, s, strlen(s)) #endif /* copy 'from' to 'to' up to but not including 'upto' return 0 if eos on from return 1 if upto found return 'to' at last char + 1 return 'from' at match + 1 or eos if no match if as_dir == 1, change all '.' to '_' else change all '.' but the last to '_' */ static int copyto (char **to, const char **from, char upto, int as_dir) { const char *s; s = strrchr (*from, '.'); while (**from) { if (**from == upto) { do { (*from)++; } while (**from == upto); return 1; } if (**from == '.') { if ((as_dir == 1) || (*from != s)) **to = '_'; else **to = '.'; } else { #ifdef HAVE_CASE_INSENSITIVE_FS if (isupper ((unsigned char)**from)) **to = tolower ((unsigned char)**from); else #endif **to = **from; } (*to)++; (*from)++; } return 0; } /* get translation of logical name */ static char * trnlog (const char *name) { int stat; static char reslt[1024]; $DESCRIPTOR (reslt_dsc, reslt); short resltlen; struct dsc$descriptor_s name_dsc; char *s; /* * the string isn't changed, but there is no string descriptor with * "const char *dsc$a_pointer" */ INIT_DSC_CSTRING (name_dsc, (char *)name); stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc); if ((stat&1) == 0) { return ""; } if (stat == SS$_NOTRAN) { return ""; } reslt[resltlen] = '\0'; s = xmalloc (resltlen+1); strcpy (s, reslt); return s; } static char * showall (char *s) { static char t[512]; char *pt; pt = t; if (strchr (s, '\\') == 0) return s; while (*s) { if (*s == '\\') { *pt++ = *s; } *pt++ = *s++; } return pt; } enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE }; /* convert unix style name to vms style type = 0 -> name is a full name (directory and filename part) type = 1 -> name is a directory type = 2 -> name is a filename without directory The following conversions are applied (0) (1) (2) input full name dir name file name 1 ./ [] .dir 2 ../ .dir 3 // : :[000000] :000000.dir 4 //a a: a: a: 5 //a/ a: a: a:000000.dir 9 / [000000] [000000] 000000.dir 10 /a [000000]a [a] [000000]a 11 /a/ [a] [a] [000000]a.dir 12 /a/b [a]b [a.b] [a]b 13 /a/b/ [a.b] [a.b] [a]b.dir 14 /a/b/c [a.b]c [a.b.c] [a.b]c 15 /a/b/c/ [a.b.c] [a.b.c] [a.b]c.dir 16 a a [.a] a 17 a/ [.a] [.a] a.dir 18 a/b [.a]b [.a.b] [.a]b 19 a/b/ [.a.b] [.a.b] [.a]b.dir 20 a/b/c [.a.b]c [.a.b.c] [.a.b]c 21 a/b/c/ [.a.b.c] [.a.b.c] [.a.b]c.dir 22 a.b.c a_b.c [.a_b_c] a_b_c.dir 23 [x][y]z [x.y]z [x.y]z [x.y]z 24 [x][.y]z [x.y]z [x.y]z [x.y]z 25 filenames with '$' are left unchanged if they contain no '/' 25 filenames with ':' are left unchanged 26 filenames with a single pair of '[' ']' are left unchanged The input string is not written to. The result is also const because it's a static buffer; we don't want to change it. */ const char * vmsify (const char *name, int type) { /* max 255 device max 39 directory max 39 filename max 39 filetype max 5 version */ /* todo: VMSMAXPATHLEN is defined for ODS2 names: it needs to be adjusted. */ #define VMSMAXPATHLEN 512 enum namestate nstate; static char vmsname[VMSMAXPATHLEN+1]; const char *fptr; const char *t; char *vptr; int as_dir; int count; const char *s; const char *s1; const char *s2; if (name == 0) return 0; fptr = name; vptr = vmsname; nstate = N_START; /* case 25a */ t = strpbrk (name, "$:"); if (t != 0) { // const char *s1; // const char *s2; if (type == 1) { s1 = strchr (t+1, '['); s2 = strchr (t+1, ']'); } if (*t == '$') { if (strchr (name, '/') == 0) { strcpy (vmsname, name); if ((type == 1) && (s1 != 0) && (s2 == 0)) strcat (vmsname, "]"); return vmsname; } } else { strcpy (vmsname, name); if ((type == 1) && (s1 != 0) && (s2 == 0)) strcat (vmsname, "]"); return vmsname; } } /* case 26 */ t = strchr (name, '['); if (t != 0) { // const char *s; // const char *s1 = strchr (t+1, '['); s1 = strchr (t+1, '['); if (s1 == 0) { strcpy (vmsname, name); if ((type == 1) && (strchr (t+1, ']') == 0)) strcat (vmsname, "]"); return vmsname; } s1--; if (*s1 != ']') { strcpy (vmsname, name); return vmsname; /* not ][, keep unchanged */ } /* we have ][ */ s = name; /* s -> starting char s1 -> ending ']' */ do { strncpy (vptr, s, s1-s); /* copy up to but not including ']' */ vptr += s1-s; if (*s1 == 0) break; s = s1 + 1; /* s -> char behind ']' */ if (*s != '[') /* was '][' ? */ break; /* no, last ] found, exit */ s++; if (*s != '.') *vptr++ = '.'; s1 = strchr (s, ']'); if (s1 == 0) /* no closing ] */ s1 = s + strlen (s); } while (1); *vptr++ = ']'; fptr = s; } else /* no [ in name */ { int state = 0; int rooted = 1; /* flag if logical is rooted, else insert [000000] */ do { switch (state) { case 0: /* start of loop */ if (*fptr == '/') { fptr++; state = 1; } else if (*fptr == '.') { fptr++; state = 10; } else state = 2; break; case 1: /* '/' at start */ if (*fptr == '/') { fptr++; state = 3; } else state = 4; break; case 2: /* no '/' at start */ { const char *s = strchr (fptr, '/'); if (s == 0) /* no '/' (16) */ { if (type == 1) { strcpy (vptr, "[."); vptr += 2; } copyto (&vptr, &fptr, 0, (type==1)); if (type == 1) *vptr++ = ']'; state = -1; } else /* found '/' (17..21) */ { if ((type == 2) && (*(s+1) == 0)) /* 17(2) */ { copyto (&vptr, &fptr, '/', 1); state = 7; } else { strcpy (vptr, "[."); vptr += 2; copyto (&vptr, &fptr, '/', 1); nstate = N_OPEN; state = 9; } } break; } case 3: /* '//' at start */ { // const char *s; // const char *s1; char *vp; while (*fptr == '/') /* collapse all '/' */ fptr++; if (*fptr == 0) /* just // */ { char cwdbuf[VMSMAXPATHLEN+1]; s1 = getcwd(cwdbuf, VMSMAXPATHLEN); if (s1 == 0) { vmsname[0] = '\0'; return vmsname; /* FIXME, err getcwd */ } s = strchr (s1, ':'); if (s == 0) { vmsname[0] = '\0'; return vmsname; /* FIXME, err no device */ } strncpy (vptr, s1, s-s1+1); vptr += s-s1+1; state = -1; break; } s = vptr; if (copyto (&vptr, &fptr, '/', 1) == 0) /* copy device part */ { *vptr++ = ':'; state = -1; break; } *vptr = ':'; nstate = N_DEVICE; if (*fptr == 0) /* just '//a/' */ { strcpy (vptr+1, "[000000]"); vptr += 9; state = -1; break; } *vptr = 0; /* check logical for [000000] insertion */ vp = trnlog (s); if (*vp != '\0') { /* found translation */ for (;;) /* loop over all nested logicals */ { char *vp2 = vp + strlen (vp) - 1; if (*vp2 == ':') /* translation ends in ':' */ { vp2 = trnlog (vp); free (vp); if (*vp2 == 0) { rooted = 0; break; } vp = vp2; continue; /* next iteration */ } if (*vp2 == ']') /* translation ends in ']' */ { if (*(vp2-1) == '.') /* ends in '.]' */ { if (strncmp (fptr, "000000", 6) != 0) rooted = 0; } else { strcpy (vmsname, s1); vp = strchr (vmsname, ']'); *vp = '.'; nstate = N_DOT; vptr = vp; } } break; } free (vp); } else rooted = 0; if (*vptr == 0) { nstate = N_DEVICE; *vptr++ = ':'; } else vptr++; if (rooted == 0) { nstate = N_DOT; strcpy (vptr, "[000000."); vptr += 8; vp = vptr-1; } else vp = 0; /* vp-> '.' after 000000 or NULL */ s = strchr (fptr, '/'); if (s == 0) { /* no next '/' */ if (*(vptr-1) == '.') *(vptr-1) = ']'; else if (rooted == 0) *vptr++ = ']'; copyto (&vptr, &fptr, 0, (type == 1)); state = -1; break; } else { while (*(s+1) == '/') /* skip multiple '/' */ s++; } if ((rooted != 0) && (*(vptr-1) != '.')) { *vptr++ = '['; nstate = N_DOT; } else if ((nstate == N_DOT) && (vp != 0) && (*(s+1) == 0)) { if (type == 2) { *vp = ']'; nstate = N_CLOSED; } } state = 9; break; } case 4: /* single '/' at start (9..15) */ if (*fptr == 0) state = 5; else state = 6; break; case 5: /* just '/' at start (9) */ if (type != 2) { *vptr++ = '['; nstate = N_OPEN; } strcpy (vptr, "000000"); vptr += 6; if (type == 2) state = 7; else state = 8; break; case 6: /* chars following '/' at start 10..15 */ { const char *s; *vptr++ = '['; nstate = N_OPEN; s = strchr (fptr, '/'); if (s == 0) /* 10 */ { if (type != 1) { strcpy (vptr, "000000]"); vptr += 7; } copyto (&vptr, &fptr, 0, (type == 1)); if (type == 1) { *vptr++ = ']'; } state = -1; } else /* 11..15 */ { if ( (type == 2) && (*(s+1) == 0)) /* 11(2) */ { strcpy (vptr, "000000]"); nstate = N_CLOSED; vptr += 7; } copyto (&vptr, &fptr, '/', (*(vptr-1) != ']')); state = 9; } break; } case 7: /* add '.dir' and exit */ if ((nstate == N_OPEN) || (nstate == N_DOT)) { char *vp = vptr-1; while (vp > vmsname) { if (*vp == ']') { break; } if (*vp == '.') { *vp = ']'; break; } vp--; } } strcpy (vptr, ".dir"); vptr += 4; state = -1; break; case 8: /* add ']' and exit */ *vptr++ = ']'; state = -1; break; case 9: /* 17..21, fptr -> 1st '/' + 1 */ { const char *s; if (*fptr == 0) { if (type == 2) { state = 7; } else state = 8; break; } s = strchr (fptr, '/'); if (s == 0) { if (type != 1) { if (nstate == N_OPEN) { *vptr++ = ']'; nstate = N_CLOSED; } as_dir = 0; } else { if (nstate == N_OPEN) { *vptr++ = '.'; nstate = N_DOT; } as_dir = 1; } } else { while (*(s+1) == '/') s++; if ( (type == 2) && (*(s+1) == 0)) /* 19(2), 21(2)*/ { if (nstate != N_CLOSED) { *vptr++ = ']'; nstate = N_CLOSED; } as_dir = 1; } else { if (nstate == N_OPEN) { *vptr++ = '.'; nstate = N_DOT; } as_dir = 1; } } if ( (*fptr == '.') /* check for '..' or '../' */ && (*(fptr+1) == '.') && ((*(fptr+2) == '/') || (*(fptr+2) == 0)) ) { char *vp; fptr += 2; if (*fptr == '/') { do { fptr++; } while (*fptr == '/'); } else if (*fptr == 0) type = 1; vptr--; /* vptr -> '.' or ']' */ vp = vptr; for (;;) { vp--; if (*vp == '.') /* one back */ { vptr = vp; nstate = N_OPEN; break; } if (*vp == '[') /* top level reached */ { if (*fptr == 0) { strcpy (vp, "[000000]"); vptr = vp + 8; nstate = N_CLOSED; s = 0; break; } else { vptr = vp+1; nstate = N_OPEN; break; } } } } else { copyto (&vptr, &fptr, '/', as_dir); if (nstate == N_DOT) nstate = N_OPEN; } if (s == 0) { /* 18,20 */ if (type == 1) *vptr++ = ']'; state = -1; } else { if (*(s+1) == 0) { if (type == 2) /* 19,21 */ { state = 7; } else { *vptr++ = ']'; state = -1; } } } break; } case 10: /* 1,2 first is '.' */ if (*fptr == '.') { fptr++; state = 11; } else state = 12; break; case 11: /* 2, '..' at start */ count = 1; if (*fptr != 0) { if (*fptr != '/') /* got ..xxx */ { strcpy (vmsname, name); return vmsname; } do /* got ../ */ { fptr++; while (*fptr == '/') fptr++; if (*fptr != '.') break; if (*(fptr+1) != '.') break; fptr += 2; if ((*fptr == 0) || (*fptr == '/')) count++; } while (*fptr == '/'); } { /* got '..' or '../' */ char *vp; char cwdbuf[VMSMAXPATHLEN+1]; vp = getcwd(cwdbuf, VMSMAXPATHLEN); if (vp == 0) { vmsname[0] = '\0'; return vmsname; /* FIXME, err getcwd */ } strcpy (vptr, vp); vp = strchr (vptr, ']'); if (vp != 0) { nstate = N_OPEN; while (vp > vptr) { vp--; if (*vp == '[') { vp++; strcpy (vp, "000000]"); state = -1; break; } else if (*vp == '.') { if (--count == 0) { if (*fptr == 0) /* had '..' or '../' */ { *vp++ = ']'; state = -1; } else /* had '../xxx' */ { state = 9; } *vp = '\0'; break; } } } } vptr += strlen (vptr); } break; case 12: /* 1, '.' at start */ if (*fptr != 0) { if (*fptr != '/') { strcpy (vmsname, name); return vmsname; } while (*fptr == '/') fptr++; } { char *vp; char cwdbuf[VMSMAXPATHLEN+1]; vp = getcwd(cwdbuf, VMSMAXPATHLEN); if (vp == 0) { vmsname[0] = '\0'; return vmsname; /*FIXME, err getcwd */ } strcpy (vptr, vp); } if (*fptr == 0) { state = -1; break; } else { char *vp = strchr (vptr, ']'); if (vp == 0) { state = -1; break; } *vp = '\0'; nstate = N_OPEN; vptr += strlen (vptr); state = 9; } break; } } while (state > 0); } /* directory conversion done fptr -> filename part of input string vptr -> free space in vmsname */ *vptr++ = 0; return vmsname; } /* convert from vms-style to unix-style dev:[dir1.dir2] //dev/dir1/dir2/ */ const char * unixify (const char *name) { static char piece[512]; const char *s; char *p; if (strchr (name, '/') != 0) /* already in unix style */ { strcpy (piece, name); return piece; } p = piece; *p = 0; /* device part */ s = strchr (name, ':'); if (s != 0) { int l = s - name; *p++ = '/'; *p++ = '/'; strncpy (p, name, l); p += l; } /* directory part */ *p++ = '/'; s = strchr (name, '['); if (s != 0) { s++; switch (*s) { case ']': /* [] */ strcat (p, "./"); break; case '-': /* [- */ strcat (p, "../"); break; case '.': strcat (p, "./"); /* [. */ break; default: s--; break; } s++; while (*s) { if (*s == '.') *p++ = '/'; else *p++ = *s; s++; if (*s == ']') { s++; break; } } if (*s != 0) /* more after ']' ?? */ { if (*(p-1) != '/') *p++ = '/'; strcpy (p, s); /* copy it anyway */ } } else /* no '[' anywhere */ { *p++ = 0; } /* force end with '/' */ if (*(p-1) != '/') *p++ = '/'; *p = 0; return piece; } /* EOF */ kbuild-3686/src/kmk/version.c0000664000175000017500000000222115053010075016107 0ustar locutuslocutus/* Record version and build host architecture for GNU make. Copyright (C) 1988-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ /* We use instead of "config.h" so that a compilation using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h (which it would do because makeint.h was found in $srcdir). */ #include #ifndef MAKE_HOST # define MAKE_HOST "unknown" #endif const char *version_string = VERSION; const char *make_host = MAKE_HOST; /* Local variables: version-control: never End: */ kbuild-3686/src/kmk/signame.c0000664000175000017500000001531715053010075016057 0ustar locutuslocutus/* Convert between signal names and numbers. Copyright (C) 1990-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #include "makeint.h" /* If the system provides strsignal, we don't need it. */ #if !HAVE_STRSIGNAL /* If the system provides sys_siglist, we'll use that. Otherwise create our own. */ #if !HAVE_DECL_SYS_SIGLIST /* Some systems do not define NSIG in . */ #ifndef NSIG #ifdef _NSIG #define NSIG _NSIG #else #define NSIG 32 #endif #endif /* There is too much variation in Sys V signal numbers and names, so we must initialize them at runtime. */ static const char *undoc; static const char *sys_siglist[NSIG]; /* Table of abbreviations for signals. Note: A given number can appear more than once with different abbreviations. */ #define SIG_TABLE_SIZE (NSIG*2) typedef struct { int number; const char *abbrev; } num_abbrev; static num_abbrev sig_table[SIG_TABLE_SIZE]; /* Number of elements of sig_table used. */ static int sig_table_nelts = 0; /* Enter signal number NUMBER into the tables with ABBREV and NAME. */ static void init_sig (int number, const char *abbrev, const char *name) { /* If this value is ever greater than NSIG it seems like it'd be a bug in the system headers, but... better safe than sorry. We know, for example, that this isn't always true on VMS. */ if (number >= 0 && number < NSIG) sys_siglist[number] = name; if (sig_table_nelts < SIG_TABLE_SIZE) { sig_table[sig_table_nelts].number = number; sig_table[sig_table_nelts++].abbrev = abbrev; } } static int signame_init (void) { int i; undoc = xstrdup (_("unknown signal")); /* Initialize signal names. */ for (i = 0; i < NSIG; i++) sys_siglist[i] = undoc; /* Initialize signal names. */ #if defined (SIGHUP) init_sig (SIGHUP, "HUP", _("Hangup")); #endif #if defined (SIGINT) init_sig (SIGINT, "INT", _("Interrupt")); #endif #if defined (SIGQUIT) init_sig (SIGQUIT, "QUIT", _("Quit")); #endif #if defined (SIGILL) init_sig (SIGILL, "ILL", _("Illegal Instruction")); #endif #if defined (SIGTRAP) init_sig (SIGTRAP, "TRAP", _("Trace/breakpoint trap")); #endif /* If SIGIOT == SIGABRT, we want to print it as SIGABRT because SIGABRT is in ANSI and POSIX.1 and SIGIOT isn't. */ #if defined (SIGABRT) init_sig (SIGABRT, "ABRT", _("Aborted")); #endif #if defined (SIGIOT) init_sig (SIGIOT, "IOT", _("IOT trap")); #endif #if defined (SIGEMT) init_sig (SIGEMT, "EMT", _("EMT trap")); #endif #if defined (SIGFPE) init_sig (SIGFPE, "FPE", _("Floating point exception")); #endif #if defined (SIGKILL) init_sig (SIGKILL, "KILL", _("Killed")); #endif #if defined (SIGBUS) init_sig (SIGBUS, "BUS", _("Bus error")); #endif #if defined (SIGSEGV) init_sig (SIGSEGV, "SEGV", _("Segmentation fault")); #endif #if defined (SIGSYS) init_sig (SIGSYS, "SYS", _("Bad system call")); #endif #if defined (SIGPIPE) init_sig (SIGPIPE, "PIPE", _("Broken pipe")); #endif #if defined (SIGALRM) init_sig (SIGALRM, "ALRM", _("Alarm clock")); #endif #if defined (SIGTERM) init_sig (SIGTERM, "TERM", _("Terminated")); #endif #if defined (SIGUSR1) init_sig (SIGUSR1, "USR1", _("User defined signal 1")); #endif #if defined (SIGUSR2) init_sig (SIGUSR2, "USR2", _("User defined signal 2")); #endif /* If SIGCLD == SIGCHLD, we want to print it as SIGCHLD because that is what is in POSIX.1. */ #if defined (SIGCHLD) init_sig (SIGCHLD, "CHLD", _("Child exited")); #endif #if defined (SIGCLD) init_sig (SIGCLD, "CLD", _("Child exited")); #endif #if defined (SIGPWR) init_sig (SIGPWR, "PWR", _("Power failure")); #endif #if defined (SIGTSTP) init_sig (SIGTSTP, "TSTP", _("Stopped")); #endif #if defined (SIGTTIN) init_sig (SIGTTIN, "TTIN", _("Stopped (tty input)")); #endif #if defined (SIGTTOU) init_sig (SIGTTOU, "TTOU", _("Stopped (tty output)")); #endif #if defined (SIGSTOP) init_sig (SIGSTOP, "STOP", _("Stopped (signal)")); #endif #if defined (SIGXCPU) init_sig (SIGXCPU, "XCPU", _("CPU time limit exceeded")); #endif #if defined (SIGXFSZ) init_sig (SIGXFSZ, "XFSZ", _("File size limit exceeded")); #endif #if defined (SIGVTALRM) init_sig (SIGVTALRM, "VTALRM", _("Virtual timer expired")); #endif #if defined (SIGPROF) init_sig (SIGPROF, "PROF", _("Profiling timer expired")); #endif #if defined (SIGWINCH) /* "Window size changed" might be more accurate, but even if that is all that it means now, perhaps in the future it will be extended to cover other kinds of window changes. */ init_sig (SIGWINCH, "WINCH", _("Window changed")); #endif #if defined (SIGCONT) init_sig (SIGCONT, "CONT", _("Continued")); #endif #if defined (SIGURG) init_sig (SIGURG, "URG", _("Urgent I/O condition")); #endif #if defined (SIGIO) /* "I/O pending" has also been suggested. A disadvantage is that signal only happens when the process has asked for it, not every time I/O is pending. Another disadvantage is the confusion from giving it a different name than under Unix. */ init_sig (SIGIO, "IO", _("I/O possible")); #endif #if defined (SIGWIND) init_sig (SIGWIND, "WIND", _("SIGWIND")); #endif #if defined (SIGPHONE) init_sig (SIGPHONE, "PHONE", _("SIGPHONE")); #endif #if defined (SIGPOLL) init_sig (SIGPOLL, "POLL", _("I/O possible")); #endif #if defined (SIGLOST) init_sig (SIGLOST, "LOST", _("Resource lost")); #endif #if defined (SIGDANGER) init_sig (SIGDANGER, "DANGER", _("Danger signal")); #endif #if defined (SIGINFO) init_sig (SIGINFO, "INFO", _("Information request")); #endif #if defined (SIGNOFP) init_sig (SIGNOFP, "NOFP", _("Floating point co-processor not available")); #endif return 1; } #endif /* HAVE_DECL_SYS_SIGLIST */ char * strsignal (int sig) { static char buf[] = "Signal 12345678901234567890"; #if ! HAVE_DECL_SYS_SIGLIST # if HAVE_DECL__SYS_SIGLIST # define sys_siglist _sys_siglist # elif HAVE_DECL___SYS_SIGLIST # define sys_siglist __sys_siglist # else static char sig_initted = 0; if (!sig_initted) sig_initted = signame_init (); # endif #endif if (sig > 0 && sig < NSIG) return (char *) sys_siglist[sig]; sprintf (buf, "Signal %d", sig); return buf; } #endif /* HAVE_STRSIGNAL */ kbuild-3686/src/kmk/glob/0000775000175000017500000000000015053010075015204 5ustar locutuslocutuskbuild-3686/src/kmk/glob/Makefile.am0000664000175000017500000000214415053010075017241 0ustar locutuslocutus# -*-Makefile-*-, or close enough # Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) any later # version. # # GNU Make 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, see . AUTOMAKE_OPTIONS = foreign # Only build the library when the system doesn't already have GNU glob. if USE_LOCAL_GLOB noinst_LIBRARIES = libglob.a endif libglob_a_SOURCES = glob.c glob.h fnmatch.c fnmatch.h EXTRA_DIST = COPYING.LIB Makefile.ami SCOPTIONS SMakefile \ configure.bat kbuild-3686/src/kmk/glob/ChangeLog0000664000175000017500000001543515053010075016766 0ustar locutuslocutus2013-10-20 Paul Smith * glob.c (glob): Cherry-pick a471e96a5352a5f0bde6d32dd36d33524811a2b1 from git://sourceware.org/git/glibc.git to fix SV 18123, https://sourceware.org/bugzilla/show_bug.cgi?id=10278 2008-09-28 Juan Manuel Guerrero * glob.c (my_realloc) [__DJGPP__]: Don't define, and don't redefine realloc to call it, since the DJGPP's realloc handles NULL pointers correctly. 2007-12-22 Juan Manuel Guerrero (tiny change) * glob.c [__GNU_LIBRARY__ && __DJGPP__]: Add a realloc declaration that matches the one in the DJGPP libc. 2006-02-24 Eli Zaretskii * glob.c (my_malloc) [WINDOWS32]: Provide a full ISO C prototype, to avoid compiler warnings. 2005-06-25 Paul D. Smith * fnmatch.h, glob.h [WINDOWS32]: Fix ifdefs in headers. Fixes Savannah bug #13477. 2005-03-11 Paul D. Smith * glob.c (glob_in_dir): Change FNM_CASEFOLD to be enabled if HAVE_CASE_INSENSITIVE_FS is defined. 2003-01-30 Paul D. Smith * glob.h: Patch for FreeBSD by Mike Barcroft Reported by Gerald Pfeifer . On FreeBSD, declare __size_t to simply size_t. 2002-04-22 Paul D. Smith * Makefile.am: Use automake 1.6. Use new automake condition USE_LOCAL_GLOB to decide whether or not to build the local GNU glob library or use the system one. 1999-09-12 Paul D. Smith * fnmatch.c: Last GLIBC version wouldn't compile outside of GLIBC (undefined reference to internal_function). Update to the latest version 1999-09-11 Paul Eggert * glob.h (glob): If #defining to glob64, do this before declaring it, so that all declarations and uses match, and do not declare glob64, to avoid a declaration clash. (globfree): Likewise with globfree64. 1999-09-08 Eli Zaretskii * glob.c (prefix_array) [__MSDOS__,WINDOWS32]: Keep the trailing slash unless DIRNAME is just "x:/". 1999-09-06 Paul D. Smith * fnmatch.c: Update to latest version from GLIBC. 1999-07-21 Paul D. Smith * glob.c, glob.h, fnmatch.c, fnmatch.h: Update to latest version from GLIBC. * fnmatch.c (internal_fnmatch): Use K&R definition syntax, not ANSI. (__strchrnul): This won't exist outside GLIBC, so create one. * glob.c: Move getlogin{,_r} prototypes below glob.h to get __P() macro. 1998-08-05 Paul D. Smith * configure.in: Remove; configuration for glob is handled by the make configure.in. 1998-07-29 Paul D. Smith * glob.c, fnmatch.c: New versions from the GLIBC folks (Ulrich Drepper). Fixes a bug reported by Eli Zaretski. Integrates DOS/Windows32 support. 1998-07-27 Kaveh R. Ghazi * glob.c (glob): Cast away const on assignment of pattern to dirname. Cast the return type of __alloca() for traditional C compilers. 1998-07-23 Paul D. Smith * glob.c, fnmatch.c: New versions of these files from the GLIBC folks (Ulrich Drepper). Had to re-integrate some DOS/Windows code. 1998-07-10 Paul D. Smith * glob.c (glob_in_dir): If no meta chars exist in PATTERN and GLOB_NOCHECK is present, don't look for the file--whether it's found or not, we'll always return it, so why bother searching? Also, if we are searching and there are no meta chars, don't bother trying fnmatch() if the strcmp() fails. 1998-05-30 Eli Zaretskii * glob.c (glob) [__MSDOS__, WINDOWS32]: Compute the directory and filename parts of the pattern correctly when it includes a drive spec. Disallow wildcards in the drive spec. Prevent recursion when dirname is of the form "d:/" or "d:". (prefix_array) [__MSDOS__, WINDOWS32]: Don't append a slash to "d:/" and "d:". 1998-05-13 Paul D. Smith * SMakefile, Makefile.ami, glob.c, glob.h, fnmatch.c: Updated from the latest glibc version. 1998-04-17 Paul D. Smith * configure.in: Create a config.h file instead of setting things on the compile line. This is because when build.sh runs it merely passes -DHAVE_CONFIG_H to the glob files, just as it does to the make files. * config.h.in: Created by autoheader. Tue Aug 12 10:52:34 1997 Paul D. Smith * configure.in: Require autoconf 2.12. * glob: Updates from latest GNU libc glob code. * glob.c,glob.h,fnmatch.h: Change all WIN32 references to WINDOWS32. * glob.h: OSF4 defines macros in such a way that GLOB_ALTDIRFUNC is not defined. Added a test to the #if which defines it if _GNU_SOURCE is defined; that's set by both glob.c and GNU make. * glob.c: SunOS4 w/ cc needs #include , since assert.h requires stderr but doesn't include stdio.h :-/. (next_brace_sub): De-protoize function definition. (glob): Cast __alloca(); on SunOS4 it uses the default return type of int. (glob): Irix defines getlogin_r() to return a char*; move the extern for that into the _LIBC area since it isn't used except in LIBC anyway. Likewise, move extern getlogin() into the "else". Sat Jul 20 21:55:31 1996 Roland McGrath Win32 hacks from . * posix/glob.c [WIN32]: Don't include ; don't use d_ino; use void * for my_realloc; include for alloca. (glob) [WIN32]: Use "c:/users/default" for ~ if no HOME variable. * posix/fnmatch.h [WIN32]: Use prototypes even if [!__STDC__]. * posix/glob.h: Likewise. Fri Jul 19 16:56:41 1996 Roland McGrath * posix/glob.h [!_AMIGA && !VMS]: Check this instead of just [!_AMIGA] for `struct stat;' forward decl. Sat Jun 22 10:44:09 1996 Roland McGrath * posix/glob.c: Include only [HAVE_ALLOCA_H], not [sparc]. Fri Jun 21 00:27:51 1996 Roland McGrath * posix/fnmatch.c (fnmatch): Fix \*[*?]+ case to increment name ptr only for ?s, not for *s. Fix from Chet Ramey. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . kbuild-3686/src/kmk/glob/configure.bat0000664000175000017500000000332415053010075017657 0ustar locutuslocutus@echo off rem Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, rem 2004, 2005, 2006, 2007 Free Software Foundation, Inc. rem This file is part of GNU Make. rem rem GNU Make is free software; you can redistribute it and/or modify it under rem the terms of the GNU General Public License as published by the Free rem Software Foundation; either version 3 of the License, or (at your option) rem any later version. rem rem GNU Make is distributed in the hope that it will be useful, but WITHOUT rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. rem more details. rem rem You should have received a copy of the GNU General Public License along rem with this program. If not, see . echo Configuring glob for DJGPP rem This batch file assumes a unix-type "sed" program echo # Makefile generated by "configure.bat"> Makefile if exist config.sed del config.sed echo "s/@srcdir@/./ ">> config.sed echo "s/@CC@/gcc/ ">> config.sed echo "s/@CFLAGS@/-O2 -g/ ">> config.sed echo "s/@CPPFLAGS@/-DHAVE_CONFIG_H -I../ ">> config.sed echo "s/@AR@/ar/ ">> config.sed echo "s/@RANLIB@/ranlib/ ">> config.sed echo "s/@LDFLAGS@// ">> config.sed echo "s/@DEFS@// ">> config.sed echo "s/@ALLOCA@// ">> config.sed echo "s/@LIBS@// ">> config.sed echo "s/@LIBOBJS@// ">> config.sed echo "s/^Makefile *:/_Makefile:/ ">> config.sed echo "s/^config.h *:/_config.h:/ ">> config.sed sed -e "s/^\"//" -e "s/\"$//" -e "s/[ ]*$//" config.sed > config2.sed sed -f config2.sed Makefile.in >> Makefile del config.sed del config2.sed kbuild-3686/src/kmk/glob/SCOPTIONS0000664000175000017500000000030315053010075016504 0ustar locutuslocutusERRORREXX OPTIMIZE NOVERSION OPTIMIZERTIME OPTIMIZERALIAS DEFINE INCLUDEDIR="include:" DEFINE LIBDIR="lib:" DEFINE NO_ALLOCA DEFINE NO_FLOAT DEFINE NO_ARCHIVES IGNORE=161 IGNORE=100 STARTUP=cres kbuild-3686/src/kmk/glob/Makefile.ami0000664000175000017500000000377615053010075017426 0ustar locutuslocutus# Makefile for standalone libglob.a (fnmatch, glob). -*-Makefile-*- # Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) any later # version. # # GNU Make 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, see . # Ultrix 2.2 make doesn't expand the value of VPATH. VPATH = /glob/ # This must repeat the value, because configure will remove `VPATH = .'. srcdir = /glob/ CC = sc RM = delete CPPFLAGS = CFLAGS = # Information determined by configure. DEFS = Define HAVE_HEADER_STDC Define HAVE_UNISTD_H Define HAVE_STRING_H \ Define HAVE_DIRENT_H # How to invoke ar. AR = join ARFLAGS = as # How to invoke ranlib. RANLIB = ; .PHONY: all all: glob.lib glob.lib : glob.o fnmatch.o $(AR) $(ARFLAGS) $@ glob.o fnmatch.o $(RANLIB) $@ # For some reason, Unix make wants the dependencies on the source files. # Otherwise it refuses to use an implicit rule! # And, get this: it doesn't work to use $(srcdir)foo.c!! glob.o: $(srcdir)glob.h $(srcdir)fnmatch.h glob.c fnmatch.o: $(srcdir)fnmatch.h fnmatch.c OUTPUT_OPTION = .c.o: $(CC) IDir "" \ $(DEFS) $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION) .PHONY: clean realclean glob-clean glob-realclean distclean clean glob-clean: -$(RM) glob.lib "#?.o" core distclean glob-realclean: clean -$(RM) TAGS tags Makefile config.status config.h config.log realcean: distclean # For inside the C library. glob.tar glob.tar.Z: $(MAKE) -C .. $@ kbuild-3686/src/kmk/glob/COPYING.LIB0000664000175000017500000006125715053010075016657 0ustar locutuslocutus GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision 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 generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! kbuild-3686/src/kmk/glob/glob.h0000664000175000017500000001667615053010075016320 0ustar locutuslocutus/* Copyright (C) 1991, 1992, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _GLOB_H #define _GLOB_H 1 #ifdef __cplusplus extern "C" { #endif #undef __ptr_t #if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32 # if !defined __GLIBC__ # undef __P # undef __PMT # define __P(protos) protos # define __PMT(protos) protos # if !defined __GNUC__ || __GNUC__ < 2 # undef __const # define __const const # endif # endif # define __ptr_t void * #else /* Not C++ or ANSI C. */ # undef __P # undef __PMT # define __P(protos) () # define __PMT(protos) () # undef __const # define __const # define __ptr_t char * #endif /* C++ or ANSI C. */ /* We need `size_t' for the following definitions. */ #ifndef __size_t # if defined __FreeBSD__ # define __size_t size_t # else # if defined __GNUC__ && __GNUC__ >= 2 typedef __SIZE_TYPE__ __size_t; # else /* This is a guess. */ /*hb * Conflicts with DECCs already defined type __size_t. * Defining an own type with a name beginning with '__' is no good. * Anyway if DECC is used and __SIZE_T is defined then __size_t is * already defined (and I hope it's exactly the one we need here). */ # if !(defined __DECC && defined __SIZE_T) typedef unsigned long int __size_t; # endif # endif # endif #else /* The GNU CC stddef.h version defines __size_t as empty. We need a real definition. */ # undef __size_t # define __size_t size_t #endif /* Bits set in the FLAGS argument to `glob'. */ #define GLOB_ERR (1 << 0)/* Return on read errors. */ #define GLOB_MARK (1 << 1)/* Append a slash to each name. */ #define GLOB_NOSORT (1 << 2)/* Don't sort the names. */ #define GLOB_DOOFFS (1 << 3)/* Insert PGLOB->gl_offs NULLs. */ #define GLOB_NOCHECK (1 << 4)/* If nothing matches, return the pattern. */ #define GLOB_APPEND (1 << 5)/* Append to results of a previous call. */ #define GLOB_NOESCAPE (1 << 6)/* Backslashes don't quote metacharacters. */ #define GLOB_PERIOD (1 << 7)/* Leading `.' can be matched by metachars. */ #if (!defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _BSD_SOURCE \ || defined _GNU_SOURCE) # define GLOB_MAGCHAR (1 << 8)/* Set in gl_flags if any metachars seen. */ # define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions. */ # define GLOB_BRACE (1 << 10)/* Expand "{a,b}" to "a" "b". */ # define GLOB_NOMAGIC (1 << 11)/* If no magic chars, return the pattern. */ # define GLOB_TILDE (1 << 12)/* Expand ~user and ~ to home directories. */ # define GLOB_ONLYDIR (1 << 13)/* Match only directories. */ # define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error if the user name is not available. */ # define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE| \ GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK) #else # define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ GLOB_PERIOD) #endif /* Error returns from `glob'. */ #define GLOB_NOSPACE 1 /* Ran out of memory. */ #define GLOB_ABORTED 2 /* Read error. */ #define GLOB_NOMATCH 3 /* No matches found. */ #define GLOB_NOSYS 4 /* Not implemented. */ #ifdef _GNU_SOURCE /* Previous versions of this file defined GLOB_ABEND instead of GLOB_ABORTED. Provide a compatibility definition here. */ # define GLOB_ABEND GLOB_ABORTED #endif /* Structure describing a globbing run. */ #if !defined _AMIGA && !defined VMS /* Buggy compiler. */ struct stat; #endif typedef struct { __size_t gl_pathc; /* Count of paths matched by the pattern. */ char **gl_pathv; /* List of matched pathnames. */ __size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */ /* If the GLOB_ALTDIRFUNC flag is set, the following functions are used instead of the normal file access functions. */ void (*gl_closedir) __PMT ((void *)); struct dirent *(*gl_readdir) __PMT ((void *)); __ptr_t (*gl_opendir) __PMT ((__const char *)); int (*gl_lstat) __PMT ((__const char *, struct stat *)); #if defined(VMS) && defined(__DECC) && !defined(_POSIX_C_SOURCE) int (*gl_stat) __PMT ((__const char *, struct stat *, ...)); #else int (*gl_stat) __PMT ((__const char *, struct stat *)); #endif #ifdef KMK # define GLOB_WITH_EXTENDED_KMK_MEMBERS int (*gl_exists) __PMT ((__const char *)); int (*gl_isdir) __PMT ((__const char *)); #endif } glob_t; #ifdef _LARGEFILE64_SOURCE struct stat64; typedef struct { __size_t gl_pathc; char **gl_pathv; __size_t gl_offs; int gl_flags; /* If the GLOB_ALTDIRFUNC flag is set, the following functions are used instead of the normal file access functions. */ void (*gl_closedir) __PMT ((void *)); struct dirent64 *(*gl_readdir) __PMT ((void *)); __ptr_t (*gl_opendir) __PMT ((__const char *)); int (*gl_lstat) __PMT ((__const char *, struct stat64 *)); int (*gl_stat) __PMT ((__const char *, struct stat64 *)); } glob64_t; #endif #if _FILE_OFFSET_BITS == 64 && __GNUC__ < 2 # define glob glob64 # define globfree globfree64 #else # ifdef _LARGEFILE64_SOURCE extern int glob64 __P ((__const char *__pattern, int __flags, int (*__errfunc) (__const char *, int), glob64_t *__pglob)); extern void globfree64 __P ((glob64_t *__pglob)); # endif #endif /* Do glob searching for PATTERN, placing results in PGLOB. The bits defined above may be set in FLAGS. If a directory cannot be opened or read and ERRFUNC is not nil, it is called with the pathname that caused the error, and the `errno' value from the failing call; if it returns non-zero `glob' returns GLOB_ABEND; if it returns zero, the error is ignored. If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. Otherwise, `glob' returns zero. */ #if _FILE_OFFSET_BITS != 64 || __GNUC__ < 2 extern int glob __P ((__const char *__pattern, int __flags, int (*__errfunc) (__const char *, int), glob_t *__pglob)); /* Free storage allocated in PGLOB by a previous `glob' call. */ extern void globfree __P ((glob_t *__pglob)); #else extern int glob __P ((__const char *__pattern, int __flags, int (*__errfunc) (__const char *, int), glob_t *__pglob)) __asm__ ("glob64"); extern void globfree __P ((glob_t *__pglob)) __asm__ ("globfree64"); #endif #ifdef _GNU_SOURCE /* Return nonzero if PATTERN contains any metacharacters. Metacharacters can be quoted with backslashes if QUOTE is nonzero. This function is not part of the interface specified by POSIX.2 but several programs want to use it. */ extern int glob_pattern_p __P ((__const char *__pattern, int __quote)); #endif #ifdef __cplusplus } #endif #endif /* glob.h */ kbuild-3686/src/kmk/glob/SMakefile0000664000175000017500000000376315053010075017000 0ustar locutuslocutus# Makefile for standalone distribution of libglob.a (fnmatch, glob). # Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) any later # version. # # GNU Make 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, see . # Ultrix 2.2 make doesn't expand the value of VPATH. VPATH = /glob/ # This must repeat the value, because configure will remove `VPATH = .'. srcdir = /glob/ CC = sc CPPFLAGS = CFLAGS = MAKE = smake RM = delete # Information determined by configure. DEFS = Define HAVE_HEADER_STDC Define HAVE_UNISTD_H Define HAVE_STRING_H \ Define HAVE_DIRENT_H # How to invoke ar. AR = join ARFLAGS = as # How to invoke ranlib. RANLIB = ; .PHONY: all all: glob.lib glob.lib : glob.o fnmatch.o $(AR) $(ARFLAGS) $@ glob.o fnmatch.o $(RANLIB) $@ # For some reason, Unix make wants the dependencies on the source files. # Otherwise it refuses to use an implicit rule! # And, get this: it doesn't work to use $(srcdir)foo.c!! glob.o: $(srcdir)glob.h $(srcdir)fnmatch.h glob.c fnmatch.o: $(srcdir)fnmatch.h fnmatch.c .c.o: $(CC) IDir "" \ $(DEFS) $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION) .PHONY: clean realclean glob-clean glob-realclean distclean clean glob-clean: -$(RM) -f glob.lib *.o core distclean glob-realclean: clean -$(RM) -f TAGS tags Makefile config.status config.h config.log realcean: distclean # For inside the C library. glob.tar glob.tar.Z: $(MAKE) -C .. $@ kbuild-3686/src/kmk/glob/fnmatch.c0000664000175000017500000003124015053010075016770 0ustar locutuslocutus/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #if HAVE_CONFIG_H # include #endif /* Enable GNU extensions in fnmatch.h. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif #include #include #include #if HAVE_STRING_H || defined _LIBC # include #else # include #endif #if defined STDC_HEADERS || defined _LIBC # include #endif /* For platform which support the ISO C amendement 1 functionality we support user defined character classes. */ #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) /* Solaris 2.5 has a bug: must be included before . */ # include # include #endif /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined _LIBC || !defined __GNU_LIBRARY__ || 1 /* bird: Same as for glob.c, don't want trouble. */ # if defined STDC_HEADERS || !defined isascii # define ISASCII(c) 1 # else # define ISASCII(c) isascii(c) # endif # ifdef isblank # define ISBLANK(c) (ISASCII (c) && isblank (c)) # else # define ISBLANK(c) ((c) == ' ' || (c) == '\t') # endif # ifdef isgraph # define ISGRAPH(c) (ISASCII (c) && isgraph (c)) # else # define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) # endif # define ISPRINT(c) (ISASCII (c) && isprint (c)) # define ISDIGIT(c) (ISASCII (c) && isdigit (c)) # define ISALNUM(c) (ISASCII (c) && isalnum (c)) # define ISALPHA(c) (ISASCII (c) && isalpha (c)) # define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) # define ISLOWER(c) (ISASCII (c) && islower (c)) # define ISPUNCT(c) (ISASCII (c) && ispunct (c)) # define ISSPACE(c) (ISASCII (c) && isspace (c)) # define ISUPPER(c) (ISASCII (c) && isupper (c)) # define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) # define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) /* The GNU C library provides support for user-defined character classes and the functions from ISO C amendement 1. */ # ifdef CHARCLASS_NAME_MAX # define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX # else /* This shouldn't happen but some implementation might still have this problem. Use a reasonable default value. */ # define CHAR_CLASS_MAX_LENGTH 256 # endif # ifdef _LIBC # define IS_CHAR_CLASS(string) __wctype (string) # else # define IS_CHAR_CLASS(string) wctype (string) # endif # else # define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ # define IS_CHAR_CLASS(string) \ (STREQ (string, "alpha") || STREQ (string, "upper") \ || STREQ (string, "lower") || STREQ (string, "digit") \ || STREQ (string, "alnum") || STREQ (string, "xdigit") \ || STREQ (string, "space") || STREQ (string, "print") \ || STREQ (string, "punct") || STREQ (string, "graph") \ || STREQ (string, "cntrl") || STREQ (string, "blank")) # endif /* Avoid depending on library functions or files whose names are inconsistent. */ # if !defined _LIBC && !defined getenv && !defined _MSC_VER extern char *getenv (); # endif # ifndef errno extern int errno; # endif /* This function doesn't exist on most systems. */ # if !defined HAVE___STRCHRNUL && !defined _LIBC static char * __strchrnul (s, c) const char *s; int c; { char *result = strchr (s, c); if (result == NULL) result = strchr (s, '\0'); return result; } # endif # ifndef internal_function /* Inside GNU libc we mark some function in a special way. In other environments simply ignore the marking. */ # define internal_function # endif /* Match STRING against the filename pattern PATTERN, returning zero if it matches, nonzero if not. */ static int internal_fnmatch __P ((const char *pattern, const char *string, int no_leading_period, int flags)) internal_function; static int internal_function internal_fnmatch (pattern, string, no_leading_period, flags) const char *pattern; const char *string; int no_leading_period; int flags; { register const char *p = pattern, *n = string; register unsigned char c; /* Note that this evaluates C many times. */ # ifdef _LIBC # define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) # else # define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) # endif while ((c = *p++) != '\0') { c = FOLD (c); switch (c) { case '?': if (*n == '\0') return FNM_NOMATCH; else if (*n == '/' && (flags & FNM_FILE_NAME)) return FNM_NOMATCH; else if (*n == '.' && no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) return FNM_NOMATCH; break; case '\\': if (!(flags & FNM_NOESCAPE)) { c = *p++; if (c == '\0') /* Trailing \ loses. */ return FNM_NOMATCH; c = FOLD (c); } if (FOLD ((unsigned char) *n) != c) return FNM_NOMATCH; break; case '*': if (*n == '.' && no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) return FNM_NOMATCH; for (c = *p++; c == '?' || c == '*'; c = *p++) { if (*n == '/' && (flags & FNM_FILE_NAME)) /* A slash does not match a wildcard under FNM_FILE_NAME. */ return FNM_NOMATCH; else if (c == '?') { /* A ? needs to match one character. */ if (*n == '\0') /* There isn't another character; no match. */ return FNM_NOMATCH; else /* One character of the string is consumed in matching this ? wildcard, so *??? won't match if there are less than three characters. */ ++n; } } if (c == '\0') /* The wildcard(s) is/are the last element of the pattern. If the name is a file name and contains another slash this does mean it cannot match. */ return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL ? FNM_NOMATCH : 0); else { const char *endp; endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0'); if (c == '[') { int flags2 = ((flags & FNM_FILE_NAME) ? flags : (flags & ~FNM_PERIOD)); for (--p; n < endp; ++n) if (internal_fnmatch (p, n, (no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))), flags2) == 0) return 0; } else if (c == '/' && (flags & FNM_FILE_NAME)) { while (*n != '\0' && *n != '/') ++n; if (*n == '/' && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD, flags) == 0)) return 0; } else { int flags2 = ((flags & FNM_FILE_NAME) ? flags : (flags & ~FNM_PERIOD)); if (c == '\\' && !(flags & FNM_NOESCAPE)) c = *p; c = FOLD (c); for (--p; n < endp; ++n) if (FOLD ((unsigned char) *n) == c && (internal_fnmatch (p, n, (no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))), flags2) == 0)) return 0; } } /* If we come here no match is possible with the wildcard. */ return FNM_NOMATCH; case '[': { /* Nonzero if the sense of the character class is inverted. */ static int posixly_correct; register int not; char cold; if (posixly_correct == 0) posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; if (*n == '\0') return FNM_NOMATCH; if (*n == '.' && no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) return FNM_NOMATCH; if (*n == '/' && (flags & FNM_FILE_NAME)) /* `/' cannot be matched. */ return FNM_NOMATCH; not = (*p == '!' || (posixly_correct < 0 && *p == '^')); if (not) ++p; c = *p++; for (;;) { unsigned char fn = FOLD ((unsigned char) *n); if (!(flags & FNM_NOESCAPE) && c == '\\') { if (*p == '\0') return FNM_NOMATCH; c = FOLD ((unsigned char) *p); ++p; if (c == fn) goto matched; } else if (c == '[' && *p == ':') { /* Leave room for the null. */ char str[CHAR_CLASS_MAX_LENGTH + 1]; size_t c1 = 0; # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) wctype_t wt; # endif const char *startp = p; for (;;) { if (c1 == CHAR_CLASS_MAX_LENGTH) /* The name is too long and therefore the pattern is ill-formed. */ return FNM_NOMATCH; c = *++p; if (c == ':' && p[1] == ']') { p += 2; break; } if (c < 'a' || c >= 'z') { /* This cannot possibly be a character class name. Match it as a normal range. */ p = startp; c = '['; goto normal_bracket; } str[c1++] = c; } str[c1] = '\0'; # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) wt = IS_CHAR_CLASS (str); if (wt == 0) /* Invalid character class name. */ return FNM_NOMATCH; if (__iswctype (__btowc ((unsigned char) *n), wt)) goto matched; # else if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n)) || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n)) || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n)) || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n)) || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n)) || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n)) || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n)) || (STREQ (str, "print") && ISPRINT ((unsigned char) *n)) || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n)) || (STREQ (str, "space") && ISSPACE ((unsigned char) *n)) || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n)) || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n))) goto matched; # endif } else if (c == '\0') /* [ (unterminated) loses. */ return FNM_NOMATCH; else { normal_bracket: if (FOLD (c) == fn) goto matched; cold = c; c = *p++; if (c == '-' && *p != ']') { /* It is a range. */ unsigned char cend = *p++; if (!(flags & FNM_NOESCAPE) && cend == '\\') cend = *p++; if (cend == '\0') return FNM_NOMATCH; if (cold <= fn && fn <= FOLD (cend)) goto matched; c = *p++; } } if (c == ']') break; } if (!not) return FNM_NOMATCH; break; matched: /* Skip the rest of the [...] that already matched. */ while (c != ']') { if (c == '\0') /* [... (unterminated) loses. */ return FNM_NOMATCH; c = *p++; if (!(flags & FNM_NOESCAPE) && c == '\\') { if (*p == '\0') return FNM_NOMATCH; /* XXX 1003.2d11 is unclear if this is right. */ ++p; } else if (c == '[' && *p == ':') { do if (*++p == '\0') return FNM_NOMATCH; while (*p != ':' || p[1] == ']'); p += 2; c = *p; } } if (not) return FNM_NOMATCH; } break; default: if (c != FOLD ((unsigned char) *n)) return FNM_NOMATCH; } ++n; } if (*n == '\0') return 0; if ((flags & FNM_LEADING_DIR) && *n == '/') /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ return 0; return FNM_NOMATCH; # undef FOLD } int fnmatch (pattern, string, flags) const char *pattern; const char *string; int flags; { return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags); } #endif /* _LIBC or not __GNU_LIBRARY__. */ kbuild-3686/src/kmk/glob/fnmatch.h0000664000175000017500000000556315053010075017006 0ustar locutuslocutus/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _FNMATCH_H #define _FNMATCH_H 1 #ifdef __cplusplus extern "C" { #endif #if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32 # if !defined __GLIBC__ # undef __P # define __P(protos) protos # endif #else /* Not C++ or ANSI C. */ # undef __P # define __P(protos) () /* We can get away without defining `const' here only because in this file it is used only inside the prototype for `fnmatch', which is elided in non-ANSI C where `const' is problematical. */ #endif /* C++ or ANSI C. */ #ifndef const # if (defined __STDC__ && __STDC__) || defined __cplusplus || defined WINDOWS32 # define __const const # else # define __const # endif #endif /* We #undef these before defining them because some losing systems (HP-UX A.08.07 for example) define these in . */ #undef FNM_PATHNAME #undef FNM_NOESCAPE #undef FNM_PERIOD /* Bits set in the FLAGS argument to `fnmatch'. */ #define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ #define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ #define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ #if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE # define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ # define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ # define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ #endif /* Value returned by `fnmatch' if STRING does not match PATTERN. */ #define FNM_NOMATCH 1 /* This value is returned if the implementation does not support `fnmatch'. Since this is not the case here it will never be returned but the conformance test suites still require the symbol to be defined. */ #ifdef _XOPEN_SOURCE # define FNM_NOSYS (-1) #endif /* Match NAME against the filename pattern PATTERN, returning zero if it matches, FNM_NOMATCH if not. */ extern int fnmatch __P ((__const char *__pattern, __const char *__name, int __flags)); #ifdef __cplusplus } #endif #endif /* fnmatch.h */ kbuild-3686/src/kmk/glob/glob.c0000664000175000017500000011036015053010075016274 0ustar locutuslocutus/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ /* AIX requires this to be the first thing in the file. */ #if defined _AIX && !defined __GNUC__ #pragma alloca #endif #ifdef HAVE_CONFIG_H # include #endif /* Enable GNU extensions in glob.h. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif #include #include #include /* Outcomment the following line for production quality code. */ /* #define NDEBUG 1 */ #include #include /* Needed on stupid SunOS for assert. */ /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GLOB_INTERFACE_VERSION 1 #if 0 /* bird: Apparently this causes trouble for some debian builds. */ #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 # include # if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #endif #ifndef ELIDE_CODE #if defined STDC_HEADERS || defined __GNU_LIBRARY__ # include #endif #if defined HAVE_UNISTD_H || defined _LIBC # include # ifndef POSIX # ifdef _POSIX_VERSION # define POSIX # endif # endif #endif #if !defined _AMIGA && !defined VMS && !defined WINDOWS32 # include #endif #if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS extern int errno; #endif #ifndef __set_errno # define __set_errno(val) errno = (val) #endif #ifndef NULL # define NULL 0 #endif #if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ # include # define NAMLEN(dirent) strlen((dirent)->d_name) #else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # ifdef HAVE_SYS_NDIR_H # include # endif # ifdef HAVE_SYS_DIR_H # include # endif # ifdef HAVE_NDIR_H # include # endif # ifdef HAVE_VMSDIR_H # include "vmsdir.h" # endif /* HAVE_VMSDIR_H */ #endif /* In GNU systems, defines this macro for us. */ #ifdef _D_NAMLEN # undef NAMLEN # define NAMLEN(d) _D_NAMLEN(d) #endif /* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available if the `d_type' member for `struct dirent' is available. */ #ifdef _DIRENT_HAVE_D_TYPE # define HAVE_D_TYPE 1 #endif #if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ /* Posix does not require that the d_ino field be present, and some systems do not provide it. */ # define REAL_DIR_ENTRY(dp) 1 #else # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) #endif /* POSIX */ #if defined STDC_HEADERS || defined __GNU_LIBRARY__ # include # include # define ANSI_STRING #else /* No standard headers. */ extern char *getenv (); # ifdef HAVE_STRING_H # include # define ANSI_STRING # else # include # endif # ifdef HAVE_MEMORY_H # include # endif extern char *malloc (), *realloc (); extern void free (); extern void qsort (); extern void abort (), exit (); #endif /* Standard headers. */ #ifndef ANSI_STRING # ifndef bzero extern void bzero (); # endif # ifndef bcopy extern void bcopy (); # endif # define memcpy(d, s, n) bcopy ((s), (d), (n)) # define strrchr rindex /* memset is only used for zero here, but let's be paranoid. */ # define memset(s, better_be_zero, n) \ ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0))) #endif /* Not ANSI_STRING. */ #if !defined HAVE_STRCOLL && !defined _LIBC # define strcoll strcmp #endif #if !defined HAVE_MEMPCPY && __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1 # define HAVE_MEMPCPY 1 #if 0 /* bird: This messes with the electric.c heap (linux/amd64). Probably missing prototype, so int return. */ # undef mempcpy # define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len) #endif #endif #if !defined __GNU_LIBRARY__ && !defined __DJGPP__ && !defined ELECTRIC_HEAP && !defined __APPLE__ /* bird (last two) */ # ifdef __GNUC__ __inline # endif # ifndef __SASC # ifdef WINDOWS32 # include static void * my_realloc (void *p, unsigned int n) # else static char * my_realloc (p, n) char *p; unsigned int n; # endif { /* These casts are the for sake of the broken Ultrix compiler, which warns of illegal pointer combinations otherwise. */ if (p == NULL) return (char *) malloc (n); return (char *) realloc (p, n); } # define realloc my_realloc # endif /* __SASC */ #endif /* __GNU_LIBRARY__ || __DJGPP__ */ #if !defined __alloca /*&& !defined __GNU_LIBRARY__ - bird: unresolved __alloca symbol if skipping this for gnu libc. duh. */ # ifdef __GNUC__ # undef alloca # define alloca(n) __builtin_alloca (n) # else /* Not GCC. */ # ifdef HAVE_ALLOCA_H # include # else /* Not HAVE_ALLOCA_H. */ # ifndef _AIX # ifdef WINDOWS32 # include # else extern char *alloca (); # endif /* WINDOWS32 */ # endif /* Not _AIX. */ # endif /* sparc or HAVE_ALLOCA_H. */ # endif /* Not GCC. */ # define __alloca alloca #endif #if 1 /*bird: sigh. ndef __GNU_LIBRARY__*/ # define __stat stat # ifdef STAT_MACROS_BROKEN # undef S_ISDIR # endif # ifndef S_ISDIR # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) # endif #endif #ifdef _LIBC # ifdef KMK # error "_LIBC better not be defined!" # endif # undef strdup # define strdup(str) __strdup (str) # define sysconf(id) __sysconf (id) # define closedir(dir) __closedir (dir) # define opendir(name) __opendir (name) # define readdir(str) __readdir (str) # define getpwnam_r(name, bufp, buf, len, res) \ __getpwnam_r (name, bufp, buf, len, res) # ifndef __stat # define __stat(fname, buf) __xstat (_STAT_VER, fname, buf) # endif #endif #if !(defined STDC_HEADERS || defined __GNU_LIBRARY__) # undef size_t # define size_t unsigned int #endif /* Some system header files erroneously define these. We want our own definitions from to take precedence. */ #ifndef __GNU_LIBRARY__ # undef FNM_PATHNAME # undef FNM_NOESCAPE # undef FNM_PERIOD #endif #include /* Some system header files erroneously define these. We want our own definitions from to take precedence. */ #ifndef __GNU_LIBRARY__ # undef GLOB_ERR # undef GLOB_MARK # undef GLOB_NOSORT # undef GLOB_DOOFFS # undef GLOB_NOCHECK # undef GLOB_APPEND # undef GLOB_NOESCAPE # undef GLOB_PERIOD #endif #include #ifdef HAVE_GETLOGIN_R extern int getlogin_r __P ((char *, size_t)); #else extern char *getlogin __P ((void)); #endif static #if __GNUC__ - 0 >= 2 inline #endif const char *next_brace_sub __P ((const char *begin)); static int glob_in_dir __P ((const char *pattern, const char *directory, int flags, int (*errfunc) (const char *, int), glob_t *pglob)); static int prefix_array __P ((const char *prefix, char **array, size_t n)); static int collated_compare __P ((const __ptr_t, const __ptr_t)); #if !defined _LIBC || !defined NO_GLOB_PATTERN_P int __glob_pattern_p __P ((const char *pattern, int quote)); #endif /* Find the end of the sub-pattern in a brace expression. We define this as an inline function if the compiler permits. */ static #if __GNUC__ - 0 >= 2 inline #endif const char * next_brace_sub (begin) const char *begin; { unsigned int depth = 0; const char *cp = begin; while (1) { if (depth == 0) { if (*cp != ',' && *cp != '}' && *cp != '\0') { if (*cp == '{') ++depth; ++cp; continue; } } else { while (*cp != '\0' && (*cp != '}' || depth > 0)) { if (*cp == '}') --depth; ++cp; } if (*cp == '\0') /* An incorrectly terminated brace expression. */ return NULL; continue; } break; } return cp; } /* Do glob searching for PATTERN, placing results in PGLOB. The bits defined above may be set in FLAGS. If a directory cannot be opened or read and ERRFUNC is not nil, it is called with the pathname that caused the error, and the `errno' value from the failing call; if it returns non-zero `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored. If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. Otherwise, `glob' returns zero. */ int glob (pattern, flags, errfunc, pglob) const char *pattern; int flags; int (*errfunc) __P ((const char *, int)); glob_t *pglob; { const char *filename; const char *dirname; size_t dirlen; int status; __size_t oldcount; /* bird: correct type. */ if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) { __set_errno (EINVAL); return -1; } /* POSIX requires all slashes to be matched. This means that with a trailing slash we must match only directories. */ if (pattern[0] && pattern[strlen (pattern) - 1] == '/') flags |= GLOB_ONLYDIR; if (flags & GLOB_BRACE) { const char *begin = strchr (pattern, '{'); if (begin != NULL) { /* Allocate working buffer large enough for our work. Note that we have at least an opening and closing brace. */ size_t firstc; /* bird: correct type. */ char *alt_start; const char *p; const char *next; const char *rest; size_t rest_len; #ifdef __GNUC__ char onealt[strlen (pattern) - 1]; #else char *onealt = (char *) malloc (strlen (pattern) - 1); if (onealt == NULL) { if (!(flags & GLOB_APPEND)) globfree (pglob); return GLOB_NOSPACE; } #endif /* We know the prefix for all sub-patterns. */ #ifdef HAVE_MEMPCPY alt_start = mempcpy (onealt, pattern, begin - pattern); #else memcpy (onealt, pattern, begin - pattern); alt_start = &onealt[begin - pattern]; #endif /* Find the first sub-pattern and at the same time find the rest after the closing brace. */ next = next_brace_sub (begin + 1); if (next == NULL) { /* It is an illegal expression. */ #ifndef __GNUC__ free (onealt); #endif return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); } /* Now find the end of the whole brace expression. */ rest = next; while (*rest != '}') { rest = next_brace_sub (rest + 1); if (rest == NULL) { /* It is an illegal expression. */ #ifndef __GNUC__ free (onealt); #endif return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); } } /* Please note that we now can be sure the brace expression is well-formed. */ rest_len = strlen (++rest) + 1; /* We have a brace expression. BEGIN points to the opening {, NEXT points past the terminator of the first element, and END points past the final }. We will accumulate result names from recursive runs for each brace alternative in the buffer using GLOB_APPEND. */ if (!(flags & GLOB_APPEND)) { /* This call is to set a new vector, so clear out the vector so we can append to it. */ pglob->gl_pathc = 0; pglob->gl_pathv = NULL; } firstc = pglob->gl_pathc; p = begin + 1; while (1) { int result; /* Construct the new glob expression. */ #ifdef HAVE_MEMPCPY mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len); #else memcpy (alt_start, p, next - p); memcpy (&alt_start[next - p], rest, rest_len); #endif result = glob (onealt, ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC)) | GLOB_APPEND), errfunc, pglob); /* If we got an error, return it. */ if (result && result != GLOB_NOMATCH) { #ifndef __GNUC__ free (onealt); #endif if (!(flags & GLOB_APPEND)) globfree (pglob); return result; } if (*next == '}') /* We saw the last entry. */ break; p = next + 1; next = next_brace_sub (p); assert (next != NULL); } #ifndef __GNUC__ free (onealt); #endif if (pglob->gl_pathc != firstc) /* We found some entries. */ return 0; else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) return GLOB_NOMATCH; } } /* Find the filename. */ filename = strrchr (pattern, '/'); #if defined __MSDOS__ || defined WINDOWS32 /* The case of "d:pattern". Since `:' is not allowed in file names, we can safely assume that wherever it happens in pattern, it signals the filename part. This is so we could some day support patterns like "[a-z]:foo". */ if (filename == NULL) filename = strchr (pattern, ':'); #endif /* __MSDOS__ || WINDOWS32 */ if (filename == NULL) { /* This can mean two things: a simple name or "~name". The later case is nothing but a notation for a directory. */ if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') { dirname = pattern; dirlen = strlen (pattern); /* Set FILENAME to NULL as a special flag. This is ugly but other solutions would require much more code. We test for this special case below. */ filename = NULL; } else { filename = pattern; #ifdef _AMIGA dirname = ""; #else dirname = "."; #endif dirlen = 0; } } else if (filename == pattern) { /* "/pattern". */ dirname = "/"; dirlen = 1; ++filename; } else { char *newp; dirlen = filename - pattern; #if defined __MSDOS__ || defined WINDOWS32 if (*filename == ':' || (filename > pattern + 1 && filename[-1] == ':')) { char *drive_spec; ++dirlen; drive_spec = (char *) __alloca (dirlen + 1); #ifdef HAVE_MEMPCPY *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0'; #else memcpy (drive_spec, pattern, dirlen); drive_spec[dirlen] = '\0'; #endif /* For now, disallow wildcards in the drive spec, to prevent infinite recursion in glob. */ if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE))) return GLOB_NOMATCH; /* If this is "d:pattern", we need to copy `:' to DIRNAME as well. If it's "d:/pattern", don't remove the slash from "d:/", since "d:" and "d:/" are not the same.*/ } #endif newp = (char *) __alloca (dirlen + 1); #ifdef HAVE_MEMPCPY *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; #else memcpy (newp, pattern, dirlen); newp[dirlen] = '\0'; #endif dirname = newp; ++filename; if (filename[0] == '\0' #if defined __MSDOS__ || defined WINDOWS32 && dirname[dirlen - 1] != ':' && (dirlen < 3 || dirname[dirlen - 2] != ':' || dirname[dirlen - 1] != '/') #endif && dirlen > 1) /* "pattern/". Expand "pattern", appending slashes. */ { int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); if (val == 0) pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK)); return val; } } if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; } oldcount = pglob->gl_pathc; #ifndef VMS if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') { if (dirname[1] == '\0' || dirname[1] == '/') { /* Look up home directory. */ #ifdef VMS /* This isn't obvious, RTLs of DECC and VAXC know about "HOME" */ const char *home_dir = getenv ("SYS$LOGIN"); #else const char *home_dir = getenv ("HOME"); #endif # ifdef _AMIGA if (home_dir == NULL || home_dir[0] == '\0') home_dir = "SYS:"; # else # ifdef WINDOWS32 if (home_dir == NULL || home_dir[0] == '\0') home_dir = "c:/users/default"; /* poor default */ # else # ifdef VMS /* Again, this isn't obvious, if "HOME" isn't known "SYS$LOGIN" should be set */ if (home_dir == NULL || home_dir[0] == '\0') home_dir = "SYS$DISK:[]"; # else if (home_dir == NULL || home_dir[0] == '\0') { int success; char *name; # if defined HAVE_GETLOGIN_R || defined _LIBC size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1; if (buflen == 0) /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try a moderate value. */ buflen = 20; name = (char *) __alloca (buflen); success = getlogin_r (name, buflen) >= 0; # else success = (name = getlogin ()) != NULL; # endif if (success) { struct passwd *p; # if defined HAVE_GETPWNAM_R || defined _LIBC size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *pwtmpbuf; struct passwd pwbuf; int save = errno; if (pwbuflen == -1) /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a moderate value. */ pwbuflen = 1024; pwtmpbuf = (char *) __alloca (pwbuflen); while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) != 0) { if (errno != ERANGE) { p = NULL; break; } pwbuflen *= 2; pwtmpbuf = (char *) __alloca (pwbuflen); __set_errno (save); } # else p = getpwnam (name); # endif if (p != NULL) home_dir = p->pw_dir; } } if (home_dir == NULL || home_dir[0] == '\0') { if (flags & GLOB_TILDE_CHECK) return GLOB_NOMATCH; else home_dir = "~"; /* No luck. */ } # endif /* VMS */ # endif /* WINDOWS32 */ # endif /* Now construct the full directory. */ if (dirname[1] == '\0') dirname = home_dir; else { char *newp; size_t home_len = strlen (home_dir); newp = (char *) __alloca (home_len + dirlen); # ifdef HAVE_MEMPCPY mempcpy (mempcpy (newp, home_dir, home_len), &dirname[1], dirlen); # else memcpy (newp, home_dir, home_len); memcpy (&newp[home_len], &dirname[1], dirlen); # endif dirname = newp; } } # if !defined _AMIGA && !defined WINDOWS32 && !defined VMS else { char *end_name = strchr (dirname, '/'); const char *user_name; const char *home_dir; if (end_name == NULL) user_name = dirname + 1; else { char *newp; newp = (char *) __alloca (end_name - dirname); # ifdef HAVE_MEMPCPY *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) = '\0'; # else memcpy (newp, dirname + 1, end_name - dirname); newp[end_name - dirname - 1] = '\0'; # endif user_name = newp; } /* Look up specific user's home directory. */ { struct passwd *p; # if defined HAVE_GETPWNAM_R || defined _LIBC size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *pwtmpbuf; struct passwd pwbuf; int save = errno; if (buflen == -1) /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a moderate value. */ buflen = 1024; pwtmpbuf = (char *) __alloca (buflen); while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) { if (errno != ERANGE) { p = NULL; break; } buflen *= 2; pwtmpbuf = __alloca (buflen); __set_errno (save); } # else p = getpwnam (user_name); # endif if (p != NULL) home_dir = p->pw_dir; else home_dir = NULL; } /* If we found a home directory use this. */ if (home_dir != NULL) { char *newp; size_t home_len = strlen (home_dir); size_t rest_len = end_name == NULL ? 0 : strlen (end_name); newp = (char *) __alloca (home_len + rest_len + 1); # ifdef HAVE_MEMPCPY *((char *) mempcpy (mempcpy (newp, home_dir, home_len), end_name, rest_len)) = '\0'; # else memcpy (newp, home_dir, home_len); memcpy (&newp[home_len], end_name, rest_len); newp[home_len + rest_len] = '\0'; # endif dirname = newp; } else if (flags & GLOB_TILDE_CHECK) /* We have to regard it as an error if we cannot find the home directory. */ return GLOB_NOMATCH; } # endif /* Not Amiga && not WINDOWS32 && not VMS. */ } #endif /* Not VMS. */ /* Now test whether we looked for "~" or "~NAME". In this case we can give the answer now. */ if (filename == NULL) { struct stat st; /* Return the directory if we don't check for error or if it exists. */ if ((flags & GLOB_NOCHECK) #ifdef KMK || (flags & GLOB_ALTDIRFUNC ? (*pglob->gl_isdir) (dirname) : __stat (dirname, &st) == 0 && S_ISDIR (st.st_mode)) #else || (((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_stat) (dirname, &st) : __stat (dirname, &st)) == 0 && S_ISDIR (st.st_mode)) #endif ) { pglob->gl_pathv = (char **) realloc (pglob->gl_pathv, (pglob->gl_pathc + ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + 1 + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) return GLOB_NOSPACE; if (flags & GLOB_DOOFFS) while (pglob->gl_pathc < pglob->gl_offs) pglob->gl_pathv[pglob->gl_pathc++] = NULL; #if defined HAVE_STRDUP || defined _LIBC pglob->gl_pathv[pglob->gl_pathc] = strdup (dirname); #else { size_t len = strlen (dirname) + 1; char *dircopy = malloc (len); if (dircopy != NULL) pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname, len); } #endif if (pglob->gl_pathv[pglob->gl_pathc] == NULL) { free (pglob->gl_pathv); return GLOB_NOSPACE; } pglob->gl_pathv[++pglob->gl_pathc] = NULL; pglob->gl_flags = flags; return 0; } /* Not found. */ return GLOB_NOMATCH; } if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE))) { /* The directory name contains metacharacters, so we have to glob for the directory, and then glob for the pattern in each directory found. */ glob_t dirs; register __size_t i; /* bird: correct type. */ status = glob (dirname, ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) | GLOB_NOSORT | GLOB_ONLYDIR), errfunc, &dirs); if (status != 0) return status; /* We have successfully globbed the preceding directory name. For each name we found, call glob_in_dir on it and FILENAME, appending the results to PGLOB. */ for (i = 0; i < dirs.gl_pathc; ++i) { int old_pathc; #ifdef SHELL { /* Make globbing interruptible in the bash shell. */ extern int interrupt_state; if (interrupt_state) { globfree (&dirs); globfree (&files); return GLOB_ABORTED; } } #endif /* SHELL. */ old_pathc = pglob->gl_pathc; status = glob_in_dir (filename, dirs.gl_pathv[i], ((flags | GLOB_APPEND) & ~(GLOB_NOCHECK | GLOB_ERR)), errfunc, pglob); if (status == GLOB_NOMATCH) /* No matches in this directory. Try the next. */ continue; if (status != 0) { globfree (&dirs); globfree (pglob); return status; } /* Stick the directory on the front of each name. */ if (prefix_array (dirs.gl_pathv[i], &pglob->gl_pathv[old_pathc], pglob->gl_pathc - old_pathc)) { globfree (&dirs); globfree (pglob); return GLOB_NOSPACE; } } flags |= GLOB_MAGCHAR; /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls. But if we have not found any matching entry and thie GLOB_NOCHECK flag was set we must return the list consisting of the disrectory names followed by the filename. */ if (pglob->gl_pathc == oldcount) { /* No matches. */ if (flags & GLOB_NOCHECK) { size_t filename_len = strlen (filename) + 1; char **new_pathv; struct stat st; /* This is an pessimistic guess about the size. */ pglob->gl_pathv = (char **) realloc (pglob->gl_pathv, (pglob->gl_pathc + ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + dirs.gl_pathc + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) { globfree (&dirs); return GLOB_NOSPACE; } if (flags & GLOB_DOOFFS) while (pglob->gl_pathc < pglob->gl_offs) pglob->gl_pathv[pglob->gl_pathc++] = NULL; for (i = 0; i < dirs.gl_pathc; ++i) { const char *dir = dirs.gl_pathv[i]; size_t dir_len = strlen (dir); /* First check whether this really is a directory. */ #ifdef KMK if (flags & GLOB_ALTDIRFUNC ? !pglob->gl_isdir (dir) : __stat (dir, &st) != 0 || !S_ISDIR (st.st_mode)) #else if (((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0 || !S_ISDIR (st.st_mode)) #endif /* No directory, ignore this entry. */ continue; pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1 + filename_len); if (pglob->gl_pathv[pglob->gl_pathc] == NULL) { globfree (&dirs); globfree (pglob); return GLOB_NOSPACE; } #ifdef HAVE_MEMPCPY mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len), "/", 1), filename, filename_len); #else memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len); pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/'; memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1], filename, filename_len); #endif ++pglob->gl_pathc; } pglob->gl_pathv[pglob->gl_pathc] = NULL; pglob->gl_flags = flags; /* Now we know how large the gl_pathv vector must be. */ new_pathv = (char **) realloc (pglob->gl_pathv, ((pglob->gl_pathc + 1) * sizeof (char *))); if (new_pathv != NULL) pglob->gl_pathv = new_pathv; } else return GLOB_NOMATCH; } globfree (&dirs); } else { status = glob_in_dir (filename, dirname, flags, errfunc, pglob); if (status != 0) return status; if (dirlen > 0) { /* Stick the directory on the front of each name. */ __size_t ignore = oldcount; /* bird: correct type. */ if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs) ignore = pglob->gl_offs; if (prefix_array (dirname, &pglob->gl_pathv[ignore], pglob->gl_pathc - ignore)) { globfree (pglob); return GLOB_NOSPACE; } } } if (flags & GLOB_MARK) { /* Append slashes to directory names. */ __size_t i; /* bird: correct type. */ struct stat st; for (i = oldcount; i < pglob->gl_pathc; ++i) #ifdef KMK if (flags & GLOB_ALTDIRFUNC ? pglob->gl_isdir (pglob->gl_pathv[i]) : __stat (pglob->gl_pathv[i], &st) == 0 && S_ISDIR (st.st_mode) ) #else if (((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st) : __stat (pglob->gl_pathv[i], &st)) == 0 && S_ISDIR (st.st_mode)) #endif { size_t len = strlen (pglob->gl_pathv[i]) + 2; char *new = realloc (pglob->gl_pathv[i], len); if (new == NULL) { globfree (pglob); return GLOB_NOSPACE; } strcpy (&new[len - 2], "/"); pglob->gl_pathv[i] = new; } } if (!(flags & GLOB_NOSORT)) { /* Sort the vector. */ int non_sort = oldcount; if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount) non_sort = pglob->gl_offs; qsort ((__ptr_t) &pglob->gl_pathv[non_sort], pglob->gl_pathc - non_sort, sizeof (char *), collated_compare); } return 0; } /* Free storage allocated in PGLOB by a previous `glob' call. */ void globfree (pglob) register glob_t *pglob; { if (pglob->gl_pathv != NULL) { register __size_t i; /* bird: correct type */ for (i = 0; i < pglob->gl_pathc; ++i) if (pglob->gl_pathv[i] != NULL) free ((__ptr_t) pglob->gl_pathv[i]); free ((__ptr_t) pglob->gl_pathv); } } /* Do a collated comparison of A and B. */ static int collated_compare (a, b) const __ptr_t a; const __ptr_t b; { const char *const s1 = *(const char *const * const) a; const char *const s2 = *(const char *const * const) b; if (s1 == s2) return 0; if (s1 == NULL) return 1; if (s2 == NULL) return -1; return strcoll (s1, s2); } /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's elements in place. Return nonzero if out of memory, zero if successful. A slash is inserted between DIRNAME and each elt of ARRAY, unless DIRNAME is just "/". Each old element of ARRAY is freed. */ static int prefix_array (dirname, array, n) const char *dirname; char **array; size_t n; { register size_t i; size_t dirlen = strlen (dirname); #if defined __MSDOS__ || defined WINDOWS32 int sep_char = '/'; # define DIRSEP_CHAR sep_char #else # define DIRSEP_CHAR '/' #endif if (dirlen == 1 && dirname[0] == '/') /* DIRNAME is just "/", so normal prepending would get us "//foo". We want "/foo" instead, so don't prepend any chars from DIRNAME. */ dirlen = 0; #if defined __MSDOS__ || defined WINDOWS32 else if (dirlen > 1) { if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':') /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */ --dirlen; else if (dirname[dirlen - 1] == ':') { /* DIRNAME is "d:". Use `:' instead of `/'. */ --dirlen; sep_char = ':'; } } #endif for (i = 0; i < n; ++i) { size_t eltlen = strlen (array[i]) + 1; char *new = (char *) malloc (dirlen + 1 + eltlen); if (new == NULL) { while (i > 0) free ((__ptr_t) array[--i]); return 1; } #ifdef HAVE_MEMPCPY { char *endp = (char *) mempcpy (new, dirname, dirlen); *endp++ = DIRSEP_CHAR; mempcpy (endp, array[i], eltlen); } #else memcpy (new, dirname, dirlen); new[dirlen] = DIRSEP_CHAR; memcpy (&new[dirlen + 1], array[i], eltlen); #endif free ((__ptr_t) array[i]); array[i] = new; } return 0; } /* We must not compile this function twice. */ #if !defined _LIBC || !defined NO_GLOB_PATTERN_P /* Return nonzero if PATTERN contains any metacharacters. Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ int __glob_pattern_p (pattern, quote) const char *pattern; int quote; { register const char *p; int open = 0; for (p = pattern; *p != '\0'; ++p) switch (*p) { case '?': case '*': return 1; case '\\': if (quote && p[1] != '\0') ++p; break; case '[': open = 1; break; case ']': if (open) return 1; break; } return 0; } # ifdef _LIBC weak_alias (__glob_pattern_p, glob_pattern_p) # endif #endif /* Like `glob', but PATTERN is a final pathname component, and matches are searched for in DIRECTORY. The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done. The GLOB_APPEND flag is assumed to be set (always appends). */ static int glob_in_dir (pattern, directory, flags, errfunc, pglob) const char *pattern; const char *directory; int flags; int (*errfunc) __P ((const char *, int)); glob_t *pglob; { __ptr_t stream = NULL; struct globlink { struct globlink *next; char *name; }; struct globlink *names = NULL; size_t nfound; int meta; int save; #ifdef VMS if (*directory == 0) directory = "[]"; #endif meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); if (meta == 0) { if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)) /* We need not do any tests. The PATTERN contains no meta characters and we must not return an error therefore the result will always contain exactly one name. */ flags |= GLOB_NOCHECK; else { /* Since we use the normal file functions we can also use stat() to verify the file is there. */ struct stat st; size_t patlen = strlen (pattern); size_t dirlen = strlen (directory); char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1); # ifdef HAVE_MEMPCPY mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), "/", 1), pattern, patlen + 1); # else memcpy (fullname, directory, dirlen); fullname[dirlen] = '/'; memcpy (&fullname[dirlen + 1], pattern, patlen + 1); # endif # ifdef KMK if (flags & GLOB_ALTDIRFUNC ? pglob->gl_exists (fullname) : __stat (fullname, &st) == 0) # else if (((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_stat) (fullname, &st) : __stat (fullname, &st)) == 0) # endif /* We found this file to be existing. Now tell the rest of the function to copy this name into the result. */ flags |= GLOB_NOCHECK; } nfound = 0; } else { if (pattern[0] == '\0') { /* This is a special case for matching directories like in "*a/". */ names = (struct globlink *) __alloca (sizeof (struct globlink)); names->name = (char *) malloc (1); if (names->name == NULL) goto memory_error; names->name[0] = '\0'; names->next = NULL; nfound = 1; meta = 0; } else { stream = ((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_opendir) (directory) : (__ptr_t) opendir (directory)); if (stream == NULL) { if (errno != ENOTDIR && ((errfunc != NULL && (*errfunc) (directory, errno)) || (flags & GLOB_ERR))) return GLOB_ABORTED; nfound = 0; meta = 0; } else { int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) #if defined HAVE_CASE_INSENSITIVE_FS | FNM_CASEFOLD #endif ); nfound = 0; flags |= GLOB_MAGCHAR; while (1) { const char *name; size_t len; struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_readdir) (stream) : readdir ((DIR *) stream)); if (d == NULL) break; if (! REAL_DIR_ENTRY (d)) continue; #ifdef HAVE_D_TYPE /* If we shall match only directories use the information provided by the dirent call if possible. */ if ((flags & GLOB_ONLYDIR) && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR) continue; #endif name = d->d_name; if (fnmatch (pattern, name, fnm_flags) == 0) { struct globlink *new = (struct globlink *) __alloca (sizeof (struct globlink)); len = NAMLEN (d); new->name = (char *) malloc (len + 1); if (new->name == NULL) goto memory_error; #ifdef HAVE_MEMPCPY *((char *) mempcpy ((__ptr_t) new->name, name, len)) = '\0'; #else memcpy ((__ptr_t) new->name, name, len); new->name[len] = '\0'; #endif new->next = names; names = new; ++nfound; } } } } } if (nfound == 0 && (flags & GLOB_NOCHECK)) { size_t len = strlen (pattern); nfound = 1; names = (struct globlink *) __alloca (sizeof (struct globlink)); names->next = NULL; names->name = (char *) malloc (len + 1); if (names->name == NULL) goto memory_error; #ifdef HAVE_MEMPCPY *((char *) mempcpy (names->name, pattern, len)) = '\0'; #else memcpy (names->name, pattern, len); names->name[len] = '\0'; #endif } if (nfound != 0) { pglob->gl_pathv = (char **) realloc (pglob->gl_pathv, (pglob->gl_pathc + ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + nfound + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) goto memory_error; if (flags & GLOB_DOOFFS) while (pglob->gl_pathc < pglob->gl_offs) pglob->gl_pathv[pglob->gl_pathc++] = NULL; for (; names != NULL; names = names->next) pglob->gl_pathv[pglob->gl_pathc++] = names->name; pglob->gl_pathv[pglob->gl_pathc] = NULL; pglob->gl_flags = flags; } save = errno; if (stream != NULL) { if (flags & GLOB_ALTDIRFUNC) (*pglob->gl_closedir) (stream); else closedir ((DIR *) stream); } __set_errno (save); return nfound == 0 ? GLOB_NOMATCH : 0; memory_error: { /*int*/ save = errno; if (flags & GLOB_ALTDIRFUNC) (*pglob->gl_closedir) (stream); else closedir ((DIR *) stream); __set_errno (save); } while (names != NULL) { if (names->name != NULL) free ((__ptr_t) names->name); names = names->next; } return GLOB_NOSPACE; } #endif /* Not ELIDE_CODE. */ kbuild-3686/src/kmk/gmk-default.scm0000664000175000017500000000335515053010075017173 0ustar locutuslocutus;; Contents of the (gnu make) Guile module ;; Copyright (C) 2011-2016 Free Software Foundation, Inc. ;; This file is part of GNU Make. ;; ;; GNU Make 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 3 of the License, or (at your option) ;; any later version. ;; ;; GNU Make 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, see . (define (to-string-maybe x) (cond ;; In GNU make, "false" is the empty string ((or (not x) (unspecified? x) (variable? x) (null? x) (and (string? x) (string-null? x))) #f) ;; We want something not false... not sure about this ((eq? x #t) "#t") ;; Basics ((or (symbol? x) (number? x)) (object->string x)) ((char? x) (string x)) ;; Printable string (no special characters) ((and (string? x) (string-every char-set:printing x)) x) ;; No idea: fail (else (error "Unknown object:" x)))) (define (obj-to-str x) (let ((acc '())) (define (walk x) (cond ((pair? x) (walk (car x)) (walk (cdr x))) ((to-string-maybe x) => (lambda (s) (set! acc (cons s acc)))))) (walk x) (string-join (reverse! acc)))) ;; Return the value of the GNU make variable V (define (gmk-var v) (gmk-expand (format #f "$(~a)" (obj-to-str v)))) ;; Export the public interfaces (export gmk-expand gmk-eval gmk-var) kbuild-3686/src/kmk/os.h0000664000175000017500000000571115053010075015057 0ustar locutuslocutus/* Declarations for operating system interfaces for GNU Make. Copyright (C) 2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ /* This section provides OS-specific functions to support the jobserver. */ #ifdef MAKE_JOBSERVER /* Returns 1 if the jobserver is enabled, else 0. */ unsigned int jobserver_enabled (void); /* Called in the master instance to set up the jobserver initially. */ unsigned int jobserver_setup (int job_slots); /* Called in a child instance to connect to the jobserver. */ unsigned int jobserver_parse_auth (const char* auth); /* Returns an allocated buffer used to pass to child instances. */ char *jobserver_get_auth (void); /* Clear this instance's jobserver configuration. */ void jobserver_clear (void); /* Recover all the jobserver tokens and return the number we got. */ unsigned int jobserver_acquire_all (void); /* Release a jobserver token. If it fails and is_fatal is 1, fatal. */ void jobserver_release (int is_fatal); /* Notify the jobserver that a child exited. */ void jobserver_signal (void); /* Get ready to start a non-recursive child. */ void jobserver_pre_child (int); /* Complete starting a non-recursive child. */ void jobserver_post_child (int); /* Set up to acquire a new token. */ void jobserver_pre_acquire (void); /* Wait until we can acquire a jobserver token. TIMEOUT is 1 if we have other jobs waiting for the load to go down; in this case we won't wait forever, so we can check the load. Returns 1 if we got a token, or 0 if we stopped waiting due to a child exiting or a timeout. */ unsigned int jobserver_acquire (int timeout); #else #define jobserver_enabled() (0) #define jobserver_setup(_slots) (0) #define jobserver_parse_auth(_auth) (0) #define jobserver_get_auth() (NULL) #define jobserver_clear() (void)(0) #define jobserver_release(_fatal) (void)(0) #define jobserver_acquire_all() (0) #define jobserver_signal() (void)(0) #define jobserver_pre_child(_r) (void)(0) #define jobserver_post_child(_r) (void)(0) #define jobserver_pre_acquire() (void)(0) #define jobserver_acquire(_tmout) (0) #endif /* Create a "bad" file descriptor for stdin when parallel jobs are run. */ #if !defined(VMD) && !defined(WINDOWS32) && !defined(_AMIGA) && !defined(__MSDOS__) int get_bad_stdin (void); #else # define get_bad_stdin() (-1) #endif kbuild-3686/src/kmk/makefile.vms0000664000175000017500000001531615053010075016573 0ustar locutuslocutus# -*-Makefile-*- to build GNU make on VMS # # Copyright (C) 1996-2016 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) any later # version. # # GNU Make 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, see . # VMS extensions from GNU Make 3.60 imported by # Klaus Kämpf (kkaempf@rmi.de) # Modified for version 3.78.1 by Hartmut.Becker@compaq.com. # Modified for version 3.80 by zinser@decus.de # Modified for versions 3.81, 3.99.90 by Hartmut Becker CC = cc CP = copy %.obj: %.c $(CC) $(CFLAGS)/obj=$@ $< # # Makefile for GNU Make # ifeq ($(CC),cc) cinclude = /nested=none/include=([],[.glob]) cprefix = /prefix=(all,except=(glob,globfree)) cwarn = /standard=relaxed/warn=(disable=questcompare) CFLAGS = $(defines) $(cinclude)$(cprefix)$(cwarn) else CFLAGS = $(defines) $(cinclude) endif #LDFLAGS = /deb LDFLAGS = ifeq ($(CC),cc) defines = /define=("unlink=remove","HAVE_CONFIG_H","VMS","allocated_variable_expand_for_file=alloc_var_expand_for_file") else ifeq ($(ARCH),VAX) defines = /define=("HAVE_CONFIG_H","GCC_IS_NATIVE","VAX") else defines = /define=("HAVE_CONFIG_H","GCC_IS_NATIVE") endif endif LOAD_AVG = /define="NO_LDAV" # If you don't want archive support, comment these out. ARCHIVES = ,ar.obj,arscan.obj ARCHIVES_SRC = ar.c arscan.c # If your system needs extra libraries loaded in, define them here. # System V probably need -lPW for alloca. # if on vax, uncomment the following line #LOADLIBES = ,c.opt/opt ifeq ($(CC),cc) #LOADLIBES =,sys$$library:vaxcrtl.olb/lib CRT0 = else LOADLIBES =,gnu_cc_library:libgcc.olb/lib endif # If your system doesn't have alloca, or the one provided is bad, # get it from the Emacs distribution and define these. #ALLOCA = ,alloca.obj #ALLOCASRC = alloca.c # If there are remote execution facilities defined, # enable them with switches here (see remote-*.c). REMOTE = # Any extra object files your system needs. extras = ,signame.obj,remote-stub.obj,vmsfunctions.obj,vmsify.obj #,directory.obj # as an alternative: glob = ,[.glob]glob.obj,[.glob]fnmatch.obj getopt = ,getopt.obj,getopt1.obj # Directory to install 'make' in. bindir = [] # Directory to install the man page in. mandir = [] # Number to put on the man page filename. manext = 1 guile = ,guile.obj objs = commands.obj,job.obj,output.obj,dir.obj,file.obj,misc.obj,hash.obj,\ load.obj,main.obj,read.obj,remake.obj,rule.obj,implicit.obj,\ default.obj,variable.obj,expand.obj,function.obj,strcache.obj,\ vpath.obj,version.obj,vms_progname.obj,vms_exit.obj,\ vms_export_symbol.obj$(guile)$(ARCHIVES)$(extras)$(getopt)$(glob) srcs = commands.c job.c output.c dir.c file.c misc.c guile.c hash.c \ load.c main.c read.c remake.c rule.c implicit.c \ default.c variable.c expand.c function.c strcache.c \ vpath.c version.c vmsfunctions.c vmsify.c vms_progname.c vms_exit.c \ vms_export_symbol.c $(ARCHIVES_SRC) $(ALLOCASRC) \ commands.h dep.h filedef.h job.h output.h makeint.h rule.h variable.h .PHONY: all doc all: config.h make.exe doc: make.info make.dvi make.exe: $(objs) $(LD)$(LDFLAGS)/exe=$@ $^$(LOADLIBES)$(CRT0) .PHONY: clean realclean clean: -purge [...] -$(RM) make.exe;,*.obj; -$(RM) [.glob]*.obj; ar.obj: ar.c makeint.h config.h gnumake.h gettext.h filedef.h hash.h dep.h \ [.glob]fnmatch.h arscan.obj: arscan.c makeint.h config.h gnumake.h gettext.h commands.obj: commands.c makeint.h config.h gnumake.h gettext.h filedef.h \ hash.h dep.h variable.h job.h output.h commands.h default.obj: default.c makeint.h config.h gnumake.h gettext.h filedef.h \ hash.h variable.h rule.h dep.h job.h output.h commands.h dir.obj: dir.c makeint.h config.h gnumake.h gettext.h hash.h filedef.h \ dep.h [.glob]glob.h expand.obj: expand.c makeint.h config.h gnumake.h gettext.h filedef.h \ hash.h job.h output.h commands.h variable.h rule.h file.obj: file.c makeint.h config.h gnumake.h gettext.h filedef.h hash.h \ dep.h job.h output.h commands.h variable.h debug.h [.glob]fnmatch.obj: [.glob]fnmatch.c config.h [.glob]fnmatch.h function.obj: function.c makeint.h config.h gnumake.h gettext.h filedef.h \ hash.h variable.h dep.h job.h output.h commands.h debug.h getopt.obj: getopt.c config.h gettext.h getopt.h getopt1.obj: getopt1.c config.h getopt.h [.glob]glob.obj: [.glob]glob.c config.h [.glob]fnmatch.h [.glob]glob.h guile.obj: guile.c makeint.h config.h gnumake.h gettext.h hash.obj: hash.c makeint.h config.h gnumake.h gettext.h hash.h implicit.obj: implicit.c makeint.h config.h gnumake.h gettext.h filedef.h \ hash.h rule.h dep.h debug.h variable.h job.h output.h commands.h job.obj: job.c makeint.h config.h gnumake.h gettext.h job.h output.h debug.h \ filedef.h hash.h commands.h variable.h debug.h vmsjobs.c load.obj: load.c makeint.h config.h gnumake.h gettext.h main.obj: main.c makeint.h config.h gnumake.h gettext.h filedef.h hash.h \ dep.h variable.h job.h output.h commands.h rule.h debug.h getopt.h misc.obj: misc.c makeint.h config.h gnumake.h gettext.h filedef.h hash.h \ dep.h debug.h output.obj: output.c makeint.h config.h gnumake.h gettext.h job.h output.h read.obj: read.c makeint.h config.h gnumake.h gettext.h [.glob]glob.h \ filedef.h hash.h dep.h job.h output.h commands.h variable.h rule.h \ debug.h remake.obj: remake.c makeint.h config.h gnumake.h gettext.h filedef.h \ hash.h job.h output.h commands.h dep.h variable.h debug.h remote-stub.obj: remote-stub.c makeint.h config.h gnumake.h gettext.h \ filedef.h hash.h job.h output.h commands.h rule.obj: rule.c makeint.h config.h gnumake.h gettext.h filedef.h hash.h \ dep.h job.h output.h commands.h variable.h rule.h signame.obj: signame.c makeint.h config.h gnumake.h gettext.h strcache.obj: strcache.c makeint.h config.h gnumake.h gettext.h hash.h variable.obj: variable.c makeint.h config.h gnumake.h gettext.h filedef.h \ hash.h dep.h job.h output.h commands.h variable.h rule.h version.obj: version.c config.h vmsfunctions.obj: vmsfunctions.c makeint.h config.h gnumake.h gettext.h \ debug.h job.h output.h vmsdir.h vmsify.obj: vmsify.c vpath.obj: vpath.c makeint.h config.h gnumake.h gettext.h filedef.h hash.h \ variable.h vms_progname.obj: vms_progname.c vms_exit.obj: vms_exit.c vms_export_symbol.obj: vms_export_symbol.c config.h: config.h-vms $(CP) $< $@ kbuild-3686/src/kmk/prepare_vms.com0000664000175000017500000000353215053010075017307 0ustar locutuslocutus$! $! prepare_vms.com - Build config.h-vms from master on VMS. $! $! This is used for building off the master instead of a release tarball. $! $! $! $! First try ODS-5, Pathworks V6 or UNZIP name. $! $ config_template = f$search("sys$disk:[]config*h-vms.template") $ if config_template .eqs. "" $ then $! $! Try NFS, VMStar, or Pathworks V5 ODS-2 encoded name. $! $ config_template = f$search("sys$disk:[]config.h-vms*template") $ if config_template .eqs. "" $ then $ write sys$output "Could not find config.h-vms*template!" $ exit 44 $ endif $ endif $ config_template_file = f$parse(config_template,,,"name") $ config_template_type = f$parse(config_template,,,"type") $ config_template = "sys$disk:[]" + config_template_file + config_template_type $! $! $! Pull the package and version from configure.ac $! $ open/read ac_file sys$disk:[]configure.ac $ac_read_loop: $ read ac_file/end=ac_read_loop_end line_in $ key = f$extract(0, 7, line_in) $ if key .nes. "AC_INIT" then goto ac_read_loop $ package = f$element (1,"[",line_in) $ package = f$element (0,"]",package) $ version = f$element (2,"[",line_in) $ version = f$element (0,"]",version) $ac_read_loop_end: $ close ac_file $! $ if (package .eqs. "") .or. (version .eqs. "") $ then $ write sys$output "Unable to determine package and/or version!" $ exit 44 $ endif $! $! $ outfile = "sys$disk:[]config.h-vms" $! $! Note the pipe command is close to the length of 255, which is the $! maximum token length prior to VMS V8.2: $! %DCL-W-TKNOVF, command element is too long - shorten $ pipe (write sys$output "sub/%PACKAGE%/''package'/WHOLE/NOTYPE" ;- write sys$output "sub/%VERSION%/''version'/WHOLE/NOTYPE" ;- write sys$output "exit") |- edit/edt 'config_template'/out='outfile'/command=sys$pipe >nla0: $! $ write sys$output package, ", version: ", version, " prepared for VMS" kbuild-3686/src/kmk/makeint.h0000664000175000017500000010561115053010075016066 0ustar locutuslocutus/* Miscellaneous global declarations and portability cruft for GNU Make. Copyright (C) 1988-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ /* We use instead of "config.h" so that a compilation using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h (which it would do because makeint.h was found in $srcdir). */ #include #undef HAVE_CONFIG_H #define HAVE_CONFIG_H 1 #include /* bird */ /* Specify we want GNU source code. This must be defined before any system headers are included. */ #define _GNU_SOURCE 1 /* AIX requires this to be the first thing in the file. */ #if HAVE_ALLOCA_H # include #else # ifdef _AIX #pragma alloca # else # if !defined(__GNUC__) && !defined(WINDOWS32) # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #endif /* Disable assert() unless we're a maintainer. Some asserts are compute-intensive. */ #ifndef MAKE_MAINTAINER_MODE # define NDEBUG 1 #endif /* Include the externally-visible content. Be sure to use the local one, and not one installed on the system. Define GMK_BUILDING_MAKE for proper selection of dllexport/dllimport declarations for MS-Windows. */ #ifdef WINDOWS32 # define GMK_BUILDING_MAKE #endif #include "gnumake.h" #ifdef CRAY /* This must happen before #include so that the declaration therein is changed. */ # define signal bsdsignal #endif /* If we're compiling for the dmalloc debugger, turn off string inlining. */ #if defined(HAVE_DMALLOC_H) && defined(__GNUC__) # define __NO_STRING_INLINES #endif #include #include #include #include #include #ifdef HAVE_SYS_TIMEB_H /* SCO 3.2 "devsys 4.2" has a prototype for 'ftime' in that bombs unless has been included first. */ # include #endif #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include #ifndef errno extern int errno; #endif #ifdef __VMS /* In strict ANSI mode, VMS compilers should not be defining the VMS macro. Define it here instead of a bulk edit for the correct code. */ # ifndef VMS # define VMS # endif #endif #ifdef HAVE_UNISTD_H # include /* Ultrix's unistd.h always defines _POSIX_VERSION, but you only get POSIX.1 behavior with 'cc -YPOSIX', which predefines POSIX itself! */ # if defined (_POSIX_VERSION) && !defined (ultrix) && !defined (VMS) # define POSIX 1 # endif #endif /* Some systems define _POSIX_VERSION but are not really POSIX.1. */ #if (defined (butterfly) || defined (__arm) || (defined (__mips) && defined (_SYSTYPE_SVR3)) || (defined (sequent) && defined (i386))) # undef POSIX #endif #if !defined (POSIX) && defined (_AIX) && defined (_POSIX_SOURCE) # define POSIX 1 #endif #ifndef RETSIGTYPE # define RETSIGTYPE void #endif #ifndef sigmask # define sigmask(sig) (1 << ((sig) - 1)) #endif #ifndef HAVE_SA_RESTART # define SA_RESTART 0 #endif #ifdef HAVE_VFORK_H # include #endif #ifdef HAVE_LIMITS_H # include #endif #ifdef HAVE_SYS_PARAM_H # include #endif #ifndef PATH_MAX # ifndef POSIX # define PATH_MAX MAXPATHLEN # endif #endif #ifndef MAXPATHLEN # define MAXPATHLEN 1024 #endif #ifdef PATH_MAX # define GET_PATH_MAX PATH_MAX # define PATH_VAR(var) char var[PATH_MAX] #else # define NEED_GET_PATH_MAX 1 # define GET_PATH_MAX (get_path_max ()) # define PATH_VAR(var) char *var = alloca (GET_PATH_MAX) unsigned int get_path_max (void); #endif #if defined (KMK) || defined (CONFIG_WITH_VALUE_LENGTH) \ || defined (CONFIG_WITH_ALLOC_CACHES) \ || defined (CONFIG_WITH_STRCACHE2) # ifdef _MSC_VER # define MY_INLINE _inline static # elif defined(__GNUC__) # define MY_INLINE static __inline__ # else # define MY_INLINE static # endif # ifdef __GNUC__ # define MY_PREDICT_TRUE(expr) __builtin_expect(!!(expr), 1) # define MY_PREDICT_FALSE(expr) __builtin_expect(!!(expr), 0) # else # define MY_PREDICT_TRUE(expr) (expr) # define MY_PREDICT_FALSE(expr) (expr) # endif #endif #if defined (KMK) || defined (CONFIG_WITH_VALUE_LENGTH) \ || defined (CONFIG_WITH_STRCACHE2) # ifdef _MSC_VER # define MY_DBGBREAK __debugbreak() # elif defined(__GNUC__) # if defined(__i386__) || defined(__x86_64__) # define MY_DBGBREAK __asm__ __volatile__ ("int3") # else # define MY_DBGBREAK assert(0) # endif # else # define MY_DBGBREAK assert(0) # endif # ifndef NDEBUG # define MY_ASSERT_MSG(expr, printfargs) \ do { if (!(expr)) { printf printfargs; MY_DBGBREAK; } } while (0) # else # define MY_ASSERT_MSG(expr, printfargs) do { } while (0) # endif #endif #ifdef KMK /** @todo measure performance diff here! */ # if 0 /* See if this speeds things up (Windows is doing this anyway, so, we might as well try be consistent in speed + features). */ # define MY_IS_BLANK(ch) ((ch) == ' ' || (ch) == '\t') # define MY_IS_BLANK_OR_EOS(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\0') # else # define MY_IS_BLANK(ch) ISBLANK ((ch)) # define MY_IS_BLANK_OR_EOS(ch) (ISBLANK ((ch)) || (ch) == '\0') # endif #endif #ifdef CONFIG_WITH_MAKE_STATS extern long make_stats_allocations; extern long make_stats_reallocations; extern unsigned long make_stats_allocated; extern unsigned long make_stats_ht_lookups; extern unsigned long make_stats_ht_collisions; # ifdef __APPLE__ # include # define SIZE_OF_HEAP_BLOCK(ptr) malloc_size(ptr) # elif defined(__linux__) /* glibc */ # include # define SIZE_OF_HEAP_BLOCK(ptr) malloc_usable_size(ptr) # elif defined(_MSC_VER) || defined(__OS2__) # define SIZE_OF_HEAP_BLOCK(ptr) _msize(ptr) # else # include # define SIZE_OF_HEAP_BLOCK(ptr) 0 #endif # define MAKE_STATS_3(expr) do { expr; } while (0) # define MAKE_STATS_2(expr) do { expr; } while (0) # define MAKE_STATS(expr) do { expr; } while (0) #else # define MAKE_STATS_3(expr) do { } while (0) # define MAKE_STATS_2(expr) do { } while (0) # define MAKE_STATS(expr) do { } while (0) #endif /* bird - start */ #ifdef _MSC_VER # include # if defined(KBUILD_ARCH_ARM64) # define CURRENT_CLOCK_TICK() _ReadStatusReg(ARM64_SYSREG(3, 3, 14, 0, 2)) /*CNTCVT_EL0*/ # else # define CURRENT_CLOCK_TICK() __rdtsc() # endif #else # define CURRENT_CLOCK_TICK() 0 #endif #define COMMA , #ifdef CONFIG_WITH_VALUE_LENGTH # define IF_WITH_VALUE_LENGTH(a_Expr) a_Expr # define IF_WITH_VALUE_LENGTH_PARAM(a_Expr) , a_Expr #else # define IF_WITH_VALUE_LENGTH(a_Expr) # define IF_WITH_VALUE_LENGTH_PARAM(a_Expr) #endif #ifdef CONFIG_WITH_ALLOC_CACHES # define IF_WITH_ALLOC_CACHES(a_Expr) a_Expr # define IF_WITH_ALLOC_CACHES_PARAM(a_Expr) , a_Expr #else # define IF_WITH_ALLOC_CACHES(a_Expr) # define IF_WITH_ALLOC_CACHES_PARAM(a_Expr) #endif #ifdef CONFIG_WITH_COMMANDS_FUNC # define IF_WITH_COMMANDS_FUNC(a_Expr) a_Expr # define IF_WITH_COMMANDS_FUNC_PARAM(a_Expr) , a_Expr #else # define IF_WITH_COMMANDS_FUNC(a_Expr) # define IF_WITH_COMMANDS_FUNC_PARAM(a_Expr) #endif /* bird - end */ #ifndef CHAR_BIT # define CHAR_BIT 8 #endif #ifndef USHRT_MAX # define USHRT_MAX 65535 #endif /* Nonzero if the integer type T is signed. Use <= to avoid GCC warnings about always-false expressions. */ #define INTEGER_TYPE_SIGNED(t) ((t) -1 <= 0) /* The minimum and maximum values for the integer type T. Use ~ (t) 0, not -1, for portability to 1's complement hosts. */ #define INTEGER_TYPE_MINIMUM(t) \ (! INTEGER_TYPE_SIGNED (t) ? (t) 0 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)) #define INTEGER_TYPE_MAXIMUM(t) (~ (t) 0 - INTEGER_TYPE_MINIMUM (t)) #ifndef CHAR_MAX # define CHAR_MAX INTEGER_TYPE_MAXIMUM (char) #endif #ifdef STAT_MACROS_BROKEN # ifdef S_ISREG # undef S_ISREG # endif # ifdef S_ISDIR # undef S_ISDIR # endif #endif /* STAT_MACROS_BROKEN. */ #ifndef S_ISREG # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #endif #ifndef S_ISDIR # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #endif #ifdef VMS # include # include # include # include # include /* Needed to use alloca on VMS. */ # include extern int vms_use_mcr_command; extern int vms_always_use_cmd_file; extern int vms_gnv_shell; extern int vms_comma_separator; extern int vms_legacy_behavior; extern int vms_unix_simulation; #endif #ifndef __attribute__ /* This feature is available in gcc versions 2.5 and later. */ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ # define __attribute__(x) # endif /* The __-protected variants of 'format' and 'printf' attributes are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) # define __format__ format # define __printf__ printf # endif #endif #define UNUSED __attribute__ ((unused)) #if defined (STDC_HEADERS) || defined (__GNU_LIBRARY__) # include # include # define ANSI_STRING 1 #else /* No standard headers. */ # ifdef HAVE_STRING_H # include # define ANSI_STRING 1 # else # include # endif # ifdef HAVE_MEMORY_H # include # endif # ifdef HAVE_STDLIB_H # include # else void *malloc (int); void *realloc (void *, int); void free (void *); void abort (void) __attribute__ ((noreturn)); void exit (int) __attribute__ ((noreturn)); # endif /* HAVE_STDLIB_H. */ #endif /* Standard headers. */ /* These should be in stdlib.h. Make sure we have them. */ #ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE # define EXIT_FAILURE 1 #endif #ifndef ANSI_STRING /* SCO Xenix has a buggy macro definition in . */ #undef strerror #if !defined(__DECC) char *strerror (int errnum); #endif #endif /* !ANSI_STRING. */ #undef ANSI_STRING #if HAVE_INTTYPES_H # include #endif #if HAVE_STDINT_H # include #endif #define FILE_TIMESTAMP uintmax_t #if !defined(HAVE_STRSIGNAL) char *strsignal (int signum); #endif /* ISDIGIT offers the following features: - Its arg may be any int or unsigned int; it need not be an unsigned char. - It's guaranteed to evaluate its argument exactly once. NOTE! Make relies on this behavior, don't change it! - It's typically faster. POSIX 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that only '0' through '9' are digits. Prefer ISDIGIT to isdigit() unless it's important to use the locale's definition of 'digit' even when the host does not conform to POSIX. */ #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) /* Test if two strings are equal. Is this worthwhile? Should be profiled. */ #define streq(a, b) \ ((a) == (b) || \ (*(a) == *(b) && (*(a) == '\0' || !strcmp ((a) + 1, (b) + 1)))) /* Test if two strings are equal, but match case-insensitively on systems which have case-insensitive filesystems. Should only be used for filenames! */ #ifdef HAVE_CASE_INSENSITIVE_FS # define patheq(a, b) \ ((a) == (b) \ || (tolower((unsigned char)*(a)) == tolower((unsigned char)*(b)) \ && (*(a) == '\0' || !strcasecmp ((a) + 1, (b) + 1)))) #else # define patheq(a, b) streq(a, b) #endif #define strneq(a, b, l) (strncmp ((a), (b), (l)) == 0) #if (defined(__GNUC__) || defined(ENUM_BITFIELDS)) && !defined(NO_ENUM_BITFIELDS) /* bird: NO_ENUM_BITFIELDS */ # define ENUM_BITFIELD(bits) :bits #else # define ENUM_BITFIELD(bits) #endif /* Handle gettext and locales. */ #if HAVE_LOCALE_H # include #else # define setlocale(category, locale) #endif #include #define _(msgid) gettext (msgid) #define N_(msgid) gettext_noop (msgid) #define S_(msg1,msg2,num) ngettext (msg1,msg2,num) /* This is needed for getcwd() and chdir(), on some W32 systems. */ #if defined(HAVE_DIRECT_H) # include #endif #ifdef WINDOWS32 # include # include # define pipe(_p) _pipe((_p), 512, O_BINARY) # ifndef CONFIG_NEW_WIN_CHILDREN /* (only used by commands.c) */ # define kill(_pid,_sig) w32_kill((_pid),(_sig)) # endif /* MSVC and Watcom C don't have ftruncate. */ # if defined(_MSC_VER) || defined(__WATCOMC__) # define ftruncate(_fd,_len) _chsize(_fd,_len) # endif /* MinGW64 doesn't have _S_ISDIR. */ # ifndef _S_ISDIR # define _S_ISDIR(m) S_ISDIR(m) # endif void sync_Path_environment (void); # ifndef CONFIG_NEW_WIN_CHILDREN /* (only used by commands.c) */ int w32_kill (pid_t pid, int sig); # endif int find_and_set_default_shell (const char *token); /* indicates whether or not we have Bourne shell */ extern int no_default_sh_exe; /* is default_shell unixy? */ extern int unixy_shell; /* We don't have a preferred fixed value for LOCALEDIR. */ # ifndef LOCALEDIR # define LOCALEDIR NULL # endif /* Include only the minimal stuff from windows.h. */ # define WIN32_LEAN_AND_MEAN #endif /* WINDOWS32 */ #define ANY_SET(_v,_m) (((_v)&(_m)) != 0) #define NONE_SET(_v,_m) (! ANY_SET ((_v),(_m))) #define MAP_NUL 0x0001 #define MAP_BLANK 0x0002 #define MAP_NEWLINE 0x0004 #define MAP_COMMENT 0x0008 #define MAP_SEMI 0x0010 #define MAP_EQUALS 0x0020 #define MAP_COLON 0x0040 #define MAP_PERCENT 0x0080 #define MAP_PIPE 0x0100 #define MAP_DOT 0x0200 #define MAP_COMMA 0x0400 /* These are the valid characters for a user-defined function. */ #define MAP_USERFUNC 0x2000 /* This means not only a '$', but skip the variable reference. */ #define MAP_VARIABLE 0x4000 /* The set of characters which are directory separators is OS-specific. */ #define MAP_DIRSEP 0x8000 #ifdef VMS # define MAP_VMSCOMMA MAP_COMMA #else # define MAP_VMSCOMMA 0x0000 #endif #define MAP_SPACE (MAP_BLANK|MAP_NEWLINE) /* Handle other OSs. To overcome an issue parsing paths in a DOS/Windows environment when built in a unix based environment, override the PATH_SEPARATOR_CHAR definition unless being built for Cygwin. */ #if defined(HAVE_DOS_PATHS) && !defined(__CYGWIN__) # undef PATH_SEPARATOR_CHAR # define PATH_SEPARATOR_CHAR ';' # define MAP_PATHSEP MAP_SEMI #elif !defined(PATH_SEPARATOR_CHAR) # if defined (VMS) # define PATH_SEPARATOR_CHAR (vms_comma_separator ? ',' : ':') # define MAP_PATHSEP (vms_comma_separator ? MAP_COMMA : MAP_SEMI) # else # define PATH_SEPARATOR_CHAR ':' # define MAP_PATHSEP MAP_COLON # endif #elif PATH_SEPARATOR_CHAR == ':' # define MAP_PATHSEP MAP_COLON #elif PATH_SEPARATOR_CHAR == ';' # define MAP_PATHSEP MAP_SEMI #elif PATH_SEPARATOR_CHAR == ',' # define MAP_PATHSEP MAP_COMMA #else # error "Unknown PATH_SEPARATOR_CHAR" #endif #define STOP_SET(_v,_m) ANY_SET(stopchar_map[(unsigned char)(_v)],(_m)) #define ISBLANK(c) STOP_SET((c),MAP_BLANK) #define ISSPACE(c) STOP_SET((c),MAP_SPACE) #define NEXT_TOKEN(s) while (ISSPACE (*(s))) ++(s) #define END_OF_TOKEN(s) while (! STOP_SET (*(s), MAP_SPACE|MAP_NUL)) ++(s) #if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) # define SET_STACK_SIZE #endif #ifdef SET_STACK_SIZE # include extern struct rlimit stack_limit; #endif #include "glob.h" /* bird double quotes */ #define NILF ((floc *)0) #define CSTRLEN(_s) (sizeof (_s)-1) #define STRING_SIZE_TUPLE(_s) (_s), CSTRLEN(_s) /* The number of bytes needed to represent the largest integer as a string. */ #define INTSTR_LENGTH CSTRLEN ("18446744073709551616") #define DEFAULT_TTYNAME "true" #ifdef HAVE_TTYNAME # define TTYNAME(_f) ttyname (_f) #else # define TTYNAME(_f) DEFAULT_TTYNAME #endif /* Specify the location of elements read from makefiles. */ typedef struct { const char *filenm; unsigned long lineno; unsigned long offset; } floc; #if defined (CONFIG_WITH_MATH) /* bird start */ \ || defined (CONFIG_WITH_NANOTS) \ || defined (CONFIG_WITH_FILE_SIZE) \ || defined (CONFIG_WITH_PRINT_TIME_SWITCH) # ifdef _MSC_VER typedef __int64 big_int; # define BIG_INT_C(c) (c ## LL) typedef unsigned __int64 big_uint; # define BIG_UINT_C(c) (c ## ULL) # else # include typedef int64_t big_int; # define BIG_INT_C(c) INT64_C(c) typedef uint64_t big_uint; # define BIG_UINT_C(c) UINT64_C(c) # endif #endif /* bird end */ const char *concat (unsigned int, ...); void message (int prefix, size_t length, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 3, 4))); void error (const floc *flocp, size_t length, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 3, 4))); void fatal (const floc *flocp, size_t length, const char *fmt, ...) __attribute__ ((noreturn, __format__ (__printf__, 3, 4))); #define O(_t,_a,_f) _t((_a), 0, (_f)) #define OS(_t,_a,_f,_s) _t((_a), strlen (_s), (_f), (_s)) #define OSS(_t,_a,_f,_s1,_s2) _t((_a), strlen (_s1) + strlen (_s2), \ (_f), (_s1), (_s2)) #define OSSS(_t,_a,_f,_s1,_s2,_s3) _t((_a), strlen (_s1) + strlen (_s2) + strlen (_s3), \ (_f), (_s1), (_s2), (_s3)) #define ON(_t,_a,_f,_n) _t((_a), INTSTR_LENGTH, (_f), (_n)) #define ONN(_t,_a,_f,_n1,_n2) _t((_a), INTSTR_LENGTH*2, (_f), (_n1), (_n2)) #define OSN(_t,_a,_f,_s,_n) _t((_a), strlen (_s) + INTSTR_LENGTH, \ (_f), (_s), (_n)) #define ONS(_t,_a,_f,_n,_s) _t((_a), INTSTR_LENGTH + strlen (_s), \ (_f), (_n), (_s)) /* bird: more wrappers */ #define OSNN(_t,_a,_f,_s,_n1,_n2) _t((_a), strlen (_s) + INTSTR_LENGTH + INTSTR_LENGTH, \ (_f), (_s), (_n1), (_n2)) /* bird */ #define OSNS(_t,_a,_f,_s1,_n,_s2) _t((_a), strlen (_s1) + strlen (_s2) + INTSTR_LENGTH, \ (_f), (_s1), (_n), (_s2)) /* bird */ #define OSSSS(_t,_a,_f,_s1,_s2,_s3,_s4) _t((_a), strlen (_s1) + strlen (_s2) + strlen (_s3) + strlen (_s4), \ (_f), (_s1), (_s2), (_s3), (_s4)) /* bird */ #define OSSN(_t,_a,_f,_s1,_s2,_n) _t((_a), strlen (_s1) + strlen (_s2) + INTSTR_LENGTH, \ (_f), (_s1), (_s2), (_n)) /* bird */ #define OSSNS(_t,_a,_f,_s1,_s2,_n,_s3) _t((_a), strlen (_s1) + strlen (_s2) + strlen (_s3) + INTSTR_LENGTH, \ (_f), (_s1), (_s2), (_n), (_s3)) /* bird */ #define ONNS(_t,_a,_f,_n1,_n2,_s1) _t((_a), INTSTR_LENGTH * 2 + strlen (_s1), \ (_f), (_n1), (_n2), (_s1)) /* bird */ #define ONNNS(_t,_a,_f,_n1,_n2,_n3,_s1) _t((_a), INTSTR_LENGTH * 3 + strlen (_s1), \ (_f), (_n1), (_n2), (_n3), (_s1)) /* bird */ #define OUT_OF_MEM() O (fatal, NILF, _("virtual memory exhausted")) void die (int) __attribute__ ((noreturn)); struct output; void die_with_job_output (int, struct output *) __attribute__ ((noreturn)); void pfatal_with_name (const char *) __attribute__ ((noreturn)); void perror_with_name (const char *, const char *); #define xstrlen(_s) ((_s)==NULL ? 0 : strlen (_s)) void *xmalloc (unsigned int); void *xcalloc (unsigned int); void *xrealloc (void *, unsigned int); char *xstrdup (const char *); char *xstrndup (const char *, unsigned int); #ifdef CONFIG_WITH_PRINT_STATS_SWITCH void print_heap_stats (void); #endif char *find_next_token (const char **, unsigned int *); char *next_token (const char *); char *end_of_token (const char *); #ifdef KMK char *find_next_token_eos (const char **ptr, const char *eos, unsigned int *lengthptr); char *find_next_file_token (const char **ptr, const char *eos, unsigned int *lengthptr); #endif #ifndef CONFIG_WITH_VALUE_LENGTH void collapse_continuations (char *); #else char *collapse_continuations (char *, unsigned int); #endif #ifdef CONFIG_WITH_OPTIMIZATION_HACKS /* memchr is usually compiler intrinsic, thus faster. */ # define lindex(s, limit, c) ((char *)memchr((s), (c), (limit) - (s))) #else char *lindex (const char *, const char *, int); #endif int alpha_compare (const void *, const void *); void print_spaces (unsigned int); char *find_percent (char *); const char *find_percent_cached (const char **); #ifndef NO_ARCHIVES int ar_name (const char *); void ar_parse_name (const char *, char **, char **); int ar_touch (const char *); time_t ar_member_date (const char *); typedef long int (*ar_member_func_t) (int desc, const char *mem, int truncated, long int hdrpos, long int datapos, long int size, long int date, int uid, int gid, unsigned int mode, const void *arg); long int ar_scan (const char *archive, ar_member_func_t function, const void *arg); int ar_name_equal (const char *name, const char *mem, int truncated); #ifndef VMS int ar_member_touch (const char *arname, const char *memname); #endif #endif int dir_file_exists_p (const char *, const char *); int file_exists_p (const char *); int file_impossible_p (const char *); void file_impossible (const char *); const char *dir_name (const char *); void print_dir_data_base (void); void dir_setup_glob (glob_t *); void hash_init_directories (void); #if defined (KMK) && defined (KBUILD_OS_WINDOWS) int utf16_regular_file_p(const wchar_t *pwszPath); #endif void define_default_variables (void); void undefine_default_variables (void); void set_default_suffixes (void); void install_default_suffix_rules (void); void install_default_implicit_rules (void); void build_vpath_lists (void); void construct_vpath_list (char *pattern, char *dirpath); const char *vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr, unsigned int* vpath_index, unsigned int* path_index); int gpath_search (const char *file, unsigned int len); void construct_include_path (const char **arg_dirs); void user_access (void); void make_access (void); void child_access (void); char *strip_whitespace (const char **begpp, const char **endpp); void show_goal_error (void); #ifdef CONFIG_WITH_ALLOC_CACHES /* bird start */ /* alloccache (misc.c) */ struct alloccache_free_ent { struct alloccache_free_ent *next; }; struct alloccache { char *free_start; char *free_end; struct alloccache_free_ent *free_head; unsigned int size; unsigned int total_count; unsigned long alloc_count; unsigned long free_count; const char *name; struct alloccache *next; void *grow_arg; void *(*grow_alloc)(void *grow_arg, unsigned int size); }; void alloccache_init (struct alloccache *cache, unsigned int size, const char *name, void *(*grow_alloc)(void *grow_arg, unsigned int size), void *grow_arg); void alloccache_term (struct alloccache *cache, void (*term_free)(void *term_arg, void *ptr, unsigned int size), void *term_arg); void alloccache_join (struct alloccache *cache, struct alloccache *eat); void alloccache_print (struct alloccache *cache); void alloccache_print_all (void); struct alloccache_free_ent *alloccache_alloc_grow (struct alloccache *cache); void alloccache_free (struct alloccache *cache, void *item); /* Allocate an item. */ MY_INLINE void * alloccache_alloc (struct alloccache *cache) { struct alloccache_free_ent *f; # ifndef CONFIG_WITH_ALLOCCACHE_DEBUG f = cache->free_head; if (f) cache->free_head = f->next; else if (cache->free_start != cache->free_end) { f = (struct alloccache_free_ent *)cache->free_start; cache->free_start += cache->size; } else # endif f = alloccache_alloc_grow (cache); MAKE_STATS(cache->alloc_count++;); return f; } /* Allocate a cleared item. */ MY_INLINE void * alloccache_calloc (struct alloccache *cache) { void *item = alloccache_alloc (cache); memset (item, '\0', cache->size); return item; } /* the alloc caches */ extern struct alloccache dep_cache; extern struct alloccache goaldep_cache; extern struct alloccache nameseq_cache; extern struct alloccache file_cache; extern struct alloccache commands_cache; extern struct alloccache variable_cache; extern struct alloccache variable_set_cache; extern struct alloccache variable_set_list_cache; #endif /* CONFIG_WITH_ALLOC_CACHES - bird end*/ /* String caching */ void strcache_init (void); void strcache_print_stats (const char *prefix); #ifndef CONFIG_WITH_STRCACHE2 /* bird */ int strcache_iscached (const char *str); const char *strcache_add (const char *str); const char *strcache_add_len (const char *str, unsigned int len); #else /* CONFIG_WITH_STRCACHE2 */ # include "strcache2.h" extern struct strcache2 file_strcache; extern const char *suffixes_strcached; # define strcache_iscached(str) strcache2_is_cached(&file_strcache, str) # define strcache_add(str) strcache2_add_file(&file_strcache, str, strlen (str)) # define strcache_add_len(str, len) strcache2_add_file(&file_strcache, str, len) # define strcache_get_len(str) strcache2_get_len(&file_strcache, str) /* FIXME: replace this and related checks ... */ #endif /* CONFIG_WITH_STRCACHE2 */ /* Guile support */ int guile_gmake_setup (const floc *flocp); /* Loadable object support. Sets to the strcached name of the loaded file. */ typedef int (*load_func_t)(const floc *flocp); int load_file (const floc *flocp, const char **filename, int noerror); void unload_file (const char *name); /* We omit these declarations on non-POSIX systems which define _POSIX_VERSION, because such systems often declare them in header files anyway. */ #if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION) && !defined(WINDOWS32) long int atol (); # ifndef VMS long int lseek (); # endif # ifdef HAVE_GETCWD # if !defined(VMS) && !defined(__DECC) && !defined(_MSC_VER) /* bird: MSC */ char *getcwd (); # endif # else char *getwd (); # define getcwd(buf, len) getwd (buf) # endif #endif /* Not GNU C library or POSIX. */ #if !HAVE_STRCASECMP # if HAVE_STRICMP # define strcasecmp stricmp # elif HAVE_STRCMPI # define strcasecmp strcmpi # else /* Create our own, in misc.c */ int strcasecmp (const char *s1, const char *s2); # endif #endif #if !HAVE_STRNCASECMP # if HAVE_STRNICMP # define strncasecmp strnicmp # elif HAVE_STRNCMPI # define strncasecmp strncmpi # else /* Create our own, in misc.c */ int strncasecmp (const char *s1, const char *s2, int n); # endif #endif #define OUTPUT_SYNC_NONE 0 #define OUTPUT_SYNC_LINE 1 #define OUTPUT_SYNC_TARGET 2 #define OUTPUT_SYNC_RECURSE 3 #if !defined(_MSC_VER) /* bird */ /* Non-GNU systems may not declare this in unistd.h. */ extern char **environ; #endif extern const floc *reading_file; extern const floc **expanding_var; extern unsigned short stopchar_map[]; extern int just_print_flag, silent_flag, ignore_errors_flag, keep_going_flag; extern int print_data_base_flag, question_flag, touch_flag, always_make_flag; extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag; extern int print_version_flag, print_directory_flag, check_symlink_flag; extern int warn_undefined_variables_flag, trace_flag, posix_pedantic; extern int not_parallel, second_expansion, clock_skew_detected; extern int rebuilding_makefiles, one_shell, output_sync, verify_flag; #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION /* bird start */ extern int second_target_expansion; #endif #ifdef CONFIG_PRETTY_COMMAND_PRINTING extern int pretty_command_printing; #endif #ifdef CONFIG_WITH_PRINT_TIME_SWITCH extern int print_time_min, print_time_width; #endif #if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS) extern int make_expensive_statistics; #endif /* bird end */ extern const char *default_shell; /* can we run commands via 'sh -c xxx' or must we use batch files? */ extern int batch_mode_shell; /* Resetting the command script introduction prefix character. */ #define RECIPEPREFIX_NAME ".RECIPEPREFIX" #define RECIPEPREFIX_DEFAULT '\t' extern char cmd_prefix; extern unsigned int job_slots; #ifndef NO_FLOAT extern double max_load_average; #else extern int max_load_average; #endif #ifdef WINDOWS32 extern char *program; #else extern const char *program; #endif #ifdef VMS const char *vms_command (const char *argv0); const char *vms_progname (const char *argv0); void vms_exit (int); # define _exit(foo) vms_exit(foo) # define exit(foo) vms_exit(foo) extern char *program_name; void set_program_name (const char *arv0); int need_vms_symbol (void); int create_foreign_command (const char *command, const char *image); int vms_export_dcl_symbol (const char *name, const char *value); int vms_putenv_symbol (const char *string); void vms_restore_symbol (const char *string); #endif void remote_setup (void); void remote_cleanup (void); int start_remote_job_p (int); int start_remote_job (char **, char **, int, int *, int *, int *); int remote_status (int *, int *, int *, int); void block_remote_children (void); void unblock_remote_children (void); int remote_kill (int id, int sig); void print_variable_data_base (void); void print_vpath_data_base (void); extern char *starting_directory; extern unsigned int makelevel; extern char *version_string, *remote_description, *make_host; extern unsigned int commands_started; extern int handling_fatal_signal; #ifndef MIN #define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) #endif #ifndef MAX #define MAX(_a,_b) ((_a)>(_b)?(_a):(_b)) #endif #define MAKE_SUCCESS 0 #define MAKE_TROUBLE 1 #define MAKE_FAILURE 2 /* Set up heap debugging library dmalloc. */ #ifdef HAVE_DMALLOC_H #include #endif #ifndef initialize_main # ifdef __EMX__ # define initialize_main(pargc, pargv) \ { _wildcard(pargc, pargv); _response(pargc, pargv); } # else # define initialize_main(pargc, pargv) # endif #endif #ifdef __EMX__ # if !defined chdir # define chdir _chdir2 # endif # if !defined getcwd # define getcwd _getcwd2 # endif /* NO_CHDIR2 causes make not to use _chdir2() and _getcwd2() instead of chdir() and getcwd(). This avoids some error messages for the make testsuite but restricts the drive letter support. */ # ifdef NO_CHDIR2 # warning NO_CHDIR2: usage of drive letters restricted # undef chdir # undef getcwd # endif #endif #ifndef initialize_main # define initialize_main(pargc, pargv) #endif /* Some systems (like Solaris, PTX, etc.) do not support the SA_RESTART flag properly according to POSIX. So, we try to wrap common system calls with checks for EINTR. Note that there are still plenty of system calls that can fail with EINTR but this, reportedly, gets the vast majority of failure cases. If you still experience failures you'll need to either get a system where SA_RESTART works, or you need to avoid -j. */ #define EINTRLOOP(_v,_c) while (((_v)=_c)==-1 && errno==EINTR) /* While system calls that return integers are pretty consistent about returning -1 on failure and setting errno in that case, functions that return pointers are not always so well behaved. Sometimes they return NULL for expected behavior: one good example is readdir() which returns NULL at the end of the directory--and _doesn't_ reset errno. So, we have to do it ourselves here. */ #define ENULLLOOP(_v,_c) do { errno = 0; (_v) = _c; } \ while((_v)==0 && errno==EINTR) #if defined(__EMX__) && defined(CONFIG_WITH_OPTIMIZATION_HACKS) /* bird: saves 40-100ms on libc. */ static inline void *__my_rawmemchr (const void *__s, int __c); #undef strchr #define strchr(s, c) \ (__extension__ (__builtin_constant_p (c) \ ? ((c) == '\0' \ ? (char *) __my_rawmemchr ((s), (c)) \ : __my_strchr_c ((s), ((c) & 0xff) << 8)) \ : __my_strchr_g ((s), (c)))) static inline char *__my_strchr_c (const char *__s, int __c) { register unsigned long int __d0; register char *__res; __asm__ __volatile__ ("1:\n\t" "movb (%0),%%al\n\t" "cmpb %%ah,%%al\n\t" "je 2f\n\t" "leal 1(%0),%0\n\t" "testb %%al,%%al\n\t" "jne 1b\n\t" "xorl %0,%0\n" "2:" : "=r" (__res), "=&a" (__d0) : "0" (__s), "1" (__c), "m" ( *(struct { char __x[0xfffffff]; } *)__s) : "cc"); return __res; } static inline char *__my_strchr_g (__const char *__s, int __c) { register unsigned long int __d0; register char *__res; __asm__ __volatile__ ("movb %%al,%%ah\n" "1:\n\t" "movb (%0),%%al\n\t" "cmpb %%ah,%%al\n\t" "je 2f\n\t" "leal 1(%0),%0\n\t" "testb %%al,%%al\n\t" "jne 1b\n\t" "xorl %0,%0\n" "2:" : "=r" (__res), "=&a" (__d0) : "0" (__s), "1" (__c), "m" ( *(struct { char __x[0xfffffff]; } *)__s) : "cc"); return __res; } static inline void *__my_rawmemchr (const void *__s, int __c) { register unsigned long int __d0; register unsigned char *__res; __asm__ __volatile__ ("cld\n\t" "repne; scasb\n\t" : "=D" (__res), "=&c" (__d0) : "a" (__c), "0" (__s), "1" (0xffffffff), "m" ( *(struct { char __x[0xfffffff]; } *)__s) : "cc"); return __res - 1; } #undef memchr #define memchr(a,b,c) __my_memchr((a),(b),(c)) static inline void *__my_memchr (__const void *__s, int __c, size_t __n) { register unsigned long int __d0; register unsigned char *__res; if (__n == 0) return NULL; __asm__ __volatile__ ("repne; scasb\n\t" "je 1f\n\t" "movl $1,%0\n" "1:" : "=D" (__res), "=&c" (__d0) : "a" (__c), "0" (__s), "1" (__n), "m" ( *(struct { __extension__ char __x[__n]; } *)__s) : "cc"); return __res - 1; } #endif /* __EMX__ (bird) */ #ifdef CONFIG_WITH_IF_CONDITIONALS extern int expr_eval_if_conditionals(const char *line, const floc *flocp); extern char *expr_eval_to_string(char *o, const char *expr); #endif #ifdef KMK extern char *abspath(const char *name, char *apath); extern char *func_breakpoint(char *o, char **argv, const char *funcname); # ifdef KBUILD_OS_WINDOWS extern void dir_cache_invalid_after_job (void); extern void dir_cache_invalid_all (void); extern void dir_cache_invalid_all_and_close_dirs (int including_root); extern void dir_cache_invalid_missing (void); extern int dir_cache_volatile_dir (const char *dir); extern int dir_cache_deleted_directory(const char *pszDir); # endif #endif #if defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_PRINT_TIME_SWITCH) || defined(CONFIG_WITH_KMK_BUILTIN_STATS) /* misc.c */ extern big_int nano_timestamp (void); extern int format_elapsed_nano (char *buf, size_t size, big_int ts); #endif #ifdef KMK /* main.c */ extern mode_t g_fUMask; #endif kbuild-3686/src/kmk/inlined_memchr.h0000664000175000017500000001076315053010075017416 0ustar locutuslocutus#define _GNU_SOURCE 1 #include #ifdef _MSC_VER _inline void * #else static __inline__ void * #endif my_inline_memchr(const void *pv, int ch, register size_t cb) { register const unsigned int uch = (unsigned)ch; register const unsigned char *pb = (const unsigned char *)pv; #if 0 /* 8-byte loop unroll */ while (cb >= 8) { if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; if (pb[3] == uch) return (unsigned char *)pb + 3; if (pb[4] == uch) return (unsigned char *)pb + 4; if (pb[5] == uch) return (unsigned char *)pb + 5; if (pb[6] == uch) return (unsigned char *)pb + 6; if (pb[7] == uch) return (unsigned char *)pb + 7; cb -= 8; pb += 8; } switch (cb & 7) { case 0: break; case 1: if (*pb == uch) return (unsigned char *)pb; break; case 2: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; break; case 3: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; break; case 4: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; if (pb[3] == uch) return (unsigned char *)pb + 3; break; case 5: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; if (pb[3] == uch) return (unsigned char *)pb + 3; if (pb[4] == uch) return (unsigned char *)pb + 4; break; case 6: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; if (pb[3] == uch) return (unsigned char *)pb + 3; if (pb[4] == uch) return (unsigned char *)pb + 4; if (pb[5] == uch) return (unsigned char *)pb + 5; break; case 7: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; if (pb[3] == uch) return (unsigned char *)pb + 3; if (pb[4] == uch) return (unsigned char *)pb + 4; if (pb[5] == uch) return (unsigned char *)pb + 5; if (pb[6] == uch) return (unsigned char *)pb + 6; break; } #elif 1 /* 4 byte loop unroll */ while (cb >= 4) { if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; if (pb[3] == uch) return (unsigned char *)pb + 3; cb -= 4; pb += 4; } switch (cb & 3) { case 0: break; case 1: if (*pb == uch) return (unsigned char *)pb; break; case 2: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; break; case 3: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; break; } #else /* the basic loop */ while (cb > 0) { if (*pb == uch) return (void *)pb; cb--; pb++; } #endif return 0; } #define memchr my_inline_memchr kbuild-3686/src/kmk/strcache2.h0000664000175000017500000001560315053010075016315 0ustar locutuslocutus/* $Id: strcache2.h 3643 2024-11-02 23:40:44Z bird $ */ /** @file * strcache - New string cache. */ /* * Copyright (c) 2006-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ #ifndef ___strcache2_h #define ___strcache2_h #ifndef CHAR_BIT # error "include after make.h!" #endif #define STRCACHE2_USE_MASK 1 /* string cache memory segment. */ struct strcache2_seg { struct strcache2_seg *next; /* The next cache segment. */ char *start; /* The first byte in the segment. */ size_t size; /* The size of the segment. */ size_t avail; /* The number of available bytes. */ char *cursor; /* Allocation cursor. */ }; /* string cache hash table entry. */ struct strcache2_entry { struct strcache2_entry *next; /* Collision chain. */ void *user; unsigned int hash; unsigned int length; }; /* The entry alignment, cacheline size if it's known & sensible. On x86/AMD64 we assume a 64-byte cacheline size. As it is difficult to guess other right now, these default 16 chars as that shouldn't cause much trouble, even if it not the most optimial value. Override, or modify for other platforms. */ #ifndef STRCACHE2_ENTRY_ALIGN_SHIFT # if defined (__i386__) || defined(__x86_64__) # define STRCACHE2_ENTRY_ALIGN_SHIFT 6 # else # define STRCACHE2_ENTRY_ALIGN_SHIFT 4 # endif #endif #define STRCACHE2_ENTRY_ALIGNMENT (1 << STRCACHE2_ENTRY_ALIGN_SHIFT) struct strcache2 { struct strcache2_entry **hash_tab; /* The hash table. */ int case_insensitive; /* case insensitive or not. */ #ifdef STRCACHE2_USE_MASK unsigned int hash_mask; /* The AND mask matching hash_size.*/ #else unsigned int hash_div; /* The number (prime) to mod by. */ #endif unsigned long lookup_count; /* The number of lookups. */ unsigned long collision_1st_count; /* The number of 1st level collisions. */ unsigned long collision_2nd_count; /* The number of 2nd level collisions. */ unsigned long collision_3rd_count; /* The number of 3rd level collisions. */ unsigned int count; /* Number entries in the cache. */ unsigned int collision_count; /* Number of entries in chains. */ unsigned int rehash_count; /* When to rehash the table. */ unsigned int init_size; /* The initial hash table size. */ unsigned int hash_size; /* The hash table size. */ unsigned int def_seg_size; /* The default segment size. */ void *lock; /* The lock handle. */ struct strcache2_seg *seg_head; /* The memory segment list. */ struct strcache2 *next; /* The next string cache. */ const char *name; /* Cache name. */ }; void strcache2_init (struct strcache2 *cache, const char *name, unsigned int size, unsigned int def_seg_size, int case_insensitive, int thread_safe); void strcache2_term (struct strcache2 *cache); void strcache2_print_stats (struct strcache2 *cache, const char *prefix); void strcache2_print_stats_all (const char *prefix); const char *strcache2_add (struct strcache2 *cache, const char *str, unsigned int length); const char *strcache2_iadd (struct strcache2 *cache, const char *str, unsigned int length); const char *strcache2_add_hashed (struct strcache2 *cache, const char *str, unsigned int length, unsigned int hash); const char *strcache2_iadd_hashed (struct strcache2 *cache, const char *str, unsigned int length, unsigned int hash); const char *strcache2_lookup (struct strcache2 *cache, const char *str, unsigned int length); const char *strcache2_ilookup (struct strcache2 *cache, const char *str, unsigned int length); #ifdef HAVE_CASE_INSENSITIVE_FS # define strcache2_add_file strcache2_iadd # define strcache2_add_hashed_file strcache2_iadd_hashed # define strcache2_lookup_file strcache2_ilookup #else # define strcache2_add_file strcache2_add # define strcache2_add_hashed_file strcache2_add_hashed # define strcache2_lookup_file strcache2_lookup #endif int strcache2_is_cached (struct strcache2 *cache, const char *str); int strcache2_verify_entry (struct strcache2 *cache, const char *str); unsigned int strcache2_get_hash2_fallback (struct strcache2 *cache, const char *str); unsigned int strcache2_hash_str (const char *str, unsigned int length, unsigned int *hash2p); unsigned int strcache2_hash_istr (const char *str, unsigned int length, unsigned int *hash2p); /* Get the hash table entry pointer. */ MY_INLINE struct strcache2_entry const * strcache2_get_entry (struct strcache2 *cache, const char *str) { #ifndef NDEBUG strcache2_verify_entry (cache, str); #endif return (struct strcache2_entry const *)str - 1; } /* Get the string length. */ MY_INLINE unsigned int strcache2_get_len (struct strcache2 *cache, const char *str) { return strcache2_get_entry (cache, str)->length; } /* Get the first hash value for the string. */ MY_INLINE unsigned int strcache2_get_hash (struct strcache2 *cache, const char *str) { return strcache2_get_entry (cache, str)->hash; } /* Calc the pointer hash value for the string. This takes the string address, shift out the bits that are always zero due to alignment, and then returns the unsigned integer value of it. The results from using this is generally better than for any of the other hash values. It is also sligtly faster code as it does not involve any memory accesses, just a right SHIFT and an optional AND. */ MY_INLINE unsigned int strcache2_calc_ptr_hash (struct strcache2 *cache, const char *str) { (void)cache; return (unsigned int) ((size_t)str >> STRCACHE2_ENTRY_ALIGN_SHIFT); } /* Get the user value for the string. */ MY_INLINE void * strcache2_get_user_val (struct strcache2 *cache, const char *str) { return strcache2_get_entry (cache, str)->user; } /* Get the user value for the string. */ MY_INLINE void strcache2_set_user_val (struct strcache2 *cache, const char *str, void *value) { struct strcache2_entry *entry = (struct strcache2_entry *)str - 1; #ifndef NDEBUG strcache2_verify_entry (cache, str); #endif entry->user = value; } #endif kbuild-3686/src/kmk/subproc.bat0000664000175000017500000000161415053010075016430 0ustar locutuslocutus@echo off rem Copyright (C) 1996-2016 Free Software Foundation, Inc. rem This file is part of GNU Make. rem rem GNU Make is free software; you can redistribute it and/or modify it under rem the terms of the GNU General Public License as published by the Free rem Software Foundation; either version 3 of the License, or (at your option) rem any later version. rem rem GNU Make is distributed in the hope that it will be useful, but WITHOUT rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. rem more details. rem rem You should have received a copy of the GNU General Public License along rem with this program. If not, see . cd w32\subproc set MAKE=%2 set MAKEFILE=%1 if x%2 == x set MAKE=nmake %MAKE% /f %MAKEFILE% if ERRORLEVEL 1 exit /B cd ..\.. kbuild-3686/src/kmk/testcase/0000775000175000017500000000000015053010075016074 5ustar locutuslocutuskbuild-3686/src/kmk/testcase/testcase-export.kmk0000664000175000017500000000150415053010075021732 0ustar locutuslocutus var0 = value0 var1 = value1 var2 = value2 var3 = value3 var4 = value4 var5 = value5 var6 = value6 var7 = value7 var8 = value8 var9 = value9 varname1 = var1 varname2 = var2 varname3 = var3 varname4 = var4 varname5 = var5 varname5 = var5 varname6 = var6 varname7 = var7 varname8 = var8 varname9 = var9 export var0 var8 $(varname1) $(subst foo,var, foo2 ) export $(foreach x, 3 4 \ ,$(subst \ odd(, \ parenthesis parsing behaviour), dont-mind-this-type{ except if you put a ${dollar} in front of it, \ $(varname$(x)) \ )\ ) export ${foreach x, 5 \ ,${subst \ odd{, \ parenthesis parsing behaviour}, dont-mind-this-type( \ except if you put a $(dollar) in front of it; two dollars $$(does do the trick though, \ ${varname$x}} \ }\ } export $ ${varname6} export $(varname7$) all: kmk_ash -c "export | kmk_sed '/var/!d' kbuild-3686/src/kmk/configure.ac0000664000175000017500000004411515053010075016554 0ustar locutuslocutus# Process this file with autoconf to produce a configure script. # # Copyright (C) 1993-2016 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) any later # version. # # GNU Make 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, see . AC_INIT([GNU make],[4.2.1],[bug-make@gnu.org]) AC_PREREQ([2.69]) # Autoconf setup AC_CONFIG_AUX_DIR([config]) AC_CONFIG_SRCDIR([vpath.c]) AC_CONFIG_HEADERS([config.h]) # Automake setup # We have to enable "foreign" because ChangeLog is auto-generated # We cannot enable -Werror because gettext 0.18.1 has invalid content # When we update gettext to 0.18.3 or better we can add it again. # bird: Added subdir-objects AM_INIT_AUTOMAKE([1.15 foreign -Werror -Wall subdir-objects]) # Checks for programs. AC_USE_SYSTEM_EXTENSIONS AC_PROG_CC AC_PROG_INSTALL AC_PROG_RANLIB AC_PROG_CPP AC_CHECK_PROG([AR], [ar], [ar], [ar]) # Perl is needed for the test suite (only) AC_CHECK_PROG([PERL], [perl], [perl], [perl]) # Needed for w32/Makefile.am AM_PROG_AR # Specialized system macros AC_CANONICAL_HOST AC_AIX AC_ISC_POSIX AC_MINIX # Enable gettext, in "external" mode. # bird: causes trouble when it doesn't find 'po' in SUBDIRS, so skip it. #AM_GNU_GETTEXT_VERSION([0.19.4]) #AM_GNU_GETTEXT([external]) # This test must come as early as possible after the compiler configuration # tests, because the choice of the file model can (in principle) affect # whether functions and headers are available, whether they work, etc. AC_SYS_LARGEFILE # Checks for libraries. AC_SEARCH_LIBS([getpwnam], [sun]) # Checks for header files. AC_HEADER_STDC AC_HEADER_DIRENT AC_HEADER_STAT AC_HEADER_TIME AC_CHECK_HEADERS([stdlib.h locale.h unistd.h limits.h fcntl.h string.h \ memory.h sys/param.h sys/resource.h sys/time.h sys/timeb.h \ sys/select.h]) AM_PROG_CC_C_O AC_C_CONST AC_TYPE_SIGNAL AC_TYPE_UID_T AC_TYPE_PID_T AC_TYPE_OFF_T AC_TYPE_SIZE_T AC_TYPE_SSIZE_T AC_TYPE_UINTMAX_T # Find out whether our struct stat returns nanosecond resolution timestamps. AC_STRUCT_ST_MTIM_NSEC AC_STRUCT_ST_ATIM_NSEC AC_CACHE_CHECK([whether to use high resolution file timestamps], [make_cv_file_timestamp_hi_res], [ make_cv_file_timestamp_hi_res=no AS_IF([test "$ac_cv_struct_st_mtim_nsec" != no], [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if HAVE_INTTYPES_H # include #endif]], [[char a[0x7fffffff < (uintmax_t)-1 >> 30 ? 1 : -1];]])], [make_cv_file_timestamp_hi_res=yes]) ])]) AS_IF([test "$make_cv_file_timestamp_hi_res" = yes], [val=1], [val=0]) AC_DEFINE_UNQUOTED([FILE_TIMESTAMP_HI_RES], [$val], [Use high resolution file timestamps if nonzero.]) AS_IF([test "$make_cv_file_timestamp_hi_res" = yes], [ # Solaris 2.5.1 needs -lposix4 to get the clock_gettime function. # Solaris 7 prefers the library name -lrt to the obsolescent name -lposix4. AC_SEARCH_LIBS([clock_gettime], [rt posix4]) AS_IF([test "$ac_cv_search_clock_gettime" != no], [ AC_DEFINE([HAVE_CLOCK_GETTIME], [1], [Define to 1 if you have the clock_gettime function.]) ]) ]) # Check for DOS-style pathnames. pds_AC_DOS_PATHS # See if we have a standard version of gettimeofday(). Since actual # implementations can differ, just make sure we have the most common # one. AC_CACHE_CHECK([for standard gettimeofday], [ac_cv_func_gettimeofday], [ac_cv_func_gettimeofday=no AC_RUN_IFELSE([AC_LANG_SOURCE([[#include #include /* kmk/darwin: for exit */ int main () { struct timeval t; t.tv_sec = -1; t.tv_usec = -1; exit (gettimeofday (&t, 0) != 0 || t.tv_sec < 0 || t.tv_usec < 0); }]])], [ac_cv_func_gettimeofday=yes], [ac_cv_func_gettimeofday=no], [ac_cv_func_gettimeofday="no (cross-compiling)"])]) AS_IF([test "$ac_cv_func_gettimeofday" = yes], [ AC_DEFINE([HAVE_GETTIMEOFDAY], [1], [Define to 1 if you have a standard gettimeofday function]) ]) AC_CHECK_FUNCS([strdup strndup mkstemp mktemp fdopen fileno \ dup dup2 getcwd realpath sigsetmask sigaction \ getgroups seteuid setegid setlinebuf setreuid setregid \ getrlimit setrlimit setvbuf pipe strerror strsignal \ lstat readlink atexit isatty ttyname pselect]) # We need to check declarations, not just existence, because on Tru64 this # function is not declared without special flags, which themselves cause # other problems. We'll just use our own. AC_CHECK_DECLS([bsd_signal], [], [], [[#define _GNU_SOURCE 1 #include ]]) AC_FUNC_FORK AC_FUNC_SETVBUF_REVERSED # Rumor has it that strcasecmp lives in -lresolv on some odd systems. # It doesn't hurt much to use our own if we can't find it so I don't # make the effort here. AC_CHECK_FUNCS([strcasecmp strncasecmp strcmpi strncmpi stricmp strnicmp]) # strcoll() is used by the GNU glob library AC_FUNC_STRCOLL AC_FUNC_ALLOCA AC_FUNC_CLOSEDIR_VOID # bird: This guile detection does not work on rhel4. Disabled it all since we doesn't care about guile. ## See if the user wants to add (or not) GNU Guile support #PKG_PROG_PKG_CONFIG #AC_ARG_WITH([guile], [AS_HELP_STRING([--with-guile], # [Support GNU Guile for embedded scripting])]) # ## For some strange reason, at least on Ubuntu, each version of Guile ## comes with it's own PC file so we have to specify them as individual ## packages. Ugh. #AS_IF([test "x$with_guile" != xno], #[ PKG_CHECK_MODULES([GUILE], [guile-2.0], [have_guile=yes], # [PKG_CHECK_MODULES([GUILE], [guile-1.8], [have_guile=yes], # [have_guile=no])]) #]) # #AS_IF([test "$have_guile" = yes], # [AC_DEFINE([HAVE_GUILE], [1], [Embed GNU Guile support])]) # #AM_CONDITIONAL([HAVE_GUILE], [test "$have_guile" = yes]) AC_FUNC_GETLOADAVG # AC_FUNC_GETLOADAVG is documented to set the NLIST_STRUCT value, but it # doesn't. So, we will. AS_IF([test "$ac_cv_header_nlist_h" = yes], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct nlist nl; nl.n_name = "string"; return 0;]])], [make_cv_nlist_struct=yes], [make_cv_nlist_struct=no]) AS_IF([test "$make_cv_nlist_struct" = yes], [ AC_DEFINE([NLIST_STRUCT], [1], [Define to 1 if struct nlist.n_name is a pointer rather than an array.]) ]) ]) AC_CHECK_DECLS([sys_siglist, _sys_siglist, __sys_siglist], , , [AC_INCLUDES_DEFAULT #include /* NetBSD declares sys_siglist in unistd.h. */ #if HAVE_UNISTD_H # include #endif ]) # Check out the wait reality. AC_CHECK_HEADERS([sys/wait.h],[],[],[[#include ]]) AC_CHECK_FUNCS([waitpid wait3]) AC_CACHE_CHECK([for union wait], [make_cv_union_wait], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[union wait status; int pid; pid = wait (&status); #ifdef WEXITSTATUS /* Some POSIXoid systems have both the new-style macros and the old union wait type, and they do not work together. If union wait conflicts with WEXITSTATUS et al, we don't want to use it at all. */ if (WEXITSTATUS (status) != 0) pid = -1; #ifdef WTERMSIG /* If we have WEXITSTATUS and WTERMSIG, just use them on ints. */ -- blow chunks here -- #endif #endif #ifdef HAVE_WAITPID /* Make sure union wait works with waitpid. */ pid = waitpid (-1, &status, 0); #endif ]])], [make_cv_union_wait=yes], [make_cv_union_wait=no]) ]) AS_IF([test "$make_cv_union_wait" = yes], [ AC_DEFINE([HAVE_UNION_WAIT], [1], [Define to 1 if you have the 'union wait' type in .]) ]) # If we're building on Windows/DOS/OS/2, add some support for DOS drive specs. AS_IF([test "$PATH_SEPARATOR" = ';'], [ AC_DEFINE([HAVE_DOS_PATHS], [1], [Define to 1 if your system requires backslashes or drive specs in pathnames.]) ]) # See if the user wants to use pmake's "customs" distributed build capability AC_SUBST([REMOTE]) REMOTE=stub use_customs=false AC_ARG_WITH([customs], [AC_HELP_STRING([--with-customs=DIR], [enable remote jobs via Customs--see README.customs])], [ AS_CASE([$withval], [n|no], [:], [make_cppflags="$CPPFLAGS" AS_CASE([$withval], [y|ye|yes], [:], [CPPFLAGS="$CPPFLAGS -I$with_customs/include/customs" make_ldflags="$LDFLAGS -L$with_customs/lib"]) CF_NETLIBS AC_CHECK_HEADER([customs.h], [use_customs=true REMOTE=cstms LIBS="$LIBS -lcustoms" LDFLAGS="$make_ldflags"], [with_customs=no CPPFLAGS="$make_cppflags" make_badcust=yes]) ]) ]) # Tell automake about this, so it can include the right .c files. AM_CONDITIONAL([USE_CUSTOMS], [test "$use_customs" = true]) # See if the user asked to handle case insensitive file systems. AH_TEMPLATE([HAVE_CASE_INSENSITIVE_FS], [Use case insensitive file names]) AC_ARG_ENABLE([case-insensitive-file-system], AC_HELP_STRING([--enable-case-insensitive-file-system], [assume file systems are case insensitive]), [AS_IF([test "$enableval" = yes], [AC_DEFINE([HAVE_CASE_INSENSITIVE_FS])])]) # See if we can handle the job server feature, and if the user wants it. AC_ARG_ENABLE([job-server], AC_HELP_STRING([--disable-job-server], [disallow recursive make communication during -jN]), [make_cv_job_server="$enableval" user_job_server="$enableval"], [make_cv_job_server="yes"]) AS_IF([test "$ac_cv_func_waitpid" = no && test "$ac_cv_func_wait3" = no], [has_wait_nohang=no], [has_wait_nohang=yes]) AC_CACHE_CHECK([for SA_RESTART], [make_cv_sa_restart], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[return SA_RESTART;]])], [make_cv_sa_restart=yes], [make_cv_sa_restart=no])]) AS_IF([test "$make_cv_sa_restart" != no], [ AC_DEFINE([HAVE_SA_RESTART], [1], [Define to 1 if defines the SA_RESTART constant.]) ]) # Only allow jobserver on systems that support it AS_CASE([/$ac_cv_func_pipe/$ac_cv_func_sigaction/$make_cv_sa_restart/$has_wait_nohang/], [*/no/*], [make_cv_job_server=no]) # Also supported on OS2 and MinGW AS_CASE([$host_os], [os2*|mingw*], [make_cv_job_server=yes]) # If we support it and the user didn't disable it, build with jobserver AS_CASE([/$make_cv_job_server/$user_job_server/], [*/no/*], [: no jobserver], [AC_DEFINE(MAKE_JOBSERVER, 1, [Define to 1 to enable job server support in GNU make.]) ]) # If dl*() functions are supported we can enable the load operation AC_CHECK_DECLS([dlopen, dlsym, dlerror], [], [], [[#include ]]) AC_ARG_ENABLE([load], AC_HELP_STRING([--disable-load], [disable support for the 'load' operation]), [make_cv_load="$enableval" user_load="$enableval"], [make_cv_load="yes"]) AS_CASE([/$ac_cv_have_decl_dlopen/$ac_cv_have_decl_dlsym/$ac_cv_have_decl_dlerror/], [*/no/*], [make_cv_load=no]) # We might need -ldl AS_IF([test "$make_cv_load" = yes], [ AC_SEARCH_LIBS([dlopen], [dl], [], [make_cv_load=]) ]) AS_CASE([/$make_cv_load/$user_load/], [*/no/*], [make_cv_load=no], [AC_DEFINE(MAKE_LOAD, 1, [Define to 1 to enable 'load' support in GNU make.]) ]) # If we want load support, we might need to link with export-dynamic. # See if we can figure it out. Unfortunately this is very difficult. # For example passing -rdynamic to the SunPRO linker gives a warning # but succeeds and creates a shared object, not an executable! AS_IF([test "$make_cv_load" = yes], [ AC_MSG_CHECKING([If the linker accepts -Wl,--export-dynamic]) old_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -Wl,--export-dynamic" AC_LINK_IFELSE([AC_LANG_SOURCE([int main(){}])], [AC_MSG_RESULT([yes]) AC_SUBST([AM_LDFLAGS], [-Wl,--export-dynamic])], [AC_MSG_RESULT([no]) AC_MSG_CHECKING([If the linker accepts -rdynamic]) LDFLAGS="$old_LDFLAGS -rdynamic" AC_LINK_IFELSE([AC_LANG_SOURCE([int main(){}])], [AC_MSG_RESULT([yes]) AC_SUBST([AM_LDFLAGS], [-rdynamic])], [AC_MSG_RESULT([no])]) ]) LDFLAGS="$old_LDFLAGS" ]) # if we have both lstat() and readlink() then we can support symlink # timechecks. AS_IF([test "$ac_cv_func_lstat" = yes && test "$ac_cv_func_readlink" = yes], [ AC_DEFINE([MAKE_SYMLINKS], [1], [Define to 1 to enable symbolic link timestamp checking.]) ]) # Find the SCCS commands, so we can include them in our default rules. AC_CACHE_CHECK([for location of SCCS get command], [make_cv_path_sccs_get], [ AS_IF([test -f /usr/sccs/get], [make_cv_path_sccs_get=/usr/sccs/get], [make_cv_path_sccs_get=get]) ]) AC_DEFINE_UNQUOTED([SCCS_GET], ["$make_cv_path_sccs_get"], [Define to the name of the SCCS 'get' command.]) ac_clean_files="$ac_clean_files s.conftest conftoast" # Remove these later. AS_IF([(/usr/sccs/admin -n s.conftest || admin -n s.conftest) >/dev/null 2>&1 && test -f s.conftest], [ # We successfully created an SCCS file. AC_CACHE_CHECK([if SCCS get command understands -G], [make_cv_sys_get_minus_G], [AS_IF([$make_cv_path_sccs_get -Gconftoast s.conftest >/dev/null 2>&1 && test -f conftoast], [make_cv_sys_get_minus_G=yes], [make_cv_sys_get_minus_G=no]) ]) AS_IF([test "$make_cv_sys_get_minus_G" = yes], [AC_DEFINE([SCCS_GET_MINUS_G], [1], [Define to 1 if the SCCS 'get' command understands the '-G' option.]) ]) ]) rm -f s.conftest conftoast ## bird: always use our glob impl. Avoids trouble with newish glibc. # Check the system to see if it provides GNU glob. If not, use our # local version. #x# AC_CACHE_CHECK([if system libc has GNU glob], [make_cv_sys_gnu_glob], #x# [ AC_EGREP_CPP([gnu glob],[ #x# #include #x# #include #x# #include #x# #x# #define GLOB_INTERFACE_VERSION 1 #x# #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 #x# # include #x# # if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION #x# gnu glob #x# # endif #x# #endif], #x# [make_cv_sys_gnu_glob=yes], #x# [make_cv_sys_gnu_glob=no])]) #x# AS_IF([test "$make_cv_sys_gnu_glob" = no], AS_IF([test yes = yes], [ GLOBINC='-I$(srcdir)/glob' GLOBLIB=glob/libglob.a make_cv_sys_gnu_glob=no ]) AC_SUBST([GLOBINC]) AC_SUBST([GLOBLIB]) # Tell automake about this, so it can build the right .c files. AM_CONDITIONAL([USE_LOCAL_GLOB], [test "$make_cv_sys_gnu_glob" = no]) # Let the makefile know what our build host is AC_DEFINE_UNQUOTED([MAKE_HOST],["$host"],[Build host information.]) MAKE_HOST="$host" AC_SUBST([MAKE_HOST]) w32_target_env=no AM_CONDITIONAL([WINDOWSENV], [false]) AS_CASE([$host], [*-*-mingw32], [AM_CONDITIONAL([WINDOWSENV], [true]) w32_target_env=yes AC_DEFINE([WINDOWS32], [1], [Use platform specific coding]) AC_DEFINE([HAVE_DOS_PATHS], [1], [Use platform specific coding]) ]) AC_DEFINE_UNQUOTED([PATH_SEPARATOR_CHAR],['$PATH_SEPARATOR'], [Define to the character that separates directories in PATH.]) # Include the Maintainer's Makefile section, if it's here. MAINT_MAKEFILE=/dev/null AS_IF([test -r "$srcdir/maintMakefile"], [ MAINT_MAKEFILE="$srcdir/maintMakefile" ]) AC_SUBST_FILE([MAINT_MAKEFILE]) # Allow building with dmalloc AM_WITH_DMALLOC # Forcibly disable SET_MAKE. If it's set it breaks things like the test # scripts, etc. SET_MAKE= # Sanity check and inform the user of what we found AS_IF([test "x$make_badcust" = xyes], [ echo echo "WARNING: --with-customs specified but no customs.h could be found;" echo " disabling Customs support." echo ]) AS_CASE([$with_customs], [""|n|no|y|ye|yes], [:], [AS_IF([test -f "$with_customs/lib/libcustoms.a"], [:], [ echo echo "WARNING: '$with_customs/lib' does not appear to contain the" echo " Customs library. You must build and install Customs" echo " before compiling GNU make." echo ])]) AS_IF([test "x$has_wait_nohang" = xno], [ echo echo "WARNING: Your system has neither waitpid() nor wait3()." echo " Without one of these, signal handling is unreliable." echo " You should be aware that running GNU make with -j" echo " could result in erratic behavior." echo ]) AS_IF([test "x$make_cv_job_server" = xno && test "x$user_job_server" = xyes], [ echo echo "WARNING: Make job server requires a POSIX-ish system that" echo " supports the pipe(), sigaction(), and either" echo " waitpid() or wait3() functions. Your system doesn't" echo " appear to provide one or more of those." echo " Disabling job server support." echo ]) AS_IF([test "x$make_cv_load" = xno && test "x$user_load" = xyes], [ echo echo "WARNING: 'load' support requires a POSIX-ish system that" echo " supports the dlopen(), dlsym(), and dlerror() functions." echo " Your system doesn't appear to provide one or more of these." echo " Disabling 'load' support." echo ]) # Specify what files are to be created. # bird: Removed po/Makefile.in. #AC_CONFIG_FILES([Makefile glob/Makefile po/Makefile.in config/Makefile \ # doc/Makefile w32/Makefile tests/config-flags.pm]) AC_CONFIG_FILES([Makefile glob/Makefile config/Makefile \ doc/Makefile w32/Makefile tests/config-flags.pm]) # OK, do it! AC_OUTPUT # We only generate the build.sh if we have a build.sh.in; we won't have # one before we've created a distribution. AS_IF([test -f "$srcdir/build.sh.in"], [ ./config.status --file build.sh chmod +x build.sh ]) dnl Local Variables: dnl comment-start: "dnl " dnl comment-end: "" dnl comment-start-skip: "\\bdnl\\b\\s *" dnl compile-command: "make configure config.h.in" dnl End: kbuild-3686/src/kmk/makefile.com0000664000175000017500000001153415053010075016542 0ustar locutuslocutus$! $! Makefile.com - builds GNU Make for VMS $! $! P1 = LIST will provide compiler listings. $! P2 = DEBUG will build an image with debug information $! P3 = WALL will enable all warning messages (some are suppressed since $! one macro intentionally causes an error condition) $! $! In case of problems with the install you might contact me at $! zinser@decus.de (preferred) or zinser@sysdev.deutsche-boerse.com $ $! hb $! But don't ask Martin Zinser about the lines, I added/changed. $! In case of an error do some cleanup $ on error then $ goto cleanup $! in case somebody set up her/his own symbol for cc $ set symbol/scope=(nolocal,noglobal) $! $! Just some general constants... $! $ true = 1 $ false = 0 $ tmpnam = "temp_" + f$getjpi("","pid") $ tt = tmpnam + ".txt" $ tc = tmpnam + ".c" $! $! Look for the compiler used $! $ lval = "" $ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs."" $ then $ if f$trnlnm("SYS").eqs."" then def/nolog sys sys$library: $ ccopt = "" $ else $ ccopt = "/decc/prefix=(all,except=(globfree,glob))" $ if f$trnlnm("SYS").eqs."" $ then $ if f$trnlnm("DECC$LIBRARY_INCLUDE").nes."" $ then $ define sys decc$library_include: $ else $ if f$search("SYS$COMMON:[DECC$LIB.REFERENCE]DECC$RTLDEF.DIR").nes."" - then lval = "SYS$COMMON:[DECC$LIB.REFERENCE.DECC$RTLDEF]," $ if f$search("SYS$COMMON:[DECC$LIB.REFERENCE]SYS$STARLET_C.DIR").nes."" - then lval = lval+"SYS$COMMON:[DECC$LIB.REFERENCE.SYS$STARLET_C]," $ lval=lval+"SYS$LIBRARY:" $ define sys 'lval $ endif $ endif $ endif $! $! $ if (p1 .eqs. "LIST") $ then $ ccopt = ccopt + "/list/show=(expan,inclu)" $ endif $! $! Should we build a debug image $! $ if (p2.eqs."DEBUG") $ then $ ccopt = ccopt + "/noopt/debug" $ lopt = "/debug" $ else $ lopt = "" $ endif $! $! Do we want to see all warnings $! $ if (p3.nes."WALL") $ then $ gosub check_cc_qual $ endif $ filelist = "alloca ar arscan commands default dir expand file function " + - "guile hash implicit job load main misc read remake " + - "remote-stub rule output signame variable version " + - "vmsfunctions vmsify vpath vms_progname vms_exit " + - "vms_export_symbol [.glob]glob [.glob]fnmatch getopt1 " + - "getopt strcache" $! $ copy config.h-vms config.h $ n=0 $ open/write optf make.opt $ loop: $ cfile = f$elem(n," ",filelist) $ if cfile .eqs. " " then goto linkit $ write sys$output "Compiling ''cfile'..." $ call compileit 'cfile' $ n = n + 1 $ goto loop $ linkit: $ close optf $ link/exe=make make.opt/opt'lopt $ goto cleanup $ $ cleanup: $ if f$trnlnm("SYS").nes."" then $ deassign sys $ if f$trnlnm("OPTF").nes."" then $ close optf $ if f$search("make.opt").nes."" then $ del make.opt;* $ exit $! $!----------------------------------------------------------------------------- $! $! Check if this is a define relating to the properties of the C/C++ $! compiler $! $CHECK_CC_QUAL: $ open/write tmpc 'tc $ ccqual = "/warn=(disable=questcompare)" $ write tmpc "#include " $ write tmpc "unsigned int i = 1;" $ write tmpc "int main(){" $ write tmpc "if (i < 0){printf(""Mission impossible\n"");}}" $ close tmpc $ gosub cc_qual_check $ return $! $!----------------------------------------------------------------------------- $! $! Check for properties of C/C++ compiler $! $CC_QUAL_CHECK: $ cc_qual = false $ set message/nofac/noident/nosever/notext $ cc 'ccqual' 'tmpnam' $ if $status then cc_qual = true $ set message/fac/ident/sever/text $ delete/nolog 'tmpnam'.*;* $ if cc_qual then ccopt = ccopt + ccqual $ return $!----------------------------------------------------------------------------- $! $ compileit : subroutine $ ploc = f$locate("]",p1) $! filnam = p1 $ if ploc .lt. f$length(p1) $ then $ objdir = f$extract(0, ploc+1, p1) $ write optf p1 $ else $ objdir := [] $ write optf objdir+p1 $ endif $ cc'ccopt'/nested=none/include=([],[.glob])/obj='objdir' - /define=("allocated_variable_expand_for_file=alloc_var_expand_for_file",- "unlink=remove","HAVE_CONFIG_H","VMS") - 'p1' $ exit $ endsubroutine : compileit $! $!----------------------------------------------------------------------------- $!Copyright (C) 1996-2016 Free Software Foundation, Inc. $!This file is part of GNU Make. $! $!GNU Make 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 3 of the License, or (at your option) any later $!version. $! $!GNU Make 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, see . kbuild-3686/src/kmk/kmkbuiltin/0000775000175000017500000000000015053010075016432 5ustar locutuslocutuskbuild-3686/src/kmk/kmkbuiltin/rmdir.c0000664000175000017500000001755015053010075017723 0ustar locutuslocutus/*- * Copyright (c) 1992, 1993, 1994 * 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. * 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 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1992, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)rmdir.c 8.3 (Berkeley) 4/2/94"; #endif /* not lint */ #endif #if 0 #include __FBSDID("$FreeBSD: src/bin/rmdir/rmdir.c,v 1.20 2005/01/26 06:51:28 ssouhlal Exp $"); #endif /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #define FAKES_NO_GETOPT_H /* bird */ #include "config.h" #include "err.h" #include #include #include #include #include #ifdef HAVE_ALLOCA_H # include #endif #include "getopt_r.h" #include "kmkbuiltin.h" #ifdef _MSC_VER # include "mscfakes.h" #endif /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ typedef struct RMDIRINSTANCE { PKMKBUILTINCTX pCtx; int pflag; int vflag; int ignore_fail_on_non_empty; int ignore_fail_on_not_exist; } RMDIRINSTANCE; typedef RMDIRINSTANCE *PRMDIRINSTANCE; /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ static struct option long_options[] = { { "help", no_argument, 0, 262 }, { "ignore-fail-on-non-empty", no_argument, 0, 260 }, { "ignore-fail-on-not-exist", no_argument, 0, 261 }, { "parents", no_argument, 0, 'p' }, { "verbose", no_argument, 0, 'v' }, { "version", no_argument, 0, 263 }, { 0, 0, 0, 0 }, }; /********************************************************************************************************************************* * Internal Functions * *********************************************************************************************************************************/ #if !defined(KMK_BUILTIN_STANDALONE) && defined(KBUILD_OS_WINDOWS) extern int dir_cache_deleted_directory(const char *pszDir); #endif static int rm_path(PRMDIRINSTANCE, char *); static int usage(PKMKBUILTINCTX, int); int kmk_builtin_rmdir(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { RMDIRINSTANCE This; struct getopt_state_r gos; int ch, errors; /* Initialize global instance. */ This.pCtx = pCtx; This.ignore_fail_on_not_exist = 0; This.ignore_fail_on_non_empty = 0; This.vflag = 0; This.pflag = 0; getopt_initialize_r(&gos, argc, argv, "pv", long_options, envp, pCtx); while ((ch = getopt_long_r(&gos, NULL)) != -1) switch(ch) { case 'p': This.pflag = 1; break; case 'v': This.vflag = 1; break; case 260: This.ignore_fail_on_non_empty = 1; break; case 261: This.ignore_fail_on_not_exist = 1; break; case 262: usage(pCtx, 0); return 0; case 263: return kbuild_version(argv[0]); case '?': default: return usage(pCtx, 1); } argc -= gos.optind; argv += gos.optind; if (argc == 0) return /*usage(stderr)*/0; for (errors = 0; *argv; argv++) { if (rmdir(*argv) < 0) { if ( ( !This.ignore_fail_on_non_empty || (errno != ENOTEMPTY && errno != EPERM && errno != EACCES && errno != EINVAL && errno != EEXIST)) && ( !This.ignore_fail_on_not_exist || errno != ENOENT)) { warn(pCtx, "rmdir: %s", *argv); errors = 1; continue; } if (!This.ignore_fail_on_not_exist || errno != ENOENT) continue; /* (only ignored doesn't exist errors fall thru) */ } else { #if !defined(KMK_BUILTIN_STANDALONE) && defined(KBUILD_OS_WINDOWS) dir_cache_deleted_directory(*argv); #endif if (This.vflag) kmk_builtin_ctx_printf(pCtx, 0, "%s\n", *argv); } if (This.pflag) errors |= rm_path(&This, *argv); } return errors; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_rmdir", NULL }; return kmk_builtin_rmdir(argc, argv, envp, &Ctx); } #endif static int rm_path(PRMDIRINSTANCE pThis, char *path) { char *p; const size_t len = strlen(path); p = alloca(len + 1); path = memcpy(p, path, len + 1); #if defined(_MSC_VER) || defined(__EMX__) p = strchr(path, '\\'); while (p) { *p++ = '/'; p = strchr(p, '\\'); } #endif p = path + len; while (--p > path && *p == '/') ; *++p = '\0'; while ((p = strrchr(path, '/')) != NULL) { /* Delete trailing slashes. */ while (--p >= path && *p == '/') ; *++p = '\0'; if (p == path) break; #if defined(_MSC_VER) || defined(__EMX__) if (p[-1] == ':' && p - 2 == path) break; #endif if (rmdir(path) < 0) { if ( pThis->ignore_fail_on_non_empty && ( errno == ENOTEMPTY || errno == EPERM || errno == EACCES || errno == EINVAL || errno == EEXIST)) break; if (!pThis->ignore_fail_on_not_exist || errno != ENOENT) { warn(pThis->pCtx, "rmdir: %s", path); return (1); } } #if defined(KMK) && defined(KBUILD_OS_WINDOWS) else { dir_cache_deleted_directory(path); } #endif if (pThis->vflag) kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s\n", path); } return (0); } static int usage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s [-pv --ignore-fail-on-non-empty --ignore-fail-on-not-exist] directory ...\n" " or: %s --help\n" " or: %s --version\n", pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); return 1; } kbuild-3686/src/kmk/kmkbuiltin/cmp.c0000664000175000017500000001244515053010074017362 0ustar locutuslocutus/* $NetBSD: cmp.c,v 1.15 2006/01/19 20:44:57 garbled Exp $ */ /* * Copyright (c) 1987, 1990, 1993, 1994 * 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. 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. */ /*__COPYRIGHT("@(#) Copyright (c) 1987, 1990, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"); static char sccsid[] = "@(#)cmp.c 8.3 (Berkeley) 4/2/94"; __RCSID("$NetBSD: cmp.c,v 1.15 2006/01/19 20:44:57 garbled Exp $"); */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #define FAKES_NO_GETOPT_H /* bird */ #ifdef _MSC_VER # define MSC_DO_64_BIT_IO /* for correct off_t */ #endif #include "config.h" #include #include "err.h" #include #include #include #include #include #ifndef _MSC_VER # include #else # include "mscfakes.h" #endif #include "getopt_r.h" #include "kmkbuiltin.h" #include "cmp_extern.h" /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ static const struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; static int usage(PKMKBUILTINCTX pCtx, int is_err); int kmk_builtin_cmp(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { struct getopt_state_r gos; off_t skip1 = 0, skip2 = 0; int lflag = 0, sflag = 0; int ch; char *file1, *file2; getopt_initialize_r(&gos, argc, argv, "ls", long_options, envp, pCtx); while ((ch = getopt_long_r(&gos, NULL)) != -1) { switch (ch) { case 'l': /* print all differences */ lflag = 1; break; case 's': /* silent run */ sflag = 1; break; case 261: usage(pCtx, 0); return 0; case 262: return kbuild_version(argv[0]); case '?': default: return usage(pCtx, 1); } } argv += gos.optind; argc -= gos.optind; if (argc < 2 || argc > 4) return usage(pCtx, 1); file1 = argv[0]; file2 = argv[1]; if (argc > 2) { char *ep; errno = 0; skip1 = strtoll(argv[2], &ep, 0); if (errno || ep == argv[2]) return errx(pCtx, ERR_EXIT, "strtoll(%s,,) failed", argv[2]); if (argc == 4) { skip2 = strtoll(argv[3], &ep, 0); if (errno || ep == argv[3]) return errx(pCtx, ERR_EXIT, "strtoll(%s,,) failed", argv[3]); } } return cmp_file_and_file_ex(pCtx, file1, skip1, file2, skip2, sflag, lflag, 0); } static int usage(PKMKBUILTINCTX pCtx, int is_err) { kmk_builtin_ctx_printf(pCtx, is_err, "usage: %s [-l | -s] file1 file2 [skip1 [skip2]]\n" " or: %s --help\n" " or: %s --version\n", pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); return ERR_EXIT; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_cmp", NULL }; setlocale(LC_ALL, ""); return kmk_builtin_cmp(argc, argv, envp, &Ctx); } #endif kbuild-3686/src/kmk/kmkbuiltin/strmode.c0000664000175000017500000001021715053010074020253 0ustar locutuslocutus/* $NetBSD: strmode.c,v 1.16 2004/06/20 22:20:15 jmc Exp $ */ /*- * Copyright (c) 1990, 1993 * 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. 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. */ /*#include */ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)strmode.c 8.3 (Berkeley) 8/15/94"; #else __RCSID("$NetBSD: strmode.c,v 1.16 2004/06/20 22:20:15 jmc Exp $"); #endif #endif /* LIBC_SCCS and not lint */ #include "config.h" /*#include "namespace.h"*/ #include #include #include #ifndef _MSC_VER #include #else #include "mscfakes.h" #endif #ifndef _DIAGASSERT #define _DIAGASSERT assert #endif void bsd_strmode(mode, p) mode_t mode; char *p; { _DIAGASSERT(p != NULL); /* print type */ switch (mode & S_IFMT) { case S_IFDIR: /* directory */ *p++ = 'd'; break; case S_IFCHR: /* character special */ *p++ = 'c'; break; #ifdef S_IFBLK case S_IFBLK: /* block special */ *p++ = 'b'; break; #endif case S_IFREG: /* regular */ #ifdef S_ARCH2 if ((mode & S_ARCH2) != 0) { *p++ = 'A'; } else if ((mode & S_ARCH1) != 0) { *p++ = 'a'; } else { #endif *p++ = '-'; #ifdef S_ARCH2 } #endif break; #ifdef S_IFLNK case S_IFLNK: /* symbolic link */ *p++ = 'l'; break; #endif #ifdef S_IFSOCK case S_IFSOCK: /* socket */ *p++ = 's'; break; #endif #ifdef S_IFIFO case S_IFIFO: /* fifo */ *p++ = 'p'; break; #endif #ifdef S_IFWHT case S_IFWHT: /* whiteout */ *p++ = 'w'; break; #endif #ifdef S_IFDOOR case S_IFDOOR: /* door */ *p++ = 'D'; break; #endif default: /* unknown */ *p++ = '?'; break; } /* usr */ if (mode & S_IRUSR) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWUSR) *p++ = 'w'; else *p++ = '-'; switch (mode & (S_IXUSR | S_ISUID)) { case 0: *p++ = '-'; break; case S_IXUSR: *p++ = 'x'; break; case S_ISUID: *p++ = 'S'; break; case S_IXUSR | S_ISUID: *p++ = 's'; break; } /* group */ if (mode & S_IRGRP) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWGRP) *p++ = 'w'; else *p++ = '-'; switch (mode & (S_IXGRP | S_ISGID)) { case 0: *p++ = '-'; break; case S_IXGRP: *p++ = 'x'; break; case S_ISGID: *p++ = 'S'; break; case S_IXGRP | S_ISGID: *p++ = 's'; break; } /* other */ if (mode & S_IROTH) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWOTH) *p++ = 'w'; else *p++ = '-'; #ifdef S_ISVTX switch (mode & (S_IXOTH | S_ISVTX)) { #else switch (mode & (S_IXOTH)) { #endif case 0: *p++ = '-'; break; case S_IXOTH: *p++ = 'x'; break; #ifdef S_ISVTX case S_ISVTX: *p++ = 'T'; break; case S_IXOTH | S_ISVTX: *p++ = 't'; break; #endif } *p++ = ' '; /* will be a '+' if ACL's implemented */ *p = '\0'; } kbuild-3686/src/kmk/kmkbuiltin/kill.c0000664000175000017500000005216415053010074017540 0ustar locutuslocutus/* $Id: kill.c 3352 2020-06-05 00:31:50Z bird $ */ /** @file * kmk kill - Process killer. */ /* * Copyright (c) 2007-2020 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include #include #include #include #ifdef WINDOWS32 # include # include # include #endif #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "err.h" #include "kmkbuiltin.h" /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ /** @name kmkKillMatchName flags * @{ */ #define KMKKILL_FN_EXE_SUFF 1 #define KMKKILL_FN_WILDCARD 2 #define KMKKILL_FN_WITH_PATH 4 #define KMKKILL_FN_ROOT_SLASH 8 /** @} */ /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ typedef struct KMKKILLGLOBALS { PKMKBUILTINCTX pCtx; int cVerbosity; const char *pszCur; } KMKKILLGLOBALS; /** * Kill one process by it's PID. * * The name is optional and only for messaging. */ static int kmkKillProcessByPid(KMKKILLGLOBALS *pThis, pid_t pid, const char *pszName) { int rcExit; HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE /*bInherit*/, pid); if (!hProcess) rcExit = errx(pThis->pCtx, 1, "Failed to open pid %u (%#x%s%s): %u", pid, pid, pszName ? ", " : "", pszName ? pszName : "", GetLastError()); else { if (!TerminateProcess(hProcess, DBG_TERMINATE_PROCESS)) rcExit = errx(pThis->pCtx, 1, "TerminateProcess failed on pid %u (%#x%s%s): %u", pid, pid, pszName ? ", " : "", pszName ? pszName : "", GetLastError()); else if (pThis->cVerbosity > 0) kmk_builtin_ctx_printf(pThis->pCtx, 0, "Terminated %u (%#x)%s%s\n", pid, pid, pszName ? " - " : "", pszName ? pszName : ""); CloseHandle(hProcess); } return rcExit; } /** * Does simple wilcard filename matching. * * @returns 1 on match, 0 on mismatch. * @param pszPattern The pattern. * @param cchPattern The length of the pattern. * @param pchFilename The filename to match. This does not have to be * terminated at @a cchFilename. * @param cchFilename The length of the filename that we should match. * @param cDepth The recursion depth. */ static int kmkKillMatchWildcard(const char *pszPattern, size_t cchPattern, const char *pchFilename, size_t cchFilename, unsigned cDepth) { while (cchPattern > 0 && cchFilename > 0) { char chPat = *pszPattern++; cchPattern--; if (chPat != '*') { if (chPat != '?') { char chExe = *pchFilename; if ( chExe != chPat && tolower(chExe) != tolower(chPat)) return 0; } pchFilename++; cchFilename--; } else { size_t off, cchExeMin; while (cchPattern > 0 && *pszPattern == '*') { pszPattern++; cchPattern--; } /* Trailing '*'? */ if (!cchPattern) return 1; /* Final wildcard? Match the tail. */ if (memchr(pszPattern, '*', cchPattern) == NULL) { if (memchr(pszPattern, '?', cchPattern) == NULL) return cchFilename >= cchPattern && strnicmp(&pchFilename[cchFilename - cchPattern], pszPattern, cchPattern) == 0; /* Only '?', so we know the exact length of this '*' match and can do a single tail matching. */ return cchFilename >= cchPattern && kmkKillMatchWildcard(pszPattern, cchPattern, &pchFilename[cchFilename - cchPattern], cchPattern, cDepth + 1); } /* * More wildcards ('*'), so we need to need to try out all matching * length for this one. We start by counting non-asterisks chars * in the remaining pattern so we know when to stop trying. * This must be at least 1 char. */ if (cDepth >= 32) return 0; for (off = cchExeMin = 0; off < cchPattern; off++) cchExeMin += pszPattern[off] != '*'; assert(cchExeMin > 0); while (cchFilename >= cchExeMin) { if (kmkKillMatchWildcard(pszPattern, cchPattern, pchFilename, cchFilename, cDepth + 1)) return 1; /* next */ pchFilename++; cchFilename--; } return 0; } } /* If there is more filename left, we won't have a match. */ if (cchFilename != 0) return 0; /* If there is pattern left, we still have a match if it's all asterisks. */ while (cchPattern > 0 && *pszPattern == '*') { pszPattern++; cchPattern--; } return cchPattern == 0; } /** * Matches a process name against the given pattern. * * @returns 1 if it matches, 0 if it doesn't. * @param pszPattern The pattern to match against. * @param cchPattern The pattern length. * @param fPattern Pattern characteristics. * @param pszExeFile The EXE filename to match (includes path). * @param cchExeFile The length of the EXE filename. */ static int kmkKillMatchName(const char *pszPattern, size_t cchPattern, unsigned fPattern, const char *pszExeFile, size_t cchExeFile) { /* * Automatically match the exe suffix if not present in the pattern. */ if ( !(fPattern & KMKKILL_FN_EXE_SUFF) && cchExeFile > 4 && stricmp(&pszExeFile[cchExeFile - 4], ".exe") == 0) cchExeFile -= sizeof(".exe") - 1; /* * If no path in the pattern, move pszExeFile up to the filename part. */ if (!(fPattern & KMKKILL_FN_WITH_PATH) && ( memchr(pszExeFile, '\\', cchExeFile) != NULL || memchr(pszExeFile, '/', cchExeFile) != NULL || memchr(pszExeFile, ':', cchExeFile) != NULL)) { size_t offFilename = cchExeFile; char ch; while ( offFilename > 0 && (ch = pszExeFile[offFilename - 1]) != '\\' && ch != '//' && ch != ':') offFilename--; cchExeFile -= offFilename; pszExeFile += offFilename; } /* * Wildcard? This only works for the filename part. */ if (fPattern & KMKKILL_FN_WILDCARD) return kmkKillMatchWildcard(pszPattern, cchPattern, pszExeFile, cchExeFile, 0); /* * No-wildcard pattern. */ if (cchExeFile >= cchPattern) { if (strnicmp(&pszExeFile[cchExeFile - cchPattern], pszPattern, cchPattern) == 0) return cchExeFile == cchPattern || (fPattern & KMKKILL_FN_ROOT_SLASH) || pszExeFile[cchExeFile - cchPattern - 1] == '\\' || pszExeFile[cchExeFile - cchPattern - 1] == '/' || pszExeFile[cchExeFile - cchPattern - 1] == ':'; /* * Might be slash directions or multiple consequtive slashes * making a difference here, so compare char-by-char from the end. */ if (fPattern & KMKKILL_FN_WITH_PATH) { while (cchPattern > 0 && cchExeFile > 0) { char chPat = pszPattern[--cchPattern]; char chExe = pszExeFile[--cchExeFile]; if (chPat == chExe) { if (chPat != '\\' && chPat != '/') { if (chPat != ':' || cchPattern > 0) continue; return 1; } } else { chPat = tolower(chPat); chExe = tolower(chExe); if (chPat == chExe) continue; if (chPat == '/') chPat = '\\'; if (chExe == '/') chExe = '\\'; if (chPat != chExe) return 0; } while (cchPattern > 0 && ((chPat = pszPattern[cchPattern - 1] == '\\') || chPat == '/')) cchPattern--; if (!cchPattern) return 1; while (cchExeFile > 0 && ((chExe = pszExeFile[cchExeFile - 1] == '\\') || chExe == '/')) cchExeFile--; } if ( cchExeFile == 0 || pszExeFile[cchExeFile - 1] == '\\' || pszExeFile[cchExeFile - 1] == '/' || pszExeFile[cchExeFile - 1] == ':') return 1; } } return 0; } /** * Analyzes pattern for kmkKillMatchName(). * * @returns Pattern characteristics. * @param pszPattern The pattern. * @param cchPattern The pattern length. */ static unsigned kmkKillAnalyzePattern(const char *pszPattern, size_t cchPattern) { unsigned fPattern = 0; if (cchPattern > 4 && stricmp(&pszPattern[cchPattern - 4], ".exe") == 0) fPattern |= KMKKILL_FN_EXE_SUFF; if (memchr(pszPattern, '*', cchPattern) != NULL) fPattern |= KMKKILL_FN_WILDCARD; if (memchr(pszPattern, '?', cchPattern) != NULL) fPattern |= KMKKILL_FN_WILDCARD; if (memchr(pszPattern, '/', cchPattern) != NULL) fPattern |= KMKKILL_FN_WITH_PATH; if (memchr(pszPattern, '\\', cchPattern) != NULL) fPattern |= KMKKILL_FN_WITH_PATH; if (*pszPattern == '\\' || *pszPattern == '/') fPattern |= KMKKILL_FN_ROOT_SLASH; return fPattern; } /** * Enumerate processes and kill the ones matching the pattern. */ static int kmkKillProcessByName(KMKKILLGLOBALS *pThis, const char *pszPattern) { HANDLE hSnapshot; int rcExit = 0; size_t const cchPattern = strlen(pszPattern); unsigned const fPattern = kmkKillAnalyzePattern(pszPattern, cchPattern); if (cchPattern == 0) return errx(pThis->pCtx, 1, "Empty process name!"); if ((fPattern & (KMKKILL_FN_WILDCARD | KMKKILL_FN_WITH_PATH)) == (KMKKILL_FN_WILDCARD | KMKKILL_FN_WITH_PATH)) return errx(pThis->pCtx, 1, "Wildcard and paths cannot be mixed: %s", pszPattern); hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (!hSnapshot) rcExit = errx(pThis->pCtx, 1, "CreateToolhelp32Snapshot failed: %d", GetLastError()); else { union { PROCESSENTRY32 Entry; char achBuf[8192]; } u; memset(&u, 0, sizeof(u)); u.Entry.dwSize = sizeof(u) - sizeof(".exe"); SetLastError(NO_ERROR); if (Process32First(hSnapshot, &u.Entry)) { for (;;) { /* Kill it if it matches. */ u.achBuf[sizeof(u.achBuf) - sizeof(".exe")] = '\0'; if ( u.Entry.szExeFile[0] != '\0' && kmkKillMatchName(pszPattern, cchPattern, fPattern, u.Entry.szExeFile, strlen(u.Entry.szExeFile))) { int rcExit2 = kmkKillProcessByPid(pThis, u.Entry.th32ProcessID, u.Entry.szExeFile); if (rcExit2 != 0 && rcExit == 0) rcExit = rcExit2; } /* next */ u.Entry.dwSize = sizeof(u) - sizeof(".exe"); SetLastError(NO_ERROR); if (!Process32Next(hSnapshot, &u.Entry)) { if (GetLastError() != ERROR_NO_MORE_FILES) rcExit = errx(pThis->pCtx, 1, "Process32Next failed: %d", GetLastError()); break; } } } else rcExit = errx(pThis->pCtx, 1, "Process32First failed: %d", GetLastError()); CloseHandle(hSnapshot); } return rcExit; } /** * Worker for handling one command line process target. * * @returns 0 on success, non-zero exit code on failure. */ static int kmkKillProcess(KMKKILLGLOBALS *pThis, const char *pszTarget) { /* * Try treat the target as a pid first, then a name pattern. */ char *pszNext = NULL; long pid; errno = 0; pid = strtol(pszTarget, &pszNext, 0); if (pszNext && *pszNext == '\0' && errno == 0) return kmkKillProcessByPid(pThis, pid, NULL); return kmkKillProcessByName(pThis, pszTarget); } /** * Worker for handling one command line job target. * * @returns 0 on success, non-zero exit code on failure. */ static int kmkKillJob(KMKKILLGLOBALS *pThis, const char *pszTarget) { int rcExit = 0; HANDLE hTempJob = NULL; BOOL fIsInJob = FALSE; /* * Open the job object. */ DWORD fRights = JOB_OBJECT_QUERY | JOB_OBJECT_TERMINATE | JOB_OBJECT_ASSIGN_PROCESS; HANDLE hJob = OpenJobObjectA(fRights, FALSE /*bInheritHandle*/, pszTarget); if (!hJob) { fRights &= ~JOB_OBJECT_ASSIGN_PROCESS; hJob = OpenJobObjectA(fRights, FALSE /*bInheritHandle*/, pszTarget); if (!hJob) return errx(pThis->pCtx, 1, "Failed to open job '%s': %u", pszTarget, GetLastError()); } /* * Are we a member of this job? If so, temporarily move * to a different object so we don't kill ourselves. */ if (IsProcessInJob(hJob, GetCurrentProcess(), &fIsInJob)) { if (fIsInJob) { /** @todo this probably isn't working. */ if (pThis->cVerbosity >= 1) kmk_builtin_ctx_printf(pThis->pCtx, 0, "kmk_kill: Is myself (%u) a member of target job (%s)", getpid(), pszTarget); if (!(fRights & JOB_OBJECT_ASSIGN_PROCESS)) rcExit = errx(pThis->pCtx, 1, "Is myself member of the target job and don't have the JOB_OBJECT_ASSIGN_PROCESS right."); else { hTempJob = CreateJobObjectA(NULL, NULL); if (hTempJob) { if (!(AssignProcessToJobObject(hTempJob, GetCurrentProcess()))) rcExit = errx(pThis->pCtx, 1, "AssignProcessToJobObject(temp, me) failed: %u", GetLastError()); } } } } else rcExit = errx(pThis->pCtx, 1, "IsProcessInJob(%s, me) failed: %u", pszTarget, GetLastError()); /* * Do the killing. */ if (rcExit == 0) { if (!TerminateJobObject(hJob, DBG_TERMINATE_PROCESS)) rcExit = errx(pThis->pCtx, 1, "TerminateJobObject(%s) failed: %u", pszTarget, GetLastError()); } /* * Cleanup. */ if (hTempJob) { if (!(AssignProcessToJobObject(hJob, GetCurrentProcess()))) rcExit = errx(pThis->pCtx, 1, "AssignProcessToJobObject(%s, me) failed: %u", pszTarget, GetLastError()); CloseHandle(hTempJob); } CloseHandle(hJob); return rcExit; } /** * Show usage. */ static void kmkKillUsage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s [options] [options] [...]\n" " or: %s --help\n" " or: %s --version\n" "\n" "Options that decide what to kill next:\n" " -p|--process Processes, either by name or by PID. (default)\n" " -j|--job Windows jobs.\n" "\n" "Other options:\n" " -q|--quiet Quiet operation. Only real errors are displayed.\n" " -v|--verbose Increase verbosity.\n" , pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); } int kmk_builtin_kill(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { int rcExit = 0; int i; KMKKILLGLOBALS This; enum { kTargetJobs, kTargetProcesses } enmTarget = kTargetProcesses; /* Globals. */ This.pCtx = pCtx; This.cVerbosity = 1; /* * Parse arguments. */ if (argc <= 1) { kmkKillUsage(pCtx, 0); return 1; } for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { const char *pszValue; const char *psz = &argv[i][1]; char chOpt; chOpt = *psz++; if (chOpt == '-') { /* Convert long to short option. */ if (!strcmp(psz, "job")) chOpt = 'j'; else if (!strcmp(psz, "process")) chOpt = 'p'; else if (!strcmp(psz, "quiet")) chOpt = 'q'; else if (!strcmp(psz, "verbose")) chOpt = 'v'; else if (!strcmp(psz, "help")) chOpt = '?'; else if (!strcmp(psz, "version")) chOpt = 'V'; else { errx(pCtx, 2, "Invalid argument '%s'.", argv[i]); kmkKillUsage(pCtx, 1); return 2; } psz = ""; } /* * Requires value? */ switch (chOpt) { /*case '': if (*psz) pszValue = psz; else if (++i < argc) pszValue = argv[i]; else return errx(pCtx, 2, "The '-%c' option takes a value.", chOpt); break;*/ default: pszValue = NULL; break; } switch (chOpt) { /* * What to kill */ case 'j': enmTarget = kTargetJobs; break; case 'p': enmTarget = kTargetProcesses; break; /* * How to kill processes... */ /* * Noise level. */ case 'q': This.cVerbosity = 0; break; case 'v': This.cVerbosity += 1; break; /* * The mandatory version & help. */ case '?': kmkKillUsage(pCtx, 0); return rcExit; case 'V': return kbuild_version(argv[0]); /* * Invalid argument. */ default: errx(pCtx, 2, "Invalid argument '%s'.", argv[i]); kmkKillUsage(pCtx, 1); return 2; } } else { /* * Kill something. */ int rcExitOne; This.pszCur = argv[i]; if (enmTarget == kTargetJobs) rcExitOne = kmkKillJob(&This, argv[i]); else rcExitOne = kmkKillProcess(&This, argv[i]); if (rcExitOne != 0 && rcExit == 0) rcExit = rcExitOne; } } return rcExit; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_kill", NULL }; return kmk_builtin_kill(argc, argv, envp, &Ctx); } #endif kbuild-3686/src/kmk/kmkbuiltin/cat.c0000664000175000017500000002525415053010074017354 0ustar locutuslocutus/*- * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kevin Fall. * * 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. * 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 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1989, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #endif #ifndef lint #if 0 static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95"; #endif #endif /* not lint */ #if 0 #include __FBSDID("$FreeBSD: src/bin/cat/cat.c,v 1.32 2005/01/10 08:39:20 imp Exp $"); #endif /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #define FAKES_NO_GETOPT_H /* bird */ #define NO_UDOM_SUPPORT /* kmk */ #include "config.h" #ifndef _MSC_VER # include #endif #include #ifndef NO_UDOM_SUPPORT # include # include # include #endif #include #include "err.h" #include #include #include #include #include #include #include #include "getopt_r.h" #ifdef __sun__ # include "solfakes.h" #endif #ifdef _MSC_VER # include "mscfakes.h" #endif #include "kmkbuiltin.h" /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ typedef struct CATINSTANCE { PKMKBUILTINCTX pCtx; int bflag, eflag, nflag, sflag, tflag, vflag; /*int rval;*/ const char *filename; /* function level statics from raw_cat (needs freeing): */ size_t bsize; char *buf; } CATINSTANCE; /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; static int usage(PKMKBUILTINCTX pCtx, int fIsErr); static int scanfiles(CATINSTANCE *pThis, char *argv[], int cooked); static int cook_cat(CATINSTANCE *pThis, FILE *); static int raw_cat(CATINSTANCE *pThis, int); #ifndef NO_UDOM_SUPPORT static int udom_open(PKMKBUILTINCTX pCtx, const char *path, int flags); #endif int kmk_builtin_cat(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { struct getopt_state_r gos; CATINSTANCE This; int ch, rc; /* kmk: reinitialize globals */ This.pCtx = pCtx; This.bflag = This.eflag = This.nflag = This.sflag = This.tflag = This.vflag = 0; This.filename = NULL; This.bsize = 0; This.buf = 0; getopt_initialize_r(&gos, argc, argv, "benstuv", long_options, envp, pCtx); while ((ch = getopt_long_r(&gos, NULL)) != -1) switch (ch) { case 'b': This.bflag = This.nflag = 1; /* -b implies -n */ break; case 'e': This.eflag = This.vflag = 1; /* -e implies -v */ break; case 'n': This.nflag = 1; break; case 's': This.sflag = 1; break; case 't': This.tflag = This.vflag = 1; /* -t implies -v */ break; case 'u': #ifdef KMK_BUILTIN_STANDALONE /* don't allow messing with stdout */ setbuf(stdout, NULL); #endif break; case 'v': This.vflag = 1; break; case 261: usage(pCtx, 0); return 0; case 262: return kbuild_version(argv[0]); default: return usage(pCtx, 1); } argv += gos.optind; if (This.bflag || This.eflag || This.nflag || This.sflag || This.tflag || This.vflag) rc = scanfiles(&This, argv, 1); else rc = scanfiles(&This, argv, 0); if (This.buf) { free(This.buf); This.buf = NULL; } #ifdef KMK_BUILTIN_STANDALONE /* don't allow messing with stdout */ if (fclose(stdout)) return err(pCtx, 1, "stdout"); #endif return rc; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_cat", NULL }; setlocale(LC_CTYPE, ""); return kmk_builtin_cat(argc, argv, envp, &Ctx); } #endif static int usage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s [-benstuv] [file ...]\n" " or: %s --help\n" " or: %s --version\n", pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); return 1; } static int scanfiles(CATINSTANCE *pThis, char *argv[], int cooked) { int i = 0; char *path; FILE *fp; int rc2 = 0; int rc = 0; while ((path = argv[i]) != NULL || i == 0) { int fd; if (path == NULL || strcmp(path, "-") == 0) { pThis->filename = "stdin"; fd = STDIN_FILENO; } else { pThis->filename = path; fd = open(path, O_RDONLY | KMK_OPEN_NO_INHERIT); #ifndef NO_UDOM_SUPPORT if (fd < 0 && errno == EOPNOTSUPP) fd = udom_open(pThis, path, O_RDONLY); #endif } if (fd < 0) { warn(pThis->pCtx, "%s", path); rc2 = 1; /* non fatal */ } else if (cooked) { if (fd == STDIN_FILENO) rc = cook_cat(pThis, stdin); else { fp = fdopen(fd, "r"); rc = cook_cat(pThis, fp); fclose(fp); } } else { rc = raw_cat(pThis, fd); if (fd != STDIN_FILENO) close(fd); } if (rc || path == NULL) break; ++i; } return !rc ? rc2 : rc; } static int cat_putchar(PKMKBUILTINCTX pCtx, char ch) { #ifndef KMK_BUILTIN_STANDALONE if (pCtx->pOut) { output_write_text(pCtx->pOut, 0, &ch, 1); return 0; } #endif return putchar(ch); } static int cook_cat(CATINSTANCE *pThis, FILE *fp) { int ch, gobble, line, prev; int rc = 0; /* Reset EOF condition on stdin. */ if (fp == stdin && feof(stdin)) clearerr(stdin); line = gobble = 0; for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { if (prev == '\n') { if (pThis->sflag) { if (ch == '\n') { if (gobble) continue; gobble = 1; } else gobble = 0; } if (pThis->nflag && (!pThis->bflag || ch != '\n')) { kmk_builtin_ctx_printf(pThis->pCtx, 0, "%6d\t", ++line); if (ferror(stdout)) break; } } if (ch == '\n') { if (pThis->eflag && cat_putchar(pThis->pCtx, '$') == EOF) break; } else if (ch == '\t') { if (pThis->tflag) { if (cat_putchar(pThis->pCtx, '^') == EOF || cat_putchar(pThis->pCtx, 'I') == EOF) break; continue; } } else if (pThis->vflag) { if (!isascii(ch) && !isprint(ch)) { if (cat_putchar(pThis->pCtx, 'M') == EOF || cat_putchar(pThis->pCtx, '-') == EOF) break; ch = toascii(ch); } if (iscntrl(ch)) { if (cat_putchar(pThis->pCtx, '^') == EOF || cat_putchar(pThis->pCtx, ch == '\177' ? '?' : ch | 0100) == EOF) break; continue; } } if (cat_putchar(pThis->pCtx, ch) == EOF) break; } if (ferror(fp)) { warn(pThis->pCtx, "%s", pThis->filename); rc = 1; clearerr(fp); } if (ferror(stdout)) return err(pThis->pCtx, 1, "stdout"); return rc; } static int raw_cat(CATINSTANCE *pThis, int rfd) { int off, wfd = fileno(stdout); ssize_t nr, nw; wfd = fileno(stdout); if (pThis->buf == NULL) { struct stat sbuf; if (fstat(wfd, &sbuf)) return err(pThis->pCtx, 1, "%s", pThis->filename); #ifdef KBUILD_OS_WINDOWS pThis->bsize = 16384; #else pThis->bsize = MAX(sbuf.st_blksize, 1024); #endif if ((pThis->buf = malloc(pThis->bsize)) == NULL) return err(pThis->pCtx, 1, "buffer"); } while ((nr = read(rfd, pThis->buf, pThis->bsize)) > 0) for (off = 0; nr; nr -= nw, off += nw) { #ifndef KMK_BUILTIN_STANDALONE if (pThis->pCtx->pOut) nw = output_write_text(pThis->pCtx->pOut, 0, pThis->buf + off, nr); else #endif nw = write(wfd, pThis->buf + off, (size_t)nr); if (nw < 0) return err(pThis->pCtx, 1, "stdout"); } if (nr < 0) { warn(pThis->pCtx, "%s", pThis->filename); return 1; } return 0; } #ifndef NO_UDOM_SUPPORT static int udom_open(CATINSTANCE *pThis, const char *path, int flags) { struct sockaddr_un sou; int fd; unsigned int len; bzero(&sou, sizeof(sou)); /* * Construct the unix domain socket address and attempt to connect */ fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd >= 0) { sou.sun_family = AF_UNIX; if ((len = strlcpy(sou.sun_path, path, sizeof(sou.sun_path))) >= sizeof(sou.sun_path)) { errno = ENAMETOOLONG; return (-1); } len = offsetof(struct sockaddr_un, sun_path[len+1]); if (connect(fd, (void *)&sou, len) < 0) { close(fd); fd = -1; } } /* * handle the open flags by shutting down appropriate directions */ if (fd >= 0) { switch(flags & O_ACCMODE) { case O_RDONLY: if (shutdown(fd, SHUT_WR) == -1) warn(pThis->pCtx, NULL); break; case O_WRONLY: if (shutdown(fd, SHUT_RD) == -1) warn(pThis->pCtx, NULL); break; default: break; } } return(fd); } #endif kbuild-3686/src/kmk/kmkbuiltin/kbuild_protection.h0000664000175000017500000000415015053010074022322 0ustar locutuslocutus/* $Id: kbuild_protection.h 3192 2018-03-26 20:25:56Z bird $ */ /** @file * Simple File Protection. */ /* * Copyright (c) 2008-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ #ifndef ___kbuild_protection_h #define ___kbuild_protection_h /** * The different protection types. */ typedef enum { KBUILDPROTECTIONTYPE_FIRST = 0, KBUILDPROTECTIONTYPE_RECURSIVE = KBUILDPROTECTIONTYPE_FIRST, KBUILDPROTECTIONTYPE_FULL, KBUILDPROTECTIONTYPE_MAX } KBUILDPROTECTIONTYPE; /** * The instance data. * Don't touch. */ typedef struct KBUILDPROTECTION { unsigned int uMagic; unsigned int cProtectionDepth; struct KMKBUILTINCTX *pCtx; unsigned char afTypes[KBUILDPROTECTIONTYPE_MAX]; } KBUILDPROTECTION; typedef KBUILDPROTECTION *PKBUILDPROTECTION; typedef const KBUILDPROTECTION *PCKBUILDPROTECTION; void kBuildProtectionInit(PKBUILDPROTECTION pThis, struct KMKBUILTINCTX *pCtx); void kBuildProtectionTerm(PKBUILDPROTECTION pThis); int kBuildProtectionScanEnv(PKBUILDPROTECTION pThis, char **papszEnv, const char *pszPrefix); void kBuildProtectionEnable(PKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType); void kBuildProtectionDisable(PKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType); int kBuildProtectionSetDepth(PKBUILDPROTECTION pThis, const char *pszValue); int kBuildProtectionEnforce(PCKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType, const char *pszPath); int kBuildProtectionDefaultDepth(void); #endif kbuild-3686/src/kmk/kmkbuiltin/echo.c0000664000175000017500000000661115053010074017517 0ustar locutuslocutus/* $Id: echo.c 3192 2018-03-26 20:25:56Z bird $ */ /** @file * kMk Builtin command - echo */ /* * Copyright (c) 2018 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #include "config.h" #include #include #include #ifdef HAVE_UNISTD_H # include #endif #ifdef _MSC_VER # include #endif #include "kmkbuiltin.h" #include "err.h" int kmk_builtin_echo(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { int rcExit = 0; int iFirst = 1; int i; char *pszBuf; size_t cbBuf; /* * Check for the -n option. */ int fNoNewLine = 0; if ( argc > iFirst && strcmp(argv[iFirst], "-n") == 0) { iFirst++; fNoNewLine = 1; } /* * Calc buffer size and allocate it. */ cbBuf = 1 + 1; for (i = 1; i < argc; i++) cbBuf += (i > iFirst) + strlen(argv[i]); pszBuf = (char *)malloc(cbBuf); if (pszBuf) { /* * Assembler the output into the buffer. */ char *pszDst = pszBuf; for (i = iFirst; i < argc; i++) { const char *pszArg = argv[i]; size_t cchArg = strlen(pszArg); /* Check for "\c" in final argument (same as -n). */ if (i + 1 >= argc && cchArg >= 2 && pszArg[cchArg - 2] == '\\' && pszArg[cchArg - 1] == 'c') { fNoNewLine = 1; cchArg -= 2; } if (i > iFirst) *pszDst++ = ' '; memcpy(pszDst, pszArg, cchArg); pszDst += cchArg; } if (!fNoNewLine) *pszDst++ = '\n'; *pszDst = '\0'; /* * Push it out. */ #ifndef KMK_BUILTIN_STANDALONE if (output_write_text(pCtx->pOut, 0, pszBuf, pszDst - pszBuf) == -1) rcExit = err(pCtx, 1, "output_write_text"); #else if (write(STDOUT_FILENO, pszBuf, pszDst - pszBuf) == -1) rcExit = err(pCtx, 1, "write"); #endif free(pszBuf); } else rcExit = err(pCtx, 1, "malloc(%lu)", (unsigned long)cbBuf); return rcExit; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_echo", NULL }; return kmk_builtin_echo(argc, argv, envp, &Ctx); } #endif kbuild-3686/src/kmk/kmkbuiltin/touch.c0000664000175000017500000010032315053010075017717 0ustar locutuslocutus/* $Id: touch.c 3282 2019-01-05 00:57:52Z bird $ */ /** @file * kmk_touch - Simple touch implementation. */ /* * Copyright (c) 2017 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "makeint.h" #include #include #include #include #include #include #include #if defined(_MSC_VER) # include # include # include #else # include #endif #include #include #include "err.h" #include "kbuild_version.h" #include "kmkbuiltin.h" #ifdef _MSC_VER # include "nt/ntstat.h" # undef FILE_TIMESTAMP_HI_RES # define FILE_TIMESTAMP_HI_RES 1 #endif /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ /** The program name to use in message. */ #ifdef KMK # define TOUCH_NAME "kmk_builtin_touch" #else # define TOUCH_NAME "kmk_touch" #endif /** Converts a two digit decimal field to a number. */ #define TWO_CHARS_TO_INT(chHigh, chLow) ( ((unsigned)(chHigh) - (unsigned)'0') * 10 + ((unsigned)(chLow) - (unsigned)'0') ) /** Checks an alleged digit. */ #define IS_DIGIT(chDigit, uMax) ( ((unsigned)(chDigit) - (unsigned)'0') <= (unsigned)(uMax) ) /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ typedef enum KMKTOUCHTARGET { kTouchAccessAndModify, kTouchAccessOnly, kTouchModifyOnly } KMKTOUCHTARGET; typedef enum KMKTOUCHACTION { kTouchActionCurrent, kTouchActionSet, kTouchActionAdjust } KMKTOUCHACTION; typedef struct KMKTOUCHOPTS { /** Command execution context. */ PKMKBUILTINCTX pCtx; /** What timestamps to modify on the files. */ KMKTOUCHTARGET enmWhatToTouch; /** How to update the time. */ KMKTOUCHACTION enmAction; /** Whether to create files (K_TRUE) or ignore missing (K_FALSE). */ KBOOL fCreate; /** Whether to dereference files. */ KBOOL fDereference; /** The new access time value. */ struct timeval NewATime; /** The new modified time value. */ struct timeval NewMTime; /** Number of files. */ int cFiles; /** The specified files. */ char **papszFiles; } KMKTOUCHOPTS; typedef KMKTOUCHOPTS *PKMKTOUCHOPTS; static int touch_usage(void) { fputs("Usage: " TOUCH_NAME " [options] [MMDDhhmm[YY]] [.. [fileN]]\n" "\n" "Options:\n" " -A [-][[hh]mm]SS, --adjust=[-][[hh]mm]SS\n" " Adjust timestamps by given delta.\n" " -a, --time=atime, --time=access\n" " Only change the accessed timestamp.\n" " -c, --no-create\n" " Ignore missing files and don't create them. (default create empty file)\n" " -d YYYY-MM-DDThh:mm:SS[.frac][tz], --date=YYYY-MM-DDThh:mm:SS[.frac][tz]\n" " Set the timestamps to the given one.\n" " -f\n" " Ignored for compatbility reasons.\n" " -h, --no-dereference\n" " Don't follow links, touch links. (Not applicable to -r.)\n" " -m, --time=mtime, --time=modify\n" " Only changed the modified timestamp.\n" " -r , --reference=\n" " Take the timestamps from .\n" " -t [[CC]YY]MMDDhhmm[.SS]\n" " Set the timestamps to the given one.\n" "\n" "Note. For compatibility reasons the first file can be taken to be a 8 or 10\n" " character long timestamp if it matches the given pattern and none of\n" " the -A, -d, --date, -r, --reference, or -t options are given. So, use\n" " absolute or relative paths when specifying more than one file.\n" , stdout); return 0; } #if K_OS == K_OS_SOLARIS /** * Solaris doesn't have lutimes because System V doesn't believe in stuff like file modes on symbolic links. */ static int lutimes(const char *pszFile, struct timeval aTimes[2]) { struct stat Stat; if (stat(pszFile, &Stat) != -1) { if (!S_ISLNK(Stat.st_mode)) return utimes(pszFile, aTimes); return 0; } return -1; } #endif /** * Parses adjustment value: [-][[hh]mm]SS */ static int touch_parse_adjust(PKMKBUILTINCTX pCtx, const char *pszValue, int *piAdjustValue) { const char * const pszInValue = pszValue; size_t cchValue = strlen(pszValue); KBOOL fNegative = K_FALSE; /* Deal with negativity */ if (pszValue[0] == '-') { fNegative = K_TRUE; pszValue++; cchValue--; } /* Validate and convert. */ *piAdjustValue = 0; switch (cchValue) { case 6: if ( !IS_DIGIT(pszValue[0], 9) || !IS_DIGIT(pszValue[0], 9)) return errx(pCtx, 2, "Malformed hour part of -A value: %s", pszInValue); *piAdjustValue = TWO_CHARS_TO_INT(pszValue[0], pszValue[1]) * 60 * 60; /* fall thru */ case 4: if ( !IS_DIGIT(pszValue[cchValue - 4], 9) /* don't bother limit to 60 minutes */ || !IS_DIGIT(pszValue[cchValue - 3], 9)) return errx(pCtx, 2, "Malformed minute part of -A value: %s", pszInValue); *piAdjustValue += TWO_CHARS_TO_INT(pszValue[cchValue - 4], pszValue[cchValue - 3]) * 60; /* fall thru */ case 2: if ( !IS_DIGIT(pszValue[cchValue - 2], 9) /* don't bother limit to 60 seconds */ || !IS_DIGIT(pszValue[cchValue - 1], 9)) return errx(pCtx, 2, "Malformed second part of -A value: %s", pszInValue); *piAdjustValue += TWO_CHARS_TO_INT(pszValue[cchValue - 2], pszValue[cchValue - 1]); break; default: return errx(pCtx, 2, "Invalid -A value (length): %s", pszInValue); } /* Apply negativity. */ if (fNegative) *piAdjustValue = -*piAdjustValue; return 0; } /** * Parse -d timestamp: YYYY-MM-DDThh:mm:SS[.frac][tz] */ static int touch_parse_d_ts(PKMKBUILTINCTX pCtx, const char *pszTs, struct timeval *pDst) { const char * const pszTsIn = pszTs; struct tm ExpTime; /* * Validate and parse the timestamp into the tm structure. */ memset(&ExpTime, 0, sizeof(ExpTime)); /* year */ if ( !IS_DIGIT(pszTs[0], 9) || !IS_DIGIT(pszTs[1], 9) || !IS_DIGIT(pszTs[2], 9) || !IS_DIGIT(pszTs[3], 9) || pszTs[4] != '-') return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to start with 4 digit year followed by a dash", pszTsIn); ExpTime.tm_year = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]) * 100 + TWO_CHARS_TO_INT(pszTs[2], pszTs[3]) - 1900; pszTs += 5; /* month */ if ( !IS_DIGIT(pszTs[0], 1) || !IS_DIGIT(pszTs[1], 9) || pszTs[2] != '-') return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to two digit month at position 6 followed by a dash", pszTsIn); ExpTime.tm_mon = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]) - 1; pszTs += 3; /* day */ if ( !IS_DIGIT(pszTs[0], 3) || !IS_DIGIT(pszTs[1], 9) || (pszTs[2] != 'T' && pszTs[2] != 't' && pszTs[2] != ' ') ) return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to two digit day of month at position 9 followed by 'T' or space", pszTsIn); ExpTime.tm_mday = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]); pszTs += 3; /* hour */ if ( !IS_DIGIT(pszTs[0], 2) || !IS_DIGIT(pszTs[1], 9) || pszTs[2] != ':') return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to two digit hour at position 12 followed by colon", pszTsIn); ExpTime.tm_hour = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]); pszTs += 3; /* minute */ if ( !IS_DIGIT(pszTs[0], 5) || !IS_DIGIT(pszTs[1], 9) || pszTs[2] != ':') return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to two digit minute at position 15 followed by colon", pszTsIn); ExpTime.tm_min = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]); pszTs += 3; /* seconds */ if ( !IS_DIGIT(pszTs[0], 5) || !IS_DIGIT(pszTs[1], 9)) return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to two digit seconds at position 12", pszTsIn); ExpTime.tm_sec = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]); pszTs += 2; /* fraction */ pDst->tv_usec = 0; if (*pszTs == '.' || *pszTs == ',') { int iFactor; pszTs++; if (!IS_DIGIT(*pszTs, 9)) return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: empty fraction", pszTsIn); iFactor = 100000; do { pDst->tv_usec += ((unsigned)*pszTs - (unsigned)'0') * iFactor; iFactor /= 10; pszTs++; } while (IS_DIGIT(*pszTs, 9)); } /* zulu time indicator */ ExpTime.tm_isdst = -1; if (*pszTs == 'Z' || *pszTs == 'z') { ExpTime.tm_isdst = 0; pszTs++; if (*pszTs != '\0') return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: Unexpected character(s) after zulu time indicator at end of timestamp", pszTsIn); } else if (*pszTs != '\0') return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to 'Z' (zulu) or nothing at end of timestamp", pszTsIn); /* * Convert to UTC seconds using either timegm or mktime. */ ExpTime.tm_yday = -1; ExpTime.tm_wday = -1; if (ExpTime.tm_isdst == 0) { #if K_OS == K_OS_SOLARIS || K_OS == K_OS_OS2 pDst->tv_sec = mktime(&ExpTime) - timezone; /* best we can do for now */ #else pDst->tv_sec = timegm(&ExpTime); #endif if (pDst->tv_sec == -1) return errx(pCtx, 1, "timegm failed on '%s': %s", pszTs, strerror(errno)); } else { pDst->tv_sec = mktime(&ExpTime); if (pDst->tv_sec == -1) return errx(pCtx, 1, "mktime failed on '%s': %s", pszTs, strerror(errno)); } return 0; } /** * Parse -t timestamp: [[CC]YY]MMDDhhmm[.SS] */ static int touch_parse_ts(PKMKBUILTINCTX pCtx, const char *pszTs, struct timeval *pDst) { size_t const cchTs = strlen(pszTs); size_t cchTsNoSec; struct tm ExpTime; struct tm *pExpTime; struct timeval Now; int rc; /* * Do some input validations first. */ if ((cchTs & 1) && pszTs[cchTs - 3] != '.') return errx(pCtx, 2, "Invalid timestamp given to -t: %s", pszTs); switch (cchTs) { case 8: /* MMDDhhmm */ case 8 + 2: /* YYMMDDhhmm */ case 8 + 2 + 2: /* CCYYMMDDhhmm */ cchTsNoSec = cchTs; break; case 8 + 3: /* MMDDhhmm.SS */ case 8 + 3 + 2: /* YYMMDDhhmm.SS */ case 8 + 3 + 2 + 2: /* CCYYMMDDhhmm.SS */ if (pszTs[cchTs - 3] != '.') return errx(pCtx, 2, "Invalid timestamp (-t) '%s': missing dot for seconds part", pszTs); if ( !IS_DIGIT(pszTs[cchTs - 2], 5) || !IS_DIGIT(pszTs[cchTs - 1], 9)) return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed seconds part", pszTs); cchTsNoSec = cchTs - 3; break; default: return errx(pCtx, 1, "Invalid timestamp (-t) '%s': wrong length (%d)", pszTs, (int)cchTs); } switch (cchTsNoSec) { case 8 + 2 + 2: /* CCYYMMDDhhmm */ if ( !IS_DIGIT(pszTs[cchTsNoSec - 12], 9) || !IS_DIGIT(pszTs[cchTsNoSec - 11], 9)) return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed CC part", pszTs); /* fall thru */ case 8 + 2: /* YYMMDDhhmm */ if ( !IS_DIGIT(pszTs[cchTsNoSec - 10], 9) || !IS_DIGIT(pszTs[cchTsNoSec - 9], 9)) return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed YY part", pszTs); /* fall thru */ case 8: /* MMDDhhmm */ if ( !IS_DIGIT(pszTs[cchTsNoSec - 8], 1) || !IS_DIGIT(pszTs[cchTsNoSec - 7], 9) ) return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed month part", pszTs); if ( !IS_DIGIT(pszTs[cchTsNoSec - 6], 3) || !IS_DIGIT(pszTs[cchTsNoSec - 5], 9) ) return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed day part", pszTs); if ( !IS_DIGIT(pszTs[cchTsNoSec - 4], 2) || !IS_DIGIT(pszTs[cchTsNoSec - 3], 9) ) return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed hour part", pszTs); if ( !IS_DIGIT(pszTs[cchTsNoSec - 2], 5) || !IS_DIGIT(pszTs[cchTsNoSec - 1], 9) ) return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed minute part", pszTs); break; } /* * Get the current time and explode it. */ rc = gettimeofday(&Now, NULL); if (rc != 0) return errx(pCtx, 1, "gettimeofday failed: %s", strerror(errno)); pExpTime = localtime_r(&Now.tv_sec, &ExpTime); if (pExpTime == NULL) return errx(pCtx, 1, "localtime_r failed: %s", strerror(errno)); /* * Do the decoding. */ if (cchTs & 1) pExpTime->tm_sec = TWO_CHARS_TO_INT(pszTs[cchTs - 2], pszTs[cchTs - 1]); else pExpTime->tm_sec = 0; if (cchTsNoSec == 8 + 2 + 2) /* CCYY */ pExpTime->tm_year = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]) * 100 + TWO_CHARS_TO_INT(pszTs[2], pszTs[3]) - 1900; else if (cchTsNoSec == 8 + 2) /* YY */ { pExpTime->tm_year = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]); if (pExpTime->tm_year < 69) pExpTime->tm_year += 100; } pExpTime->tm_mon = TWO_CHARS_TO_INT(pszTs[cchTsNoSec - 8], pszTs[cchTsNoSec - 7]) - 1; pExpTime->tm_mday = TWO_CHARS_TO_INT(pszTs[cchTsNoSec - 6], pszTs[cchTsNoSec - 5]); pExpTime->tm_hour = TWO_CHARS_TO_INT(pszTs[cchTsNoSec - 4], pszTs[cchTsNoSec - 3]); pExpTime->tm_min = TWO_CHARS_TO_INT(pszTs[cchTsNoSec - 2], pszTs[cchTsNoSec - 1]); /* * Use mktime to convert to UTC seconds. */ pExpTime->tm_isdst = -1; pExpTime->tm_yday = -1; pExpTime->tm_wday = -1; pDst->tv_usec = 0; pDst->tv_sec = mktime(pExpTime); if (pDst->tv_sec != -1) return 0; return errx(pCtx, 1, "mktime failed on '%s': %s", pszTs, strerror(errno)); } /** * Check for old timestamp: MMDDhhmm[YY] */ static int touch_parse_old_ts(PKMKBUILTINCTX pCtx, const char *pszOldTs, time_t Now, struct timeval *pDst) { /* * Check if this is a valid timestamp. */ size_t const cchOldTs = strlen(pszOldTs); if ( ( cchOldTs == 8 || cchOldTs == 10) && IS_DIGIT(pszOldTs[0], 1) && IS_DIGIT(pszOldTs[1], 9) && IS_DIGIT(pszOldTs[2], 3) && IS_DIGIT(pszOldTs[3], 9) && IS_DIGIT(pszOldTs[4], 2) && IS_DIGIT(pszOldTs[5], 9) && IS_DIGIT(pszOldTs[6], 5) && IS_DIGIT(pszOldTs[7], 9) && ( cchOldTs == 8 || ( IS_DIGIT(pszOldTs[8], 9) && IS_DIGIT(pszOldTs[9], 9) )) ) { /* * Explode the current time as local. */ struct tm ExpTime; struct tm *pExpTime; pExpTime = localtime_r(&Now, &ExpTime); if (pExpTime == NULL) return errx(pCtx, 1, "localtime_r failed: %s", strerror(errno)); /* * Decode the bits we've got. */ pExpTime->tm_mon = TWO_CHARS_TO_INT(pszOldTs[0], pszOldTs[1]) - 1; pExpTime->tm_mday = TWO_CHARS_TO_INT(pszOldTs[2], pszOldTs[3]); pExpTime->tm_hour = TWO_CHARS_TO_INT(pszOldTs[4], pszOldTs[5]); pExpTime->tm_min = TWO_CHARS_TO_INT(pszOldTs[6], pszOldTs[7]); if (cchOldTs == 10) { pExpTime->tm_year = TWO_CHARS_TO_INT(pszOldTs[8], pszOldTs[9]); if (pExpTime->tm_year <= 38) /* up to 2038, 32-bit time_t style logic. */ pExpTime->tm_year += 100; } /* * Use mktime to convert to UTC seconds. */ pExpTime->tm_isdst = -1; pExpTime->tm_yday = -1; pExpTime->tm_wday = -1; pDst->tv_usec = 0; pDst->tv_sec = mktime(pExpTime); if (pDst->tv_sec != -1) return 0; return errx(pCtx, 1, "mktime failed on '%s': %s", pszOldTs, strerror(errno)); } /* No valid timestamp present. */ return -1; } /** * Parses the arguments into pThis. * * @returns exit code. * @param pThis Options structure to return the parsed info in. * Caller initalizes this with defaults. * @param cArgs The number of arguments. * @param papszArgs The arguments. * @param pfExit Indicates whether to exit or to start processing * files. */ static int touch_parse_args(PKMKTOUCHOPTS pThis, int cArgs, char **papszArgs, KBOOL *pfExit) { int iAdjustValue = 0; int iArg; int rc; *pfExit = K_TRUE; /* * Parse arguments, skipping all files (GNU style). */ for (iArg = 1; iArg < cArgs; iArg++) { const char *pszArg = papszArgs[iArg]; if (*pszArg == '-') { const char *pszLongValue = NULL; char ch = *++pszArg; pszArg++; /* * Deal with long options first, preferably translating them into short ones. */ if (ch == '-') { const char *pszLong = pszArg; ch = *pszArg++; if (!ch) { while (++iArg < cArgs) pThis->papszFiles[pThis->cFiles++] = papszArgs[iArg]; break; /* '--' */ } /* Translate long options. */ pszArg = ""; if (strcmp(pszLong, "adjust") == 0) ch = 'A'; else if (strncmp(pszLong, "adjust=", sizeof("adjust=") - 1) == 0) { ch = 'A'; pszLongValue = pszArg = pszLong + sizeof("adjust=") - 1; } else if (strcmp(pszLong, "no-create") == 0) ch = 'c'; else if (strcmp(pszLong, "date") == 0) ch = 'd'; else if (strncmp(pszLong, "date=", sizeof("date=") - 1) == 0) { ch = 'd'; pszLongValue = pszArg = pszLong + sizeof("date=") - 1; } else if (strcmp(pszLong, "no-dereference") == 0) ch = 'h'; else if (strcmp(pszLong, "reference") == 0) ch = 'r'; else if (strncmp(pszLong, "reference=", sizeof("reference=") - 1) == 0) { ch = 'r'; pszLongValue = pszArg = pszLong + sizeof("reference=") - 1; } else if (strcmp(pszLong, "time") == 0) ch = 'T'; else if (strncmp(pszLong, "time=", sizeof("time=") - 1) == 0) { ch = 'T'; pszLongValue = pszArg = pszLong + sizeof("time=") - 1; } else if (strcmp(pszLong, "help") == 0) return touch_usage(); else if (strcmp(pszLong, "version") == 0) return kbuild_version(papszArgs[0]); else return errx(pThis->pCtx, 2, "Unknown option: --%s", pszLong); } /* * Process short options. */ do { /* Some options takes a value. */ const char *pszValue; switch (ch) { case 'A': case 'd': case 'r': case 't': case 'T': if (*pszArg || pszLongValue) { pszValue = pszArg; pszArg = ""; } else if (iArg + 1 < cArgs) pszValue = papszArgs[++iArg]; else return errx(pThis->pCtx, 2, "Option -%c requires a value", ch); break; default: pszValue = NULL; break; } switch (ch) { /* -A [-][[HH]MM]SS */ case 'A': rc = touch_parse_adjust(pThis->pCtx, pszValue, &iAdjustValue); if (rc != 0) return rc; if (pThis->enmAction != kTouchActionSet) { pThis->enmAction = kTouchActionAdjust; pThis->NewATime.tv_sec = iAdjustValue; pThis->NewATime.tv_usec = 0; pThis->NewMTime = pThis->NewATime; } /* else: applied after parsing everything. */ break; case 'a': pThis->enmWhatToTouch = kTouchAccessOnly; break; case 'c': pThis->fCreate = K_FALSE; break; case 'd': rc = touch_parse_d_ts(pThis->pCtx, pszValue, &pThis->NewATime); if (rc != 0) return rc; pThis->enmAction = kTouchActionSet; pThis->NewMTime = pThis->NewATime; break; case 'f': /* some historical thing, ignored. */ break; case 'h': pThis->fDereference = K_FALSE; break; case 'm': pThis->enmWhatToTouch = kTouchModifyOnly; break; case 'r': { struct stat St; if (stat(pszValue, &St) != 0) return errx(pThis->pCtx, 1, "Failed to stat '%s' (-r option): %s", pszValue, strerror(errno)); pThis->enmAction = kTouchActionSet; pThis->NewATime.tv_sec = St.st_atime; pThis->NewMTime.tv_sec = St.st_mtime; #if FILE_TIMESTAMP_HI_RES pThis->NewATime.tv_usec = St.ST_ATIM_NSEC / 1000; pThis->NewMTime.tv_usec = St.ST_MTIM_NSEC / 1000; #else pThis->NewATime.tv_usec = 0; pThis->NewMTime.tv_usec = 0; #endif break; } case 't': rc = touch_parse_ts(pThis->pCtx, pszValue, &pThis->NewATime); if (rc != 0) return rc; pThis->enmAction = kTouchActionSet; pThis->NewMTime = pThis->NewATime; break; case 'T': if ( strcmp(pszValue, "atime") == 0 || strcmp(pszValue, "access") == 0) pThis->enmWhatToTouch = kTouchAccessOnly; else if ( strcmp(pszValue, "mtime") == 0 || strcmp(pszValue, "modify") == 0) pThis->enmWhatToTouch = kTouchModifyOnly; else return errx(pThis->pCtx, 2, "Unknown --time value: %s", pszValue); break; case 'V': return kbuild_version(papszArgs[0]); default: return errx(pThis->pCtx, 2, "Unknown option: -%c (%c%s)", ch, ch, pszArg); } } while ((ch = *pszArg++) != '\0'); } else pThis->papszFiles[pThis->cFiles++] = papszArgs[iArg]; } /* * Allow adjusting specified timestamps too like BSD does. */ if ( pThis->enmAction == kTouchActionSet && iAdjustValue != 0) { if ( pThis->enmWhatToTouch == kTouchAccessAndModify || pThis->enmWhatToTouch == kTouchAccessOnly) pThis->NewATime.tv_sec += iAdjustValue; if ( pThis->enmWhatToTouch == kTouchAccessAndModify || pThis->enmWhatToTouch == kTouchModifyOnly) pThis->NewMTime.tv_sec += iAdjustValue; } /* * Check for old timestamp: MMDDhhmm[YY] */ if ( pThis->enmAction == kTouchActionCurrent && pThis->cFiles >= 2) { struct timeval OldTs; rc = touch_parse_old_ts(pThis->pCtx, pThis->papszFiles[0], pThis->NewATime.tv_sec, &OldTs); if (rc == 0) { int iFile; pThis->NewATime = OldTs; pThis->NewMTime = OldTs; pThis->enmAction = kTouchActionSet; for (iFile = 1; iFile < pThis->cFiles; iFile++) pThis->papszFiles[iFile - 1] = pThis->papszFiles[iFile]; pThis->cFiles--; } else if (rc > 0) return rc; } /* * Check that we've found at least one file argument. */ if (pThis->cFiles > 0) { *pfExit = K_FALSE; return 0; } return errx(pThis->pCtx, 2, "No file specified"); } /** * Touches one file. * * @returns exit code. * @param pThis The options. * @param pszFile The file to touch. */ static int touch_process_file(PKMKTOUCHOPTS pThis, const char *pszFile) { int fd; int rc; struct stat St; struct timeval aTimes[2]; /* * Create the file if it doesn't exists. If the --no-create/-c option is * in effect, we silently skip the file if it doesn't already exist. */ if (pThis->fDereference) rc = stat(pszFile, &St); else rc = lstat(pszFile, &St); if (rc != 0) { if (errno != ENOENT) return errx(pThis->pCtx, 1, "Failed to stat '%s': %s", pszFile, strerror(errno)); if (!pThis->fCreate) return 0; fd = open(pszFile, O_WRONLY | O_CREAT | KMK_OPEN_NO_INHERIT, 0666); if (fd == -1) return errx(pThis->pCtx, 1, "Failed to create '%s': %s", pszFile, strerror(errno)); /* If we're not setting the current time, we may need value stat info on the file, so get it thru the file descriptor before closing it. */ if (pThis->enmAction == kTouchActionCurrent) rc = 0; else rc = fstat(fd, &St); if (close(fd) != 0) return errx(pThis->pCtx, 1, "Failed to close '%s' after creation: %s", pszFile, strerror(errno)); if (rc != 0) return errx(pThis->pCtx, 1, "Failed to fstat '%s' after creation: %s", pszFile, strerror(errno)); /* We're done now if we're setting the current time. */ if (pThis->enmAction == kTouchActionCurrent) return 0; } /* * Create aTimes and call utimes/lutimes. */ aTimes[0].tv_sec = St.st_atime; aTimes[1].tv_sec = St.st_mtime; #if FILE_TIMESTAMP_HI_RES aTimes[0].tv_usec = St.ST_ATIM_NSEC / 1000; aTimes[1].tv_usec = St.ST_MTIM_NSEC / 1000; #else aTimes[0].tv_usec = 0; aTimes[1].tv_usec = 0; #endif if ( pThis->enmWhatToTouch == kTouchAccessAndModify || pThis->enmWhatToTouch == kTouchAccessOnly) { if ( pThis->enmAction == kTouchActionCurrent || pThis->enmAction == kTouchActionSet) aTimes[0] = pThis->NewATime; else aTimes[0].tv_sec += pThis->NewATime.tv_sec; } if ( pThis->enmWhatToTouch == kTouchAccessAndModify || pThis->enmWhatToTouch == kTouchModifyOnly) { if ( pThis->enmAction == kTouchActionCurrent || pThis->enmAction == kTouchActionSet) aTimes[1] = pThis->NewMTime; else aTimes[1].tv_sec += pThis->NewMTime.tv_sec; } /* * Try set the times. If we're setting current time, fall back on calling * [l]utimes with a NULL timeval vector since that has slightly different * permissions checks. (Note that we don't do that by default because it * may do more than what we want (st_ctime).) */ if (pThis->fDereference) rc = utimes(pszFile, aTimes); else rc = lutimes(pszFile, aTimes); if (rc != 0) { if (pThis->enmAction == kTouchActionCurrent) { if (pThis->fDereference) rc = utimes(pszFile, NULL); else rc = lutimes(pszFile, NULL); } if (rc != 0) rc = errx(pThis->pCtx, 1, "%stimes failed on '%s': %s", pThis->fDereference ? "" : "l", pszFile, strerror(errno)); } return rc; } /** * Actual main function for the touch command. */ int kmk_builtin_touch(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { int rc; KMKTOUCHOPTS This; K_NOREF(envp); /* * Initialize options with defaults and parse them. */ This.pCtx = pCtx; This.enmWhatToTouch = kTouchAccessAndModify; This.enmAction = kTouchActionCurrent; This.fCreate = K_TRUE; This.fDereference = K_TRUE; This.cFiles = 0; This.papszFiles = (char **)calloc(argc, sizeof(char *)); if (This.papszFiles) { rc = gettimeofday(&This.NewATime, NULL); if (rc == 0) { KBOOL fExit; This.NewMTime = This.NewATime; rc = touch_parse_args(&This, argc, argv, &fExit); if (rc == 0 && !fExit) { /* * Process the files. */ int iFile; for (iFile = 0; iFile < This.cFiles; iFile++) { int rc2 = touch_process_file(&This, This.papszFiles[iFile]); if (rc2 != 0 && rc == 0) rc = rc2; } } } else rc = errx(pCtx, 2, "gettimeofday failed: %s", strerror(errno)); free(This.papszFiles); } else rc = errx(pCtx, 2, "calloc failed"); return rc; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_touch", NULL }; return kmk_builtin_touch(argc, argv, envp, &Ctx); } #endif kbuild-3686/src/kmk/kmkbuiltin/cp_utils.c0000664000175000017500000002761215053010075020430 0ustar locutuslocutus/*- * Copyright (c) 1991, 1993, 1994 * 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. * 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. */ #ifndef lint #if 0 static char sccsid[] = "@(#)utils.c 8.3 (Berkeley) 4/1/94"; #include __FBSDID("$FreeBSD: src/bin/cp/utils.c,v 1.43 2004/04/06 20:06:44 markm Exp $"); #endif #endif /* not lint */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #define MSC_DO_64_BIT_IO #include "config.h" #ifndef _MSC_VER # include #endif #include #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED # include #endif #include "err.h" #include #include #include "fts.h" #include #include #include #include #ifndef __HAIKU__ # include #endif #include #ifdef __sun__ # include "solfakes.h" #endif #ifdef __HAIKU__ # include "haikufakes.h" #endif #ifdef _MSC_VER # include "mscfakes.h" #else # include #endif #include "cp_extern.h" #include "cmp_extern.h" /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ #define cp_pct(x,y) (int)(100.0 * (double)(x) / (double)(y)) #ifndef MAXBSIZE # define MAXBSIZE 0x10000 #endif #ifndef O_BINARY # define O_BINARY 0 #endif #ifndef S_ISVTX # define S_ISVTX 0 #endif int copy_file(CPUTILSINSTANCE *pThis, const FTSENT *entp, int dne, int changed_only, int *pcopied) { /*static*/ char buf[MAXBSIZE]; struct stat *fs; int ch, checkch, from_fd, rcount, rval, to_fd; ssize_t wcount; size_t wresid; size_t wtotal; char *bufp; #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED char *p; #endif *pcopied = 0; if ((from_fd = open(entp->fts_path, O_RDONLY | O_BINARY | KMK_OPEN_NO_INHERIT, 0)) == -1) { warn(pThis->pCtx, "open: %s", entp->fts_path); return (1); } fs = entp->fts_statp; /* * If the file exists and we're interactive, verify with the user. * If the file DNE, set the mode to be the from file, minus setuid * bits, modified by the umask; arguably wrong, but it makes copying * executables work right and it's been that way forever. (The * other choice is 666 or'ed with the execute bits on the from file * modified by the umask.) */ if (!dne) { /* compare the files first if requested */ if (changed_only) { if (cmp_fd_and_file(pThis->pCtx, from_fd, entp->fts_path, pThis->to.p_path, 1 /* silent */, 0 /* lflag */, 0 /* special */) == OK_EXIT) { close(from_fd); return (0); } if (lseek(from_fd, 0, SEEK_SET) != 0) { close(from_fd); if ((from_fd = open(entp->fts_path, O_RDONLY | O_BINARY | KMK_OPEN_NO_INHERIT, 0)) == -1) { warn(pThis->pCtx, "open: %s", entp->fts_path); return (1); } } } #define YESNO "(y/n [n]) " if (pThis->nflag) { if (pThis->vflag) kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s not overwritten\n", pThis->to.p_path); return (0); } else if (pThis->iflag) { (void)fprintf(stderr, "overwrite %s? %s", pThis->to.p_path, YESNO); checkch = ch = getchar(); while (ch != '\n' && ch != EOF) ch = getchar(); if (checkch != 'y' && checkch != 'Y') { (void)close(from_fd); kmk_builtin_ctx_printf(pThis->pCtx, 1, "not overwritten\n"); return (1); } } if (pThis->fflag) { /* remove existing destination file name, * create a new file */ (void)unlink(pThis->to.p_path); to_fd = open(pThis->to.p_path, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY | KMK_OPEN_NO_INHERIT, fs->st_mode & ~(S_ISUID | S_ISGID)); } else /* overwrite existing destination file name */ to_fd = open(pThis->to.p_path, O_WRONLY | O_TRUNC | O_BINARY | KMK_OPEN_NO_INHERIT, 0); } else to_fd = open(pThis->to.p_path, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY | KMK_OPEN_NO_INHERIT, fs->st_mode & ~(S_ISUID | S_ISGID)); if (to_fd == -1) { warn(pThis->pCtx, "open: %s", pThis->to.p_path); (void)close(from_fd); return (1); } rval = 0; *pcopied = 1; /* * Mmap and write if less than 8M (the limit is so we don't totally * trash memory on big files. This is really a minor hack, but it * wins some CPU back. */ #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED if (S_ISREG(fs->st_mode) && fs->st_size > 0 && fs->st_size <= 8 * 1048576) { if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ, MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) { warn(pThis->pCtx, "mmap: %s", entp->fts_path); rval = 1; } else { wtotal = 0; for (bufp = p, wresid = fs->st_size; ; bufp += wcount, wresid -= (size_t)wcount) { wcount = write(to_fd, bufp, wresid); wtotal += wcount; # if defined(SIGINFO) && defined(KMK_BUILTIN_STANDALONE) if (g_cp_info) { g_cp_info = 0; kmk_builtin_ctx_printf(pThis->pCtx, 1, "%s -> %s %3d%%\n", entp->fts_path, pThis->to.p_path, cp_pct(wtotal, fs->st_size)); } #endif if (wcount >= (ssize_t)wresid || wcount <= 0) break; } if (wcount != (ssize_t)wresid) { warn(pThis->pCtx, "write[%zd != %zu]: %s", wcount, wresid, pThis->to.p_path); rval = 1; } /* Some systems don't unmap on close(2). */ if (munmap(p, fs->st_size) < 0) { warn(pThis->pCtx, "munmap: %s", entp->fts_path); rval = 1; } } } else #endif { wtotal = 0; while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) { for (bufp = buf, wresid = rcount; ; bufp += wcount, wresid -= wcount) { wcount = write(to_fd, bufp, wresid); wtotal += wcount; #if defined(SIGINFO) && defined(KMK_BUILTIN_STANDALONE) if (g_cp_info) { g_cp_info = 0; kmk_builtin_ctx_printf(pThis->pCtx, 1, "%s -> %s %3d%%\n", entp->fts_path, pThis->to.p_path, cp_pct(wtotal, fs->st_size)); } #endif if (wcount >= (ssize_t)wresid || wcount <= 0) break; } if (wcount != (ssize_t)wresid) { warn(pThis->pCtx, "write[%zd != %zu]: %s", wcount, wresid, pThis->to.p_path); rval = 1; break; } } if (rcount < 0) { warn(pThis->pCtx, "read: %s", entp->fts_path); rval = 1; } } /* * Don't remove the target even after an error. The target might * not be a regular file, or its attributes might be important, * or its contents might be irreplaceable. It would only be safe * to remove it if we created it and its length is 0. */ if (pThis->pflag && copy_file_attribs(pThis, fs, to_fd)) rval = 1; (void)close(from_fd); if (close(to_fd)) { warn(pThis->pCtx, "close: %s", pThis->to.p_path); rval = 1; } return (rval); } int copy_link(CPUTILSINSTANCE *pThis, const FTSENT *p, int exists) { int len; char llink[PATH_MAX]; if ((len = readlink(p->fts_path, llink, sizeof(llink) - 1)) == -1) { warn(pThis->pCtx, "readlink: %s", p->fts_path); return (1); } llink[len] = '\0'; if (exists && unlink(pThis->to.p_path)) { warn(pThis->pCtx, "unlink: %s", pThis->to.p_path); return (1); } if (symlink(llink, pThis->to.p_path)) { warn(pThis->pCtx, "symlink: %s", llink); return (1); } return (pThis->pflag ? copy_file_attribs(pThis, p->fts_statp, -1) : 0); } int copy_fifo(CPUTILSINSTANCE *pThis, struct stat *from_stat, int exists) { if (exists && unlink(pThis->to.p_path)) { warn(pThis->pCtx, "unlink: %s", pThis->to.p_path); return (1); } if (mkfifo(pThis->to.p_path, from_stat->st_mode)) { warn(pThis->pCtx, "mkfifo: %s", pThis->to.p_path); return (1); } return (pThis->pflag ? copy_file_attribs(pThis, from_stat, -1) : 0); } int copy_special(CPUTILSINSTANCE *pThis, struct stat *from_stat, int exists) { if (exists && unlink(pThis->to.p_path)) { warn(pThis->pCtx, "unlink: %s", pThis->to.p_path); return (1); } if (mknod(pThis->to.p_path, from_stat->st_mode, from_stat->st_rdev)) { warn(pThis->pCtx, "mknod: %s", pThis->to.p_path); return (1); } return (pThis->pflag ? copy_file_attribs(pThis, from_stat, -1) : 0); } int copy_file_attribs(CPUTILSINSTANCE *pThis, struct stat *fs, int fd) { /*static*/ struct timeval tv[2]; struct stat ts; int rval, gotstat, islink, fdval; rval = 0; fdval = fd != -1; islink = !fdval && S_ISLNK(fs->st_mode); fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO; #ifdef HAVE_ST_TIMESPEC TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec); TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec); #else tv[0].tv_sec = fs->st_atime; tv[1].tv_sec = fs->st_mtime; tv[0].tv_usec = tv[1].tv_usec = 0; #endif if (islink ? lutimes(pThis->to.p_path, tv) : utimes(pThis->to.p_path, tv)) { warn(pThis->pCtx, "%sutimes: %s", islink ? "l" : "", pThis->to.p_path); rval = 1; } if (fdval ? fstat(fd, &ts) : (islink ? lstat(pThis->to.p_path, &ts) : stat(pThis->to.p_path, &ts))) gotstat = 0; else { gotstat = 1; ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO; } /* * Changing the ownership probably won't succeed, unless we're root * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting * the mode; current BSD behavior is to remove all setuid bits on * chown. If chown fails, lose setuid/setgid bits. */ if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid) if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) : (islink ? lchown(pThis->to.p_path, fs->st_uid, fs->st_gid) : chown(pThis->to.p_path, fs->st_uid, fs->st_gid))) { if (errno != EPERM) { warn(pThis->pCtx, "chown: %s", pThis->to.p_path); rval = 1; } fs->st_mode &= ~(S_ISUID | S_ISGID); } if (!gotstat || fs->st_mode != ts.st_mode) if (fdval ? fchmod(fd, fs->st_mode) : (islink ? lchmod(pThis->to.p_path, fs->st_mode) : chmod(pThis->to.p_path, fs->st_mode))) { warn(pThis->pCtx, "chmod: %s", pThis->to.p_path); rval = 1; } #ifdef HAVE_ST_FLAGS if (!gotstat || fs->st_flags != ts.st_flags) if (fdval ? fchflags(fd, fs->st_flags) : (islink ? (errno = ENOSYS) : chflags(pThis->to.p_path, fs->st_flags))) { warn(pThis->pCtx, "chflags: %s", pThis->to.p_path); rval = 1; } #endif return (rval); } kbuild-3686/src/kmk/kmkbuiltin/haikufakes.h0000664000175000017500000000223015053010074020712 0ustar locutuslocutus/* $Id: haikufakes.h 2656 2012-09-10 20:39:16Z bird $ */ /** @file * Unix/BSD fakes for Haiku. */ /* * Copyright (c) 2005-2012 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ #ifndef ___haikufakes_h #define ___haikufakes_h #define EX_OK 0 #define EX_OSERR 1 #define EX_NOUSER 1 #define EX_USAGE 1 #define EX_TEMPFAIL 1 #define EX_SOFTWARE 1 #define lutimes(path, tvs) utimes(path, tvs) #define lchmod haiku_lchmod extern int haiku_lchmod(const char *pszPath, mode_t mode); #endif kbuild-3686/src/kmk/kmkbuiltin/mv.c0000664000175000017500000003527015053010074017226 0ustar locutuslocutus/*- * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Ken Smith of The State University of New York at Buffalo. * * 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. * 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 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1989, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)mv.c 8.2 (Berkeley) 4/2/94"; #endif /* not lint */ #endif #if 0 #include __FBSDID("$FreeBSD: src/bin/mv/mv.c,v 1.46 2005/09/05 04:36:08 csjp Exp $"); #endif /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #define FAKES_NO_GETOPT_H /* bird */ #include "config.h" #include #ifndef _MSC_VER # ifdef CROSS_DEVICE_MOVE # include # endif # include # include # include # if !defined(__HAIKU__) && !defined(__gnu_hurd__) # include # endif #endif #include #include "err.h" #include #include #include #include #include #include #include #include #include #ifndef __HAIKU__ # include #endif #include #include "getopt_r.h" #ifdef __sun__ # include "solfakes.h" #endif #ifdef __HAIKU__ # include "haikufakes.h" #endif #ifdef _MSC_VER # include "mscfakes.h" #endif #include "kmkbuiltin.h" /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ typedef struct MVINSTANCE { PKMKBUILTINCTX pCtx; int fflg, iflg, nflg, vflg; } MVINSTANCE; typedef MVINSTANCE *PMVINSTANCE; /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; /********************************************************************************************************************************* * Internal Functions * *********************************************************************************************************************************/ extern void bsd_strmode(mode_t mode, char *p); /* strmode.c */ static int do_move(PMVINSTANCE, char *, char *); #if 0 // def CROSS_DEVICE_MOVE static int fastcopy(char *, char *, struct stat *); static int copy(char *, char *); #endif static int usage(PKMKBUILTINCTX, int); int kmk_builtin_mv(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { MVINSTANCE This; struct getopt_state_r gos; size_t baselen, len; int rval; char *p, *endp; struct stat sb; int ch; char path[PATH_MAX]; /* Initialize instance. */ This.pCtx = pCtx; This.fflg = 0; This.iflg = 0; This.nflg = 0; This.vflg = 0; getopt_initialize_r(&gos, argc, argv, "finv", long_options, envp, pCtx); while ((ch = getopt_long_r(&gos, NULL)) != -1) switch (ch) { case 'i': This.iflg = 1; This.fflg = This.nflg = 0; break; case 'f': This.fflg = 1; This.iflg = This.nflg = 0; break; case 'n': This.nflg = 1; This.fflg = This.iflg = 0; break; case 'v': This.vflg = 1; break; case 261: usage(pCtx, 0); return 0; case 262: return kbuild_version(argv[0]); default: return usage(pCtx, 1); } argc -= gos.optind; argv += gos.optind; if (argc < 2) return usage(pCtx, 1); /* * If the stat on the target fails or the target isn't a directory, * try the move. More than 2 arguments is an error in this case. */ if (stat(argv[argc - 1], &sb) || !S_ISDIR(sb.st_mode)) { if (argc > 2) return usage(pCtx, 1); return do_move(&This, argv[0], argv[1]); } /* It's a directory, move each file into it. */ baselen = strlen(argv[argc - 1]); if (baselen > sizeof(path) - 1) return errx(pCtx, 1, "%s: destination pathname too long", *argv); memcpy(path, argv[argc - 1], baselen); endp = &path[baselen]; *endp = '\0'; #if defined(_MSC_VER) || defined(__EMX__) if (!baselen || (*(endp - 1) != '/' && *(endp - 1) != '\\' && *(endp - 1) != ':')) { #else if (!baselen || *(endp - 1) != '/') { #endif *endp++ = '/'; ++baselen; } for (rval = 0; --argc; ++argv) { /* * Find the last component of the source pathname. It * may have trailing slashes. */ p = *argv + strlen(*argv); #if defined(_MSC_VER) || defined(__EMX__) while (p != *argv && (p[-1] == '/' || p[-1] == '\\')) --p; while (p != *argv && p[-1] != '/' && p[-1] != '/' && p[-1] != ':') --p; #else while (p != *argv && p[-1] == '/') --p; while (p != *argv && p[-1] != '/') --p; #endif if ((baselen + (len = strlen(p))) >= PATH_MAX) { warnx(pCtx, "%s: destination pathname too long", *argv); rval = 1; } else { memmove(endp, p, (size_t)len + 1); if (do_move(&This, *argv, path)) rval = 1; } } return rval; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_mv", NULL }; return kmk_builtin_mv(argc, argv, envp, &Ctx); } #endif static int do_move(PMVINSTANCE pThis, char *from, char *to) { struct stat sb; int ask, ch, first; char modep[15]; /* * Check access. If interactive and file exists, ask user if it * should be replaced. Otherwise if file exists but isn't writable * make sure the user wants to clobber it. */ if (!pThis->fflg && !access(to, F_OK)) { /* prompt only if source exist */ if (lstat(from, &sb) == -1) { warn(pThis->pCtx, "%s", from); return (1); } #define YESNO "(y/n [n]) " ask = 0; if (pThis->nflg) { if (pThis->vflg) kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s not overwritten\n", to); return (0); } else if (pThis->iflg) { (void)fprintf(stderr, "overwrite %s? %s", to, YESNO); ask = 1; } else if (access(to, W_OK) && !stat(to, &sb)) { bsd_strmode(sb.st_mode, modep); #if 0 /* probably not thread safe, also BSDism. */ (void)fprintf(stderr, "override %s%s%s/%s for %s? %s", modep + 1, modep[9] == ' ' ? "" : " ", user_from_uid((unsigned long)sb.st_uid, 0), group_from_gid((unsigned long)sb.st_gid, 0), to, YESNO); #else (void)fprintf(stderr, "override %s%s%lu/%lu for %s? %s", modep + 1, modep[9] == ' ' ? "" : " ", (unsigned long)sb.st_uid, (unsigned long)sb.st_gid, to, YESNO); #endif ask = 1; } if (ask) { fflush(stderr); first = ch = getchar(); while (ch != '\n' && ch != EOF) ch = getchar(); if (first != 'y' && first != 'Y') { kmk_builtin_ctx_printf(pThis->pCtx, 1, "not overwritten\n"); return (0); } } } if (!rename(from, to)) { if (pThis->vflg) kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s -> %s\n", from, to); return (0); } #ifdef _MSC_VER if (errno == EEXIST) { remove(to); if (!rename(from, to)) { if (pThis->vflg) kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s -> %s\n", from, to); return (0); } } #endif if (errno == EXDEV) { #if 1 //ndef CROSS_DEVICE_MOVE warnx(pThis->pCtx, "cannot move `%s' to a different device: `%s'", from, to); return (1); #else struct statfs sfs; char path[PATH_MAX]; /* * If the source is a symbolic link and is on another * filesystem, it can be recreated at the destination. */ if (lstat(from, &sb) == -1) { warn(pThis->pCtx, "%s", from); return (1); } if (!S_ISLNK(sb.st_mode)) { /* Can't mv(1) a mount point. */ if (realpath(from, path) == NULL) { warnx(pThis->pCtx, "cannot resolve %s: %s", from, path); return (1); } if (!statfs(path, &sfs) && !strcmp(path, sfs.f_mntonname)) { warnx(pThis->pCtx, "cannot rename a mount point"); return (1); } } #endif } else { warn(pThis->pCtx, "rename %s to %s", from, to); return (1); } #if 0//def CROSS_DEVICE_MOVE /* * If rename fails because we're trying to cross devices, and * it's a regular file, do the copy internally; otherwise, use * cp and rm. */ if (lstat(from, &sb)) { warn(pThis->pCtx, "%s", from); return (1); } return (S_ISREG(sb.st_mode) ? fastcopy(pThis, from, to, &sb) : copy(pThis, from, to)); #endif } #if 0 //def CROSS_DEVICE_MOVE - using static buffers and fork. int static fastcopy(char *from, char *to, struct stat *sbp) { struct timeval tval[2]; static u_int blen; static char *bp; mode_t oldmode; int nread, from_fd, to_fd; acl_t acl; if ((from_fd = open(from, O_RDONLY | KMK_OPEN_NO_INHERIT, 0)) < 0) { warn("%s", from); return (1); } if (blen < sbp->st_blksize) { if (bp != NULL) free(bp); if ((bp = malloc((size_t)sbp->st_blksize)) == NULL) { blen = 0; warnx("malloc failed"); return (1); } blen = sbp->st_blksize; } while ((to_fd = open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY | KMK_OPEN_NO_INHERIT, 0)) < 0) { if (errno == EEXIST && unlink(to) == 0) continue; warn("%s", to); (void)close(from_fd); return (1); } while ((nread = read(from_fd, bp, (size_t)blen)) > 0) if (write(to_fd, bp, (size_t)nread) != nread) { warn("%s", to); goto err; } if (nread < 0) { warn("%s", from); err: if (unlink(to)) warn("%s: remove", to); (void)close(from_fd); (void)close(to_fd); return (1); } oldmode = sbp->st_mode & ALLPERMS; if (fchown(to_fd, sbp->st_uid, sbp->st_gid)) { warn("%s: set owner/group (was: %lu/%lu)", to, (u_long)sbp->st_uid, (u_long)sbp->st_gid); if (oldmode & (S_ISUID | S_ISGID)) { warnx( "%s: owner/group changed; clearing suid/sgid (mode was 0%03o)", to, oldmode); sbp->st_mode &= ~(S_ISUID | S_ISGID); } } /* * POSIX 1003.2c states that if _POSIX_ACL_EXTENDED is in effect * for dest_file, then it's ACLs shall reflect the ACLs of the * source_file. */ if (fpathconf(to_fd, _PC_ACL_EXTENDED) == 1 && fpathconf(from_fd, _PC_ACL_EXTENDED) == 1) { acl = acl_get_fd(from_fd); if (acl == NULL) warn("failed to get acl entries while setting %s", from); else if (acl_set_fd(to_fd, acl) < 0) warn("failed to set acl entries for %s", to); } (void)close(from_fd); if (fchmod(to_fd, sbp->st_mode)) warn("%s: set mode (was: 0%03o)", to, oldmode); /* * XXX * NFS doesn't support chflags; ignore errors unless there's reason * to believe we're losing bits. (Note, this still won't be right * if the server supports flags and we were trying to *remove* flags * on a file that we copied, i.e., that we didn't create.) */ errno = 0; if (fchflags(to_fd, (u_long)sbp->st_flags)) if (errno != EOPNOTSUPP || sbp->st_flags != 0) warn("%s: set flags (was: 0%07o)", to, sbp->st_flags); tval[0].tv_sec = sbp->st_atime; tval[1].tv_sec = sbp->st_mtime; tval[0].tv_usec = tval[1].tv_usec = 0; if (utimes(to, tval)) warn("%s: set times", to); if (close(to_fd)) { warn("%s", to); return (1); } if (unlink(from)) { warn("%s: remove", from); return (1); } if (vflg) kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s -> %s\n", from, to); return (0); } int copy(char *from, char *to) { int pid, status; if ((pid = fork()) == 0) { execl(_PATH_CP, "mv", vflg ? "-PRpv" : "-PRp", "--", from, to, (char *)NULL); warn("%s", _PATH_CP); _exit(1); } if (waitpid(pid, &status, 0) == -1) { warn("%s: waitpid", _PATH_CP); return (1); } if (!WIFEXITED(status)) { warnx("%s: did not terminate normally", _PATH_CP); return (1); } if (WEXITSTATUS(status)) { warnx("%s: terminated with %d (non-zero) status", _PATH_CP, WEXITSTATUS(status)); return (1); } if (!(pid = vfork())) { execl(_PATH_RM, "mv", "-rf", "--", from, (char *)NULL); warn("%s", _PATH_RM); _exit(1); } if (waitpid(pid, &status, 0) == -1) { warn("%s: waitpid", _PATH_RM); return (1); } if (!WIFEXITED(status)) { warnx("%s: did not terminate normally", _PATH_RM); return (1); } if (WEXITSTATUS(status)) { warnx("%s: terminated with %d (non-zero) status", _PATH_RM, WEXITSTATUS(status)); return (1); } return (0); } #endif /* CROSS_DEVICE_MOVE */ static int usage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s [-f | -i | -n] [-v] source target\n" " or: %s [-f | -i | -n] [-v] source ... directory\n" " or: %s --help\n" " or: %s --version\n", pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); return EX_USAGE; } kbuild-3686/src/kmk/kmkbuiltin/common-env-and-cwd-opt.c0000664000175000017500000004773315053010075023005 0ustar locutuslocutus/* $Id: common-env-and-cwd-opt.c 3332 2020-04-19 23:08:16Z bird $ */ /** @file * kMk Builtin command - Commmon environment and CWD option handling code. */ /* * Copyright (c) 2007-2016 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include "kmkbuiltin.h" #include "err.h" /** The environment variable compare function. * We must use case insensitive compare on windows (Path vs PATH). */ #ifdef KBUILD_OS_WINDOWS # define KSUBMIT_ENV_NCMP _strnicmp #else # define KSUBMIT_ENV_NCMP strncmp #endif /** * Duplicates a read-only enviornment vector. * * @returns The duplicate enviornment. * @param pCtx The built-in command context. * @param papszEnv The read-only vector. * @param cEnvVars The number of variables. * @param pcAllocatedEnvVars The allocated papszEnv size. This is zero on * input and non-zero on successful return. * @param cVerbosity The verbosity level. */ static char **kBuiltinOptEnvDuplicate(PKMKBUILTINCTX pCtx, char **papszEnv, unsigned cEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity) { unsigned cAllocatedEnvVars = (cEnvVars + 2 + 0xf) & ~(unsigned)0xf; char **papszEnvNew = malloc(cAllocatedEnvVars * sizeof(papszEnvNew[0])); assert(*pcAllocatedEnvVars == 0); if (papszEnvNew) { unsigned i; for (i = 0; i < cEnvVars; i++) { papszEnvNew[i] = strdup(papszEnv[i]); if (!papszEnvNew) { while (i-- > 0) free(papszEnvNew[i]); free(papszEnvNew); errx(pCtx, 1, "out of memory for duplicating environment variables!", i); return NULL; } } papszEnvNew[i] = NULL; *pcAllocatedEnvVars = cAllocatedEnvVars; } else errx(pCtx, 1, "out of memory for duplicating environment vector!"); return papszEnvNew; } /** * Common worker for kBuiltinOptEnvSet and kBuiltinOptEnvAppendPrepend that adds * a new variable to the environment. * * @returns 0 on success, non-zero exit code on error. * @param pCtx The built-in command context. * @param papszEnv The environment vector. * @param pcEnvVars Pointer to the variable holding the number of * environment variables held by @a papszEnv. * @param pcAllocatedEnvVars Pointer to the variable holding max size of the * environment vector. * @param cVerbosity The verbosity level. * @param pszValue The var=value string to apply. */ static int kBuiltinOptEnvAddVar(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue) { /* Append new variable. We probably need to resize the vector. */ char **papszEnv = *ppapszEnv; unsigned cEnvVars = *pcEnvVars; if ((cEnvVars + 2) > *pcAllocatedEnvVars) { *pcAllocatedEnvVars = (cEnvVars + 2 + 0xf) & ~(unsigned)0xf; papszEnv = (char **)realloc(papszEnv, *pcAllocatedEnvVars * sizeof(papszEnv[0])); if (!papszEnv) return errx(pCtx, 1, "out of memory growing environment vector!"); *ppapszEnv = papszEnv; } papszEnv[cEnvVars] = strdup(pszValue); if (!papszEnv[cEnvVars]) return errx(pCtx, 1, "out of memory adding environment variable!"); papszEnv[++cEnvVars] = NULL; *pcEnvVars = cEnvVars; if (cVerbosity > 0) warnx(pCtx, "added '%s'", papszEnv[cEnvVars - 1]); return 0; } /** * Common worker for kBuiltinOptEnvSet and kBuiltinOptEnvAppendPrepend that * remove duplicates. * * @returns 0 on success, non-zero exit code on error. * @param pCtx The built-in command context. * @param papszEnv The environment vector. * @param cEnvVars Number of environment variables. * @param cVerbosity The verbosity level. * @param pszValue The var=value string to apply. * @param cchVar The length of the variable part of @a pszValue. * @param iEnvVar Where to start searching after. */ static int kBuiltinOptEnvRemoveDuplicates(PKMKBUILTINCTX pCtx, char **papszEnv, unsigned cEnvVars, int cVerbosity, const char *pszValue, size_t cchVar, unsigned iEnvVar) { for (iEnvVar++; iEnvVar < cEnvVars; iEnvVar++) if ( KSUBMIT_ENV_NCMP(papszEnv[iEnvVar], pszValue, cchVar) == 0 && papszEnv[iEnvVar][cchVar] == '=') { if (cVerbosity > 0) warnx(pCtx, "removing duplicate '%s'", papszEnv[iEnvVar]); free(papszEnv[iEnvVar]); cEnvVars--; if (iEnvVar != cEnvVars) papszEnv[iEnvVar] = papszEnv[cEnvVars]; papszEnv[cEnvVars] = NULL; iEnvVar--; } return 0; } /** * Handles the --set var=value option. * * @returns 0 on success, non-zero exit code on error. * @param pCtx The built-in command context. * @param ppapszEnv The environment vector pointer. * @param pcEnvVars Pointer to the variable holding the number of * environment variables held by @a papszEnv. * @param pcAllocatedEnvVars Pointer to the variable holding max size of the * environment vector. * @param cVerbosity The verbosity level. * @param pszValue The var=value string to apply. */ int kBuiltinOptEnvSet(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue) { const char *pszEqual = strchr(pszValue, '='); if (pszEqual) { char **papszEnv = *ppapszEnv; unsigned iEnvVar; unsigned cEnvVars = *pcEnvVars; size_t const cchVar = pszEqual - pszValue; if (!*pcAllocatedEnvVars) { papszEnv = kBuiltinOptEnvDuplicate(pCtx, papszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity); if (!papszEnv) return errx(pCtx, 1, "out of memory duplicating enviornment (setenv)!"); *ppapszEnv = papszEnv; } for (iEnvVar = 0; iEnvVar < cEnvVars; iEnvVar++) { char *pszCur = papszEnv[iEnvVar]; if ( KSUBMIT_ENV_NCMP(pszCur, pszValue, cchVar) == 0 && pszCur[cchVar] == '=') { if (cVerbosity > 0) warnx(pCtx, "replacing '%s' with '%s'", papszEnv[iEnvVar], pszValue); free(papszEnv[iEnvVar]); papszEnv[iEnvVar] = strdup(pszValue); if (!papszEnv[iEnvVar]) return errx(pCtx, 1, "out of memory for modified environment variable!"); return kBuiltinOptEnvRemoveDuplicates(pCtx, papszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar); } } return kBuiltinOptEnvAddVar(pCtx, ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue); } return errx(pCtx, 1, "Missing '=': -E %s", pszValue); } /** * Common worker for kBuiltinOptEnvAppend and kBuiltinOptEnvPrepend. * * @returns 0 on success, non-zero exit code on error. * @param pCtx The built-in command context. * @param ppapszEnv The environment vector pointer. * @param pcEnvVars Pointer to the variable holding the number of * environment variables held by @a papszEnv. * @param pcAllocatedEnvVars Pointer to the variable holding max size of the * environment vector. * @param cVerbosity The verbosity level. * @param pszValue The var=value string to apply. */ static int kBuiltinOptEnvAppendPrepend(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue, int fAppend) { const char *pszEqual = strchr(pszValue, '='); if (pszEqual) { char **papszEnv = *ppapszEnv; unsigned iEnvVar; unsigned cEnvVars = *pcEnvVars; size_t const cchVar = pszEqual - pszValue; if (!*pcAllocatedEnvVars) { papszEnv = kBuiltinOptEnvDuplicate(pCtx, papszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity); if (!papszEnv) return errx(pCtx, 1, "out of memory duplicating environment (append)!"); *ppapszEnv = papszEnv; } for (iEnvVar = 0; iEnvVar < cEnvVars; iEnvVar++) { char *pszCur = papszEnv[iEnvVar]; if ( KSUBMIT_ENV_NCMP(pszCur, pszValue, cchVar) == 0 && pszCur[cchVar] == '=') { size_t cchOldValue = strlen(pszCur) - cchVar - 1; size_t cchNewValue = strlen(pszValue) - cchVar - 1; char *pszNew = malloc(cchVar + 1 + cchOldValue + cchNewValue + 1); if (!pszNew) return errx(pCtx, 1, "out of memory appending to environment variable!"); if (fAppend) { memcpy(pszNew, pszCur, cchVar + 1 + cchOldValue); memcpy(&pszNew[cchVar + 1 + cchOldValue], &pszValue[cchVar + 1], cchNewValue + 1); } else { memcpy(pszNew, pszCur, cchVar + 1); /* preserve variable name case */ memcpy(&pszNew[cchVar + 1], &pszValue[cchVar + 1], cchNewValue); memcpy(&pszNew[cchVar + 1 + cchNewValue], &pszCur[cchVar + 1], cchOldValue + 1); } if (cVerbosity > 0) warnx(pCtx, "replacing '%s' with '%s'", pszCur, pszNew); free(pszCur); papszEnv[iEnvVar] = pszNew; return kBuiltinOptEnvRemoveDuplicates(pCtx, papszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar); } } return kBuiltinOptEnvAddVar(pCtx, ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue); } return errx(pCtx, 1, "Missing '=': -%c %s", fAppend ? 'A' : 'D', pszValue); } /** * Handles the --append var=value option. * * @returns 0 on success, non-zero exit code on error. * @param pCtx The built-in command context. * @param ppapszEnv The environment vector pointer. * @param pcEnvVars Pointer to the variable holding the number of * environment variables held by @a papszEnv. * @param pcAllocatedEnvVars Pointer to the variable holding max size of the * environment vector. * @param cVerbosity The verbosity level. * @param pszValue The var=value string to apply. */ int kBuiltinOptEnvAppend(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue) { return kBuiltinOptEnvAppendPrepend(pCtx, ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue, 1 /*fAppend*/); } /** * Handles the --prepend var=value option. * * @returns 0 on success, non-zero exit code on error. * @param pCtx The built-in command context. * @param ppapszEnv The environment vector pointer. * @param pcEnvVars Pointer to the variable holding the number of * environment variables held by @a papszEnv. * @param pcAllocatedEnvVars Pointer to the variable holding max size of the * environment vector. * @param cVerbosity The verbosity level. * @param pszValue The var=value string to apply. */ int kBuiltinOptEnvPrepend(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue) { return kBuiltinOptEnvAppendPrepend(pCtx, ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue, 0 /*fAppend*/); } /** * Handles the --unset var option. * * @returns 0 on success, non-zero exit code on error. * @param pCtx The built-in command context. * @param ppapszEnv The environment vector pointer. * @param pcEnvVars Pointer to the variable holding the number of * environment variables held by @a papszEnv. * @param pcAllocatedEnvVars Pointer to the size of the vector allocation. * The size is zero when read-only (CRT, GNU make) * environment. * @param cVerbosity The verbosity level. * @param pszVarToRemove The name of the variable to remove. */ int kBuiltinOptEnvUnset(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszVarToRemove) { if (strchr(pszVarToRemove, '=') == NULL) { char **papszEnv = *ppapszEnv; unsigned cRemoved = 0; size_t const cchVar = strlen(pszVarToRemove); unsigned cEnvVars = *pcEnvVars; unsigned iEnvVar; for (iEnvVar = 0; iEnvVar < cEnvVars; iEnvVar++) if ( KSUBMIT_ENV_NCMP(papszEnv[iEnvVar], pszVarToRemove, cchVar) == 0 && papszEnv[iEnvVar][cchVar] == '=') { if (cVerbosity > 0) warnx(pCtx, !cRemoved ? "removing '%s'" : "removing duplicate '%s'", papszEnv[iEnvVar]); if (!*pcAllocatedEnvVars) { papszEnv = kBuiltinOptEnvDuplicate(pCtx, papszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity); if (!papszEnv) return errx(pCtx, 1, "out of memory duplicating environment (unset)!"); *ppapszEnv = papszEnv; } free(papszEnv[iEnvVar]); cEnvVars--; if (iEnvVar != cEnvVars) papszEnv[iEnvVar] = papszEnv[cEnvVars]; papszEnv[cEnvVars] = NULL; cRemoved++; iEnvVar--; } *pcEnvVars = cEnvVars; if (cVerbosity > 0 && !cRemoved) warnx(pCtx, "not found '%s'", pszVarToRemove); } else return errx(pCtx, 1, "Found invalid variable name character '=' in: -U %s", pszVarToRemove); return 0; } /** * Handles the --zap-env & --ignore-environment options. * * @returns 0 on success, non-zero exit code on error. * @param pCtx The built-in command context. * @param ppapszEnv The environment vector pointer. * @param pcEnvVars Pointer to the variable holding the number of * environment variables held by @a papszEnv. * @param pcAllocatedEnvVars Pointer to the size of the vector allocation. * The size is zero when read-only (CRT, GNU make) * environment. * @param cVerbosity The verbosity level. */ int kBuiltinOptEnvZap(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity) { if (*pcAllocatedEnvVars > 0) { char **papszEnv = *ppapszEnv; unsigned i = *pcEnvVars; while (i-- > 0) { free(papszEnv[i]); papszEnv[i] = NULL; } } else { char **papszEnv = calloc(4, sizeof(char *)); if (!papszEnv) return err(pCtx, 1, "out of memory!"); *ppapszEnv = papszEnv; *pcAllocatedEnvVars = 4; } *pcEnvVars = 0; return 0; } /** * Cleans up afterwards, if necessary. * * @param ppapszEnv The environment vector pointer. * @param cEnvVars The number of variables in the vector. * @param pcAllocatedEnvVars Pointer to the size of the vector allocation. * The size is zero when read-only (CRT, GNU make) * environment. */ void kBuiltinOptEnvCleanup(char ***ppapszEnv, unsigned cEnvVars, unsigned *pcAllocatedEnvVars) { char **papszEnv = *ppapszEnv; *ppapszEnv = NULL; if (*pcAllocatedEnvVars > 0) { *pcAllocatedEnvVars = 0; while (cEnvVars-- > 0) { free(papszEnv[cEnvVars]); papszEnv[cEnvVars] = NULL; } free(papszEnv); } } /** * Handles the --chdir dir option. * * @returns 0 on success, non-zero exit code on error. * @param pCtx The built-in command context. * @param pszCwd The CWD buffer. Contains current CWD on input, * modified by @a pszValue on output. * @param cbCwdBuf The size of the CWD buffer. * @param pszValue The --chdir value to apply. */ int kBuiltinOptChDir(PKMKBUILTINCTX pCtx, char *pszCwd, size_t cbCwdBuf, const char *pszValue) { size_t cchNewCwd = strlen(pszValue); size_t offDst; if (cchNewCwd) { #ifdef HAVE_DOS_PATHS if (*pszValue == '/' || *pszValue == '\\') { if (pszValue[1] == '/' || pszValue[1] == '\\') offDst = 0; /* UNC */ else if (pszCwd[1] == ':' && isalpha(pszCwd[0])) offDst = 2; /* Take drive letter from CWD. */ else return errx(pCtx, 1, "UNC relative CWD not implemented: cur='%s' new='%s'", pszCwd, pszValue); } else if ( pszValue[1] == ':' && isalpha(pszValue[0])) { if (pszValue[2] == '/'|| pszValue[2] == '\\') offDst = 0; /* DOS style absolute path. */ else if ( pszCwd[1] == ':' && tolower(pszCwd[0]) == tolower(pszValue[0]) ) { pszValue += 2; /* Same drive as CWD, append drive relative path from value. */ cchNewCwd -= 2; offDst = strlen(pszCwd); } else { /* Get current CWD on the specified drive and append value. */ int iDrive = tolower(pszValue[0]) - 'a' + 1; if (!_getdcwd(iDrive, pszCwd, cbCwdBuf)) return err(pCtx, 1, "_getdcwd(%d,,) failed", iDrive); pszValue += 2; cchNewCwd -= 2; } } #else if (*pszValue == '/') offDst = 0; #endif else offDst = strlen(pszCwd); /* Relative path, append to the existing CWD value. */ /* Do the copying. */ #ifdef HAVE_DOS_PATHS if (offDst > 0 && pszCwd[offDst - 1] != '/' && pszCwd[offDst - 1] != '\\') #else if (offDst > 0 && pszCwd[offDst - 1] != '/') #endif pszCwd[offDst++] = '/'; if (offDst + cchNewCwd >= cbCwdBuf) return errx(pCtx, 1, "Too long CWD: %*.*s%s", offDst, offDst, pszCwd, pszValue); memcpy(&pszCwd[offDst], pszValue, cchNewCwd + 1); } /* else: relative, no change - quitely ignore. */ return 0; } kbuild-3686/src/kmk/kmkbuiltin/expr.c0000664000175000017500000002713315053010075017562 0ustar locutuslocutus/* $OpenBSD: expr.c,v 1.17 2006/06/21 18:28:24 deraadt Exp $ */ /* $NetBSD: expr.c,v 1.3.6.1 1996/06/04 20:41:47 cgd Exp $ */ /* * Written by J.T. Conklin . * Public domain. */ #include "config.h" #include #include #include #include #include #ifdef KMK_WITH_REGEX #include #endif #include #include #ifdef HAVE_ALLOCA_H # include #endif #include "err.h" #include "kmkbuiltin.h" typedef struct EXPRINSTANCE *PEXPRINSTANCE; static struct val *make_int(PEXPRINSTANCE, int); static struct val *make_str(PEXPRINSTANCE, char *); static void free_value(PEXPRINSTANCE, struct val *); static int is_integer(struct val *, int *); static int to_integer(PEXPRINSTANCE, struct val *); static void to_string(PEXPRINSTANCE, struct val *); static int is_zero_or_null(PEXPRINSTANCE, struct val *); static void nexttoken(PEXPRINSTANCE, int); static struct val *eval6(PEXPRINSTANCE); static struct val *eval5(PEXPRINSTANCE); static struct val *eval4(PEXPRINSTANCE); static struct val *eval3(PEXPRINSTANCE); static struct val *eval2(PEXPRINSTANCE); static struct val *eval1(PEXPRINSTANCE); static struct val *eval0(PEXPRINSTANCE); enum token { OR, AND, EQ, LT, GT, ADD, SUB, MUL, DIV, MOD, MATCH, RP, LP, NE, LE, GE, OPERAND, EOI }; struct val { enum { integer, string } type; union { char *s; int i; } u; }; typedef struct EXPRINSTANCE { PKMKBUILTINCTX pCtx; enum token token; struct val *tokval; char **av; jmp_buf g_expr_jmp; void **recorded_allocations; int num_recorded_allocations; } EXPRINSTANCE; static void expr_mem_record_alloc(PEXPRINSTANCE pThis, void *ptr) { if (!(pThis->num_recorded_allocations & 31)) { void *newtab = realloc(pThis->recorded_allocations, (pThis->num_recorded_allocations + 33) * sizeof(void *)); if (!newtab) longjmp(pThis->g_expr_jmp, err(pThis->pCtx, 3, NULL)); pThis->recorded_allocations = (void **)newtab; } pThis->recorded_allocations[pThis->num_recorded_allocations++] = ptr; } static void expr_mem_record_free(PEXPRINSTANCE pThis, void *ptr) { int i = pThis->num_recorded_allocations; while (i-- > 0) if (pThis->recorded_allocations[i] == ptr) { pThis->num_recorded_allocations--; pThis->recorded_allocations[i] = pThis->recorded_allocations[pThis->num_recorded_allocations]; return; } assert(i >= 0); } static void expr_mem_init(PEXPRINSTANCE pThis) { pThis->num_recorded_allocations = 0; pThis->recorded_allocations = NULL; } static void expr_mem_cleanup(PEXPRINSTANCE pThis) { if (pThis->recorded_allocations) { while (pThis->num_recorded_allocations-- > 0) free(pThis->recorded_allocations[pThis->num_recorded_allocations]); free(pThis->recorded_allocations); pThis->recorded_allocations = NULL; } } static struct val * make_int(PEXPRINSTANCE pThis, int i) { struct val *vp; vp = (struct val *) malloc(sizeof(*vp)); if (vp == NULL) longjmp(pThis->g_expr_jmp, err(pThis->pCtx, 3, NULL)); expr_mem_record_alloc(pThis, vp); vp->type = integer; vp->u.i = i; return vp; } static struct val * make_str(PEXPRINSTANCE pThis, char *s) { struct val *vp; vp = (struct val *) malloc(sizeof(*vp)); if (vp == NULL || ((vp->u.s = strdup(s)) == NULL)) longjmp(pThis->g_expr_jmp, err(pThis->pCtx, 3, NULL)); expr_mem_record_alloc(pThis, vp->u.s); expr_mem_record_alloc(pThis, vp); vp->type = string; return vp; } static void free_value(PEXPRINSTANCE pThis, struct val *vp) { if (vp->type == string) { expr_mem_record_free(pThis, vp->u.s); free(vp->u.s); } free(vp); expr_mem_record_free(pThis, vp); } /* determine if vp is an integer; if so, return it's value in *r */ static int is_integer(struct val *vp, int *r) { char *s; int neg; int i; if (vp->type == integer) { *r = vp->u.i; return 1; } /* * POSIX.2 defines an "integer" as an optional unary minus * followed by digits. */ s = vp->u.s; i = 0; neg = (*s == '-'); if (neg) s++; while (*s) { if (!isdigit(*s)) return 0; i *= 10; i += *s - '0'; s++; } if (neg) i *= -1; *r = i; return 1; } /* coerce to vp to an integer */ static int to_integer(PEXPRINSTANCE pThis, struct val *vp) { int r; if (vp->type == integer) return 1; if (is_integer(vp, &r)) { expr_mem_record_free(pThis, vp->u.s); free(vp->u.s); vp->u.i = r; vp->type = integer; return 1; } return 0; } /* coerce to vp to an string */ static void to_string(PEXPRINSTANCE pThis, struct val *vp) { char *tmp; if (vp->type == string) return; if (asprintf(&tmp, "%d", vp->u.i) == -1) longjmp(pThis->g_expr_jmp, err(pThis->pCtx, 3, NULL)); expr_mem_record_alloc(pThis, tmp); vp->type = string; vp->u.s = tmp; } static int is_zero_or_null(PEXPRINSTANCE pThis, struct val *vp) { if (vp->type == integer) { return (vp->u.i == 0); } else { return (*vp->u.s == 0 || (to_integer(pThis, vp) && vp->u.i == 0)); } /* NOTREACHED */ } static void nexttoken(PEXPRINSTANCE pThis, int pat) { char *p; if ((p = *pThis->av) == NULL) { pThis->token = EOI; return; } pThis->av++; if (pat == 0 && p[0] != '\0') { if (p[1] == '\0') { const char *x = "|&=<>+-*/%:()"; char *i; /* index */ if ((i = strchr(x, *p)) != NULL) { pThis->token = i - x; return; } } else if (p[1] == '=' && p[2] == '\0') { switch (*p) { case '<': pThis->token = LE; return; case '>': pThis->token = GE; return; case '!': pThis->token = NE; return; } } } pThis->tokval = make_str(pThis, p); pThis->token = OPERAND; return; } #ifdef __GNUC__ __attribute__((noreturn)) #endif #ifdef _MSC_VER __declspec(noreturn) #endif static void error(PEXPRINSTANCE pThis) { longjmp(pThis->g_expr_jmp, errx(pThis->pCtx, 2, "syntax error")); /* NOTREACHED */ } static struct val * eval6(PEXPRINSTANCE pThis) { struct val *v; if (pThis->token == OPERAND) { nexttoken(pThis, 0); return pThis->tokval; } else if (pThis->token == RP) { nexttoken(pThis, 0); v = eval0(pThis); if (pThis->token != LP) { error(pThis); /* NOTREACHED */ } nexttoken(pThis, 0); return v; } else { error(pThis); } /* NOTREACHED */ } /* Parse and evaluate match (regex) expressions */ static struct val * eval5(PEXPRINSTANCE pThis) { #ifdef KMK_WITH_REGEX regex_t rp; regmatch_t rm[2]; char errbuf[256]; int eval; struct val *r; struct val *v; #endif struct val *l; l = eval6(pThis); while (pThis->token == MATCH) { #ifdef KMK_WITH_REGEX nexttoken(pThis, 1); r = eval6(pThis); /* coerce to both arguments to strings */ to_string(pThis, l); to_string(pThis, r); /* compile regular expression */ if ((eval = regcomp(&rp, r->u.s, 0)) != 0) { regerror(eval, &rp, errbuf, sizeof(errbuf)); longjmp(pThis->g_expr_jmp, errx(pThis->pCtx, 2, "%s", errbuf)); } /* compare string against pattern -- remember that patterns are anchored to the beginning of the line */ if (regexec(&rp, l->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) { if (rm[1].rm_so >= 0) { *(l->u.s + rm[1].rm_eo) = '\0'; v = make_str(pThis, l->u.s + rm[1].rm_so); } else { v = make_int(pThis, (int)(rm[0].rm_eo - rm[0].rm_so)); } } else { if (rp.re_nsub == 0) { v = make_int(pThis, 0); } else { v = make_str(pThis, ""); } } /* free arguments and pattern buffer */ free_value(pThis, l); free_value(pThis, r); regfree(&rp); l = v; #else longjmp(pThis->g_expr_jmp, errx(pThis->pCtx, 2, "regex not supported, sorry.")); #endif } return l; } /* Parse and evaluate multiplication and division expressions */ static struct val * eval4(PEXPRINSTANCE pThis) { struct val *l, *r; enum token op; l = eval5(pThis); while ((op = pThis->token) == MUL || op == DIV || op == MOD) { nexttoken(pThis, 0); r = eval5(pThis); if (!to_integer(pThis, l) || !to_integer(pThis, r)) { longjmp(pThis->g_expr_jmp, errx(pThis->pCtx, 2, "non-numeric argument")); } if (op == MUL) { l->u.i *= r->u.i; } else { if (r->u.i == 0) { longjmp(pThis->g_expr_jmp, errx(pThis->pCtx, 2, "division by zero")); } if (op == DIV) { l->u.i /= r->u.i; } else { l->u.i %= r->u.i; } } free_value(pThis, r); } return l; } /* Parse and evaluate addition and subtraction expressions */ static struct val * eval3(PEXPRINSTANCE pThis) { struct val *l, *r; enum token op; l = eval4(pThis); while ((op = pThis->token) == ADD || op == SUB) { nexttoken(pThis, 0); r = eval4(pThis); if (!to_integer(pThis, l) || !to_integer(pThis, r)) { longjmp(pThis->g_expr_jmp, errx(pThis->pCtx, 2, "non-numeric argument")); } if (op == ADD) { l->u.i += r->u.i; } else { l->u.i -= r->u.i; } free_value(pThis, r); } return l; } /* Parse and evaluate comparison expressions */ static struct val * eval2(PEXPRINSTANCE pThis) { struct val *l, *r; enum token op; int v = 0, li, ri; l = eval3(pThis); while ((op = pThis->token) == EQ || op == NE || op == LT || op == GT || op == LE || op == GE) { nexttoken(pThis, 0); r = eval3(pThis); if (is_integer(l, &li) && is_integer(r, &ri)) { switch (op) { case GT: v = (li > ri); break; case GE: v = (li >= ri); break; case LT: v = (li < ri); break; case LE: v = (li <= ri); break; case EQ: v = (li == ri); break; case NE: v = (li != ri); break; default: break; } } else { to_string(pThis, l); to_string(pThis, r); switch (op) { case GT: v = (strcoll(l->u.s, r->u.s) > 0); break; case GE: v = (strcoll(l->u.s, r->u.s) >= 0); break; case LT: v = (strcoll(l->u.s, r->u.s) < 0); break; case LE: v = (strcoll(l->u.s, r->u.s) <= 0); break; case EQ: v = (strcoll(l->u.s, r->u.s) == 0); break; case NE: v = (strcoll(l->u.s, r->u.s) != 0); break; default: break; } } free_value(pThis, l); free_value(pThis, r); l = make_int(pThis, v); } return l; } /* Parse and evaluate & expressions */ static struct val * eval1(PEXPRINSTANCE pThis) { struct val *l, *r; l = eval2(pThis); while (pThis->token == AND) { nexttoken(pThis, 0); r = eval2(pThis); if (is_zero_or_null(pThis, l) || is_zero_or_null(pThis, r)) { free_value(pThis, l); free_value(pThis, r); l = make_int(pThis, 0); } else { free_value(pThis, r); } } return l; } /* Parse and evaluate | expressions */ static struct val * eval0(PEXPRINSTANCE pThis) { struct val *l, *r; l = eval1(pThis); while (pThis->token == OR) { nexttoken(pThis, 0); r = eval1(pThis); if (is_zero_or_null(pThis, l)) { free_value(pThis, l); l = r; } else { free_value(pThis, r); } } return l; } int kmk_builtin_expr(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { EXPRINSTANCE This; struct val *vp; int rval; if (argc > 1 && !strcmp(argv[1], "--")) argv++; /* Init globals */ This.pCtx = pCtx; This.token = 0; This.tokval = 0; This.av = argv + 1; expr_mem_init(&This); rval = setjmp(This.g_expr_jmp); if (!rval) { nexttoken(&This, 0); vp = eval0(&This); if (This.token != EOI) { error(&This); /* NOTREACHED */ } if (vp->type == integer) kmk_builtin_ctx_printf(pCtx, 0, "%d\n", vp->u.i); else kmk_builtin_ctx_printf(pCtx, 0, "%s\n", vp->u.s); rval = is_zero_or_null(&This, vp); } /* else: longjmp */ /* cleanup */ expr_mem_cleanup(&This); return rval; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_expr", NULL }; (void) setlocale(LC_ALL, ""); return kmk_builtin_expr(argc, argv, envp, &Ctx); } #endif kbuild-3686/src/kmk/kmkbuiltin/getopt1_r.c0000664000175000017500000001060115053010074020477 0ustar locutuslocutus/* Reentrant version of getopt_long and getopt_long_only. Based on ../getopt*.*: getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987-1994, 1996-2016 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . Modifications: Copyright (c) 2018 knut st. osmundsen */ #define FAKES_NO_GETOPT_H /* bird */ #ifdef HAVE_CONFIG_H #include #endif #include "getopt_r.h" #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include #if 0 /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #endif #if 1 //ndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #endif #ifndef NULL #define NULL 0 #endif int getopt_long_r (struct getopt_state_r *gos, int *opt_index) { return _getopt_internal_r (gos, gos->long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only_r (struct getopt_state_r *gos, int *opt_index) { return _getopt_internal_r (gos, gos->long_options, opt_index, 0); } #endif /* #if 1 */ /* Not ELIDE_CODE. */ #ifdef TEST #include int main (int argc, char **argv) { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; struct getopt_state_r gos; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; getopt_initialize_r (&gos, argc, argv, "abc:d:0123456789", long_options, NULL, NULL); c = getopt_long_r (&geo, &option_index); if (c == -1) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (geo.optarg) printf (" with arg %s", geo.optarg); printf ("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value '%s'\n", geo.optarg); break; case 'd': printf ("option d with value '%s'\n", geo.optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (geo.optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[geo.optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ kbuild-3686/src/kmk/kmkbuiltin/md5sum.c0000664000175000017500000006366115053010074020023 0ustar locutuslocutus/* $Id: md5sum.c 3219 2018-03-30 22:30:15Z bird $ */ /** @file * md5sum. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #ifdef _MSC_VER # include #else # include #endif #include #include "err.h" #include "kmkbuiltin.h" #include "../../lib/md5.h" #include /*#define MD5SUM_USE_STDIO*/ /** * Prints the usage and return 1. */ static int usage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: md5sum [-bt] [-o list-file] file(s)\n" " or: md5sum [-btwq] -c list-file(s)\n" " or: md5sum [-btq] -C MD5 file\n" "\n" " -c, --check Check MD5 and files found in the specified list file(s).\n" " The default is to compute MD5 sums of the specified files\n" " and print them to stdout in list form.\n" " -C, --check-file This is followed by an MD5 sum and the file to check.\n" " -b, --binary Read files in binary mode. (default)\n" " -t, --text Read files in text mode.\n" " -m, --manifest Output in kBuild fetch 'manifest' format.\n" " -p, --progress Show progress indicator on large files.\n" " -o, --output Name of the output list file. Useful with -p.\n" " -q, --status Be quiet.\n" " -w, --warn Ignored. Always warn, unless quiet.\n" " -h, --help This usage info.\n" " -v, --version Show version information and exit.\n" ); return 1; } /** * Makes a string out of the given digest. * * @param pDigest The MD5 digest. * @param pszDigest Where to put the digest string. Must be able to * hold at least 33 bytes. */ static void digest_to_string(unsigned char pDigest[16], char *pszDigest) { unsigned i; for (i = 0; i < 16; i++) { static char s_achDigits[17] = "0123456789abcdef"; pszDigest[i*2] = s_achDigits[(pDigest[i] >> 4)]; pszDigest[i*2 + 1] = s_achDigits[(pDigest[i] & 0xf)]; } pszDigest[i*2] = '\0'; } /** * Attempts to convert a string to a MD5 digest. * * @returns 0 on success, 1-based position of the failure first error. * @param pszDigest The string to interpret. * @param pDigest Where to put the MD5 digest. */ static int string_to_digest(const char *pszDigest, unsigned char pDigest[16]) { unsigned i; unsigned iBase = 1; /* skip blanks */ while ( *pszDigest == ' ' || *pszDigest == '\t' || *pszDigest == '\n' || *pszDigest == '\r') pszDigest++, iBase++; /* convert the digits. */ memset(pDigest, 0, 16); for (i = 0; i < 32; i++, pszDigest++) { int iDigit; if (*pszDigest >= '0' && *pszDigest <= '9') iDigit = *pszDigest - '0'; else if (*pszDigest >= 'a' && *pszDigest <= 'f') iDigit = *pszDigest - 'a' + 10; else if (*pszDigest >= 'A' && *pszDigest <= 'F') iDigit = *pszDigest - 'A' + 10; else return i + iBase; if (i & 1) pDigest[i >> 1] |= iDigit; else pDigest[i >> 1] |= iDigit << 4; } /* the rest of the string must now be blanks. */ while ( *pszDigest == ' ' || *pszDigest == '\t' || *pszDigest == '\n' || *pszDigest == '\r') pszDigest++, i++; return *pszDigest ? i + iBase : 0; } /** * Opens the specified file for md5 sum calculation. * * @returns Opaque pointer on success, NULL and errno on failure. * @param pszFilename The filename. * @param fText Whether text or binary mode should be used. */ static void *open_file(const char *pszFilename, unsigned fText) { #if defined(MD5SUM_USE_STDIO) FILE *pFile; errno = 0; pFile = fopen(pszFilename, fText ? "r" KMK_FOPEN_NO_INHERIT_MODE : "rb" KMK_FOPEN_NO_INHERIT_MODE); if (!pFile && errno == EINVAL && !fText) pFile = fopen(pszFilename, "r" KMK_FOPEN_NO_INHERIT_MODE); return pFile; #else int fd; int fFlags; /* figure out the appropriate flags. */ fFlags = O_RDONLY | KMK_OPEN_NO_INHERIT; #ifdef O_SEQUENTIAL fFlags |= _O_SEQUENTIAL; #elif defined(_O_SEQUENTIAL) fFlags |= _O_SEQUENTIAL; #endif #ifdef O_BINARY if (!fText) fFlags |= O_BINARY; #elif defined(_O_BINARY) if (!fText) fFlags |= _O_BINARY; #endif #ifdef O_TEXT if (fText) fFlags |= O_TEXT; #elif defined(O_TEXT) if (fText) fFlags |= _O_TEXT; #else (void)fText; #endif errno = 0; fd = open(pszFilename, fFlags, 0755); if (fd >= 0) { int *pFd = malloc(sizeof(*pFd)); if (pFd) { *pFd = fd; return pFd; } close(fd); errno = ENOMEM; } return NULL; #endif } /** * Closes a file opened by open_file. * * @param pvFile The opaque pointer returned by open_file. */ static void close_file(void *pvFile) { #if defined(MD5SUM_USE_STDIO) fclose((FILE *)pvFile); #else close(*(int *)pvFile); free(pvFile); #endif } /** * Reads from a file opened by open_file. * * @returns Number of bytes read on success. * 0 on EOF. * Negated errno on read error. * @param pvFile The opaque pointer returned by open_file. * @param pvBuf Where to put the number of read bytes. * @param cbBuf The max number of bytes to read. * Must be less than a INT_MAX. */ static int read_file(void *pvFile, void *pvBuf, size_t cbBuf) { #if defined(MD5SUM_USE_STDIO) int cb; errno = 0; cb = (int)fread(pvBuf, 1, cbBuf, (FILE *)pvFile); if (cb >= 0) return (int)cb; if (!errno) return -EINVAL; return -errno; #else int cb; errno = 0; cb = (int)read(*(int *)pvFile, pvBuf, (int)cbBuf); if (cb >= 0) return (int)cb; if (!errno) return -EINVAL; return -errno; #endif } /** * Gets the size of the file. * This is informational and not necessarily 100% accurate. * * @returns File size. * @param pvFile The opaque pointer returned by open_file */ static KU64 size_file(void *pvFile) { #if defined(_MSC_VER) __int64 cb; # if defined(MD5SUM_USE_STDIO) cb = _filelengthi64(fileno((FILE *)pvFile)); # else cb = _filelengthi64(*(int *)pvFile); # endif if (cb >= 0) return cb; #elif defined(MD5SUM_USE_STDIO) struct stat st; if (!fstat(fileno((FILE *)pvFile), &st)) return st.st_size; #else struct stat st; if (!fstat(*(int *)pvFile, &st)) return st.st_size; #endif return 1024; } /** * Calculates the md5sum of the sepecified file stream. * * @returns errno on failure, 0 on success. * @param pvFile The file stream. * @param pDigest Where to store the MD5 digest. * @param fProgress Whether to show a progress bar. * @param pcbFile Where to return the file size. Optional. */ static int calc_md5sum(void *pvFile, unsigned char pDigest[16], unsigned fProgress, KU64 *pcbFile) { int cb; int rc = 0; struct MD5Context Ctx; unsigned uPercent = 0; KU64 off = 0; KU64 const cbFile = size_file(pvFile); /* Get a decent sized buffer assuming we'll be spending more time reading from the storage than doing MD5 sums. (2MB was choosen based on recent SATA storage benchmarks which used that block size for sequential tests.) We align the buffer address on a 16K boundrary to avoid most transfer alignment issues. */ char *pabBufAligned; size_t const cbBufAlign = 16*1024 - 1; size_t const cbBufMax = 2048*1024; size_t cbBuf = cbFile >= cbBufMax ? cbBufMax : ((size_t)cbFile + cbBufAlign) & ~(size_t)cbBufAlign; char *pabBuf = (char *)malloc(cbBuf + cbBufAlign); if (pabBuf) pabBufAligned = (char *)(((uintptr_t)pabBuf + cbBufAlign) & ~(uintptr_t)cbBufAlign ); else { do { cbBuf /= 2; pabBuf = (char *)malloc(cbBuf); } while (!pabBuf && cbBuf > 4096); if (!pabBuf) return ENOMEM; pabBufAligned = pabBuf; } if (cbFile < cbBuf * 4) fProgress = 0; MD5Init(&Ctx); for (;;) { /* process a chunk. */ cb = read_file(pvFile, pabBufAligned, cbBuf); if (cb > 0) MD5Update(&Ctx, (unsigned char *)pabBufAligned, cb); else if (!cb) break; else { rc = -cb; break; } off += cb; /* update the progress indicator. */ if (fProgress) { unsigned uNewPercent; uNewPercent = (unsigned)(((double)off / cbFile) * 100); if (uNewPercent != uPercent) { if (uPercent) printf("\b\b\b\b"); printf("%3d%%", uNewPercent); fflush(stdout); uPercent = uNewPercent; } } } MD5Final(pDigest, &Ctx); if (pcbFile) *pcbFile = off; if (fProgress) printf("\b\b\b\b \b\b\b\b"); free(pabBuf); return rc; } /** * Checks the if the specified digest matches the digest of the file stream. * * @returns 0 on match, -1 on mismatch, errno value (positive) on failure. * @param pvFile The file stream. * @param Digest The MD5 digest. * @param fProgress Whether to show an progress indicator on large files. */ static int check_md5sum(void *pvFile, unsigned char Digest[16], unsigned fProgress) { unsigned char DigestFile[16]; int rc; rc = calc_md5sum(pvFile, DigestFile, fProgress, NULL); if (!rc) rc = memcmp(Digest, DigestFile, 16) ? -1 : 0; return rc; } /** * Checks if the specified file matches the given MD5 digest. * * @returns 0 if it matches, 1 if it doesn't or an error occurs. * @param pCtx The command execution context. * @param pszFilename The name of the file to check. * @param pszDigest The MD5 digest string. * @param fText Whether to open the file in text or binary mode. * @param fQuiet Whether to go about this in a quiet fashion or not. * @param fProgress Whether to show an progress indicator on large files. */ static int check_one_file(PKMKBUILTINCTX pCtx, const char *pszFilename, const char *pszDigest, unsigned fText, unsigned fQuiet, unsigned fProgress) { unsigned char Digest[16]; int rc; rc = string_to_digest(pszDigest, Digest); if (!rc) { void *pvFile; pvFile = open_file(pszFilename, fText); if (pvFile) { if (!fQuiet) kmk_builtin_ctx_printf(pCtx, 0, "%s: ", pszFilename); rc = check_md5sum(pvFile, Digest, fProgress); close_file(pvFile); if (!fQuiet) { kmk_builtin_ctx_printf(pCtx, 0, "%s\n", !rc ? "OK" : rc < 0 ? "FAILURE" : "ERROR"); if (rc > 0) errx(pCtx, 1, "Error reading '%s': %s", pszFilename, strerror(rc)); } if (rc) rc = 1; } else { if (!fQuiet) errx(pCtx, 1, "Failed to open '%s': %s", pszFilename, strerror(errno)); rc = 1; } } else { errx(pCtx, 1, "Malformed MD5 digest '%s'!", pszDigest); errx(pCtx, 1, " %*s^", rc - 1, ""); rc = 1; } return rc; } /** * Checks the specified md5.lst file. * * @returns 0 if all checks out file, 1 if one or more fails or there are read errors. * @param pCtx The command execution context. * @param pszFilename The name of the file. * @param fText The default mode, text or binary. Only used when fBinaryTextOpt is true. * @param fBinaryTextOpt Whether a -b or -t option was specified and should be used. * @param fQuiet Whether to be quiet. * @param fProgress Whether to show an progress indicator on large files. */ static int check_files(PKMKBUILTINCTX pCtx, const char *pszFilename, int fText, int fBinaryTextOpt, int fQuiet, unsigned fProgress) { int rc = 0; FILE *pFile; /* * Try open the md5.lst file and process it line by line. */ pFile = fopen(pszFilename, "r" KMK_FOPEN_NO_INHERIT_MODE); if (pFile) { int iLine = 0; char szLine[8192]; while (fgets(szLine, sizeof(szLine), pFile)) { const char *pszDigest; int fLineText; char *psz; int rc2; iLine++; psz = szLine; /* leading blanks */ while (*psz == ' ' || *psz == '\t' || *psz == '\n') psz++; /* skip blank or comment lines. */ if (!*psz || *psz == '#' || *psz == ';' || *psz == '/') continue; /* remove the trailing newline. */ rc2 = (int)strlen(psz); if (psz[rc2 - 1] == '\n') psz[rc2 - (rc2 >= 2 && psz[rc2 - 2] == '\r' ? 2 : 1)] = '\0'; /* skip to the end of the digest and terminate it. */ pszDigest = psz; while (*psz != ' ' && *psz != '\t' && *psz) psz++; if (*psz) { *psz++ = '\0'; /* blanks */ while (*psz == ' ' || *psz == '\t' || *psz == '\n') psz++; /* check for binary asterix */ if (*psz != '*') fLineText = fBinaryTextOpt ? fText : 0; else { fLineText = 0; psz++; } if (*psz) { unsigned char Digest[16]; /* the rest is filename. */ pszFilename = psz; /* * Do the job. */ rc2 = string_to_digest(pszDigest, Digest); if (!rc2) { void *pvFile = open_file(pszFilename, fLineText); if (pvFile) { if (!fQuiet) kmk_builtin_ctx_printf(pCtx, 0, "%s: ", pszFilename); rc2 = check_md5sum(pvFile, Digest, fProgress); close_file(pvFile); if (!fQuiet) { kmk_builtin_ctx_printf(pCtx, 0, "%s\n", !rc2 ? "OK" : rc2 < 0 ? "FAILURE" : "ERROR"); if (rc2 > 0) errx(pCtx, 1, "Error reading '%s': %s", pszFilename, strerror(rc2)); } if (rc2) rc = 1; } else { if (!fQuiet) errx(pCtx, 1, "Failed to open '%s': %s", pszFilename, strerror(errno)); rc = 1; } } else if (!fQuiet) { errx(pCtx, 1, "%s (%d): Ignoring malformed digest '%s' (digest)", pszFilename, iLine, pszDigest); errx(pCtx, 1, "%s (%d): %*s^", pszFilename, iLine, rc2 - 1, ""); } } else if (!fQuiet) errx(pCtx, 1, "%s (%d): Ignoring malformed line!", pszFilename, iLine); } else if (!fQuiet) errx(pCtx, 1, "%s (%d): Ignoring malformed line!", pszFilename, iLine); } /* while more lines */ fclose(pFile); } else { errx(pCtx, 1, "Failed to open '%s': %s", pszFilename, strerror(errno)); rc = 1; } return rc; } /** * Calculates the MD5 sum for one file and prints it. * * @returns 0 on success, 1 on any kind of failure. * @param pCtx Command context. * @param pszFilename The file to process. * @param fText The mode to open the file in. * @param fQuiet Whether to be quiet or verbose about errors. * @param fManifest Whether to format the output like a fetch manifest. * @param fProgress Whether to show an progress indicator on large files. * @param pOutput Where to write the list. Progress is always written to stdout. */ static int md5sum_file(PKMKBUILTINCTX pCtx, const char *pszFilename, unsigned fText, unsigned fQuiet, unsigned fProgress, unsigned fManifest, FILE *pOutput) { int rc; void *pvFile; /* * Calculate and print the MD5 sum for one file. */ pvFile = open_file(pszFilename, fText); if (pvFile) { unsigned char Digest[16]; KU64 cbFile = 0; if (fProgress && pOutput) fprintf(stdout, "%s: ", pszFilename); rc = calc_md5sum(pvFile, Digest, fProgress, &cbFile); close_file(pvFile); if (fProgress && pOutput) { size_t cch = strlen(pszFilename) + 2; while (cch-- > 0) fputc('\b', stdout); } if (!rc) { char szDigest[36]; digest_to_string(Digest, szDigest); if (!fManifest) { if (pOutput) fprintf(pOutput, "%s %s%s\n", szDigest, fText ? "" : "*", pszFilename); kmk_builtin_ctx_printf(pCtx, 0, "%s %s%s\n", szDigest, fText ? "" : "*", pszFilename); } else { if (pOutput) fprintf(pOutput, "%s_SIZE := %" KU64_PRI "\n%s_MD5 := %s\n", pszFilename, cbFile, pszFilename, szDigest); kmk_builtin_ctx_printf(pCtx, 0, "%s_SIZE := %" KU64_PRI "\n%s_MD5 := %s\n", pszFilename, cbFile, pszFilename, szDigest); } if (pOutput) fflush(pOutput); } else { if (!fQuiet) errx(pCtx, 1, "Failed to open '%s': %s", pszFilename, strerror(rc)); rc = 1; } } else { if (!fQuiet) errx(pCtx, 1, "Failed to open '%s': %s", pszFilename, strerror(errno)); rc = 1; } return rc; } /** * md5sum, calculates and checks the md5sum of files. * Somewhat similar to the GNU coreutil md5sum command. */ int kmk_builtin_md5sum(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { int i; int rc = 0; int fText = 0; int fBinaryTextOpt = 0; int fQuiet = 0; int fChecking = 0; int fManifest = 0; int fProgress = 0; int fNoMoreOptions = 0; const char *pszOutput = NULL; FILE *pOutput = NULL; /* * Print usage if no arguments. */ if (argc <= 1) return usage(pCtx, 1); /* * Process the arguments, FIFO style. */ i = 1; while (i < argc) { char *psz = argv[i]; if (!fNoMoreOptions && psz[0] == '-' && psz[1] == '-' && !psz[2]) fNoMoreOptions = 1; else if (*psz == '-' && !fNoMoreOptions) { psz++; /* convert long options for gnu just for fun */ if (*psz == '-') { if (!strcmp(psz, "-binary")) psz = "b"; else if (!strcmp(psz, "-text")) psz = "t"; else if (!strcmp(psz, "-check")) psz = "c"; else if (!strcmp(psz, "-check-file")) psz = "C"; else if (!strcmp(psz, "-manifest")) psz = "m"; else if (!strcmp(psz, "-output")) psz = "o"; else if (!strcmp(psz, "-progress")) psz = "p"; else if (!strcmp(psz, "-status")) psz = "q"; else if (!strcmp(psz, "-warn")) psz = "w"; else if (!strcmp(psz, "-help")) psz = "h"; else if (!strcmp(psz, "-version")) psz = "v"; } /* short options */ do { switch (*psz) { case 'c': fChecking = 1; break; case 'b': fText = 0; fBinaryTextOpt = 1; break; case 't': fText = 1; fBinaryTextOpt = 1; break; case 'm': fManifest = 1; break; case 'p': fProgress = 1 && isatty(fileno(stdout)) #ifndef KMK_BUILTIN_STANDALONE && (!pCtx->pOut || !pCtx->pOut->syncout) #endif ; break; case 'q': fQuiet = 1; break; case 'w': /* ignored */ break; case 'h': usage(pCtx, 0); return 0; case 'v': return kbuild_version(argv[0]); /* * -C md5 file */ case 'C': { const char *pszFilename; const char *pszDigest; if (psz[1]) pszDigest = &psz[1]; else if (i + 1 < argc) pszDigest = argv[++i]; else { errx(pCtx, 1, "'-C' is missing the MD5 sum!"); return 1; } if (i + 1 < argc) pszFilename = argv[++i]; else { errx(pCtx, 1, "'-C' is missing the filename!"); return 1; } rc |= check_one_file(pCtx, pszFilename, pszDigest, fText, fQuiet, fProgress && !fQuiet); psz = "\0"; break; } /* * Output file. */ case 'o': { if (fChecking) { errx(pCtx, 1, "'-o' cannot be used with -c or -C!"); return 1; } if (psz[1]) pszOutput = &psz[1]; else if (i + 1 < argc) pszOutput = argv[++i]; else { errx(pCtx, 1, "'-o' is missing the file name!"); return 1; } psz = "\0"; break; } default: errx(pCtx, 1, "Invalid option '%c'! (%s)", *psz, argv[i]); return usage(pCtx, 1); } } while (*++psz); } else if (fChecking) rc |= check_files(pCtx, argv[i], fText, fBinaryTextOpt, fQuiet, fProgress && !fQuiet); else { /* lazily open the output if specified. */ if (pszOutput) { if (pOutput) fclose(pOutput); pOutput = fopen(pszOutput, "w" KMK_FOPEN_NO_INHERIT_MODE); if (!pOutput) { rc = err(pCtx, 1, "fopen(\"%s\", \"w" KMK_FOPEN_NO_INHERIT_MODE "\") failed", pszOutput); break; } pszOutput = NULL; } rc |= md5sum_file(pCtx, argv[i], fText, fQuiet, fProgress && !fQuiet && !fManifest, fManifest, pOutput); } i++; } if (pOutput) fclose(pOutput); return rc; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_md5sum", NULL }; return kmk_builtin_md5sum(argc, argv, envp, &Ctx); } #endif kbuild-3686/src/kmk/kmkbuiltin/test.c0000664000175000017500000005602515053010075017565 0ustar locutuslocutus/* $NetBSD: test.c,v 1.33 2007/06/24 18:54:58 christos Exp $ */ /* * test(1); version 7-like -- author Erik Baalbergen * modified by Eric Gisin to be used as built-in. * modified by Arnold Robbins to add SVR3 compatibility * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). * modified by J.T. Conklin for NetBSD. * * This program is in the Public Domain. */ /*#include #ifndef lint __RCSID("$NetBSD: test.c,v 1.33 2007/06/24 18:54:58 christos Exp $"); #endif*/ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #include "config.h" #include #include #include #include "err.h" #include #include #include #include #include #ifdef _MSC_VER # include # include # include # include "mscfakes.h" # include "quote_argv.h" #else # include #endif #include #include #include "kmkbuiltin.h" /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ #ifndef __arraycount # define __arraycount(a) ( sizeof(a) / sizeof(a[0]) ) #endif /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ /* test(1) accepts the following grammar: oexpr ::= aexpr | aexpr "-o" oexpr ; aexpr ::= nexpr | nexpr "-a" aexpr ; nexpr ::= primary | "!" primary primary ::= unary-operator operand | operand binary-operator operand | operand | "(" oexpr ")" ; unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"| "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S"; binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| "-nt"|"-ot"|"-ef"; operand ::= */ enum token { EOI, FILRD, FILWR, FILEX, FILEXIST, FILREG, FILDIR, FILCDEV, FILBDEV, FILFIFO, FILSOCK, FILSYM, FILGZ, FILTT, FILSUID, FILSGID, FILSTCK, FILNT, FILOT, FILEQ, FILUID, FILGID, STREZ, STRNZ, STREQ, STRNE, STRLT, STRGT, INTEQ, INTNE, INTGE, INTGT, INTLE, INTLT, UNOT, BAND, BOR, LPAREN, RPAREN, OPERAND }; enum token_types { UNOP, BINOP, BUNOP, BBINOP, PAREN }; struct t_op { const char *op_text; short op_num, op_type; }; /** kmk_test instance data. */ typedef struct TESTINSTANCE { PKMKBUILTINCTX pCtx; char **t_wp; struct t_op const *t_wp_op; } TESTINSTANCE; typedef TESTINSTANCE *PTESTINSTANCE; /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ static const struct t_op cop[] = { {"!", UNOT, BUNOP}, {"(", LPAREN, PAREN}, {")", RPAREN, PAREN}, {"<", STRLT, BINOP}, {"=", STREQ, BINOP}, {">", STRGT, BINOP}, }; static const struct t_op cop2[] = { {"!=", STRNE, BINOP}, }; static const struct t_op mop3[] = { {"ef", FILEQ, BINOP}, {"eq", INTEQ, BINOP}, {"ge", INTGE, BINOP}, {"gt", INTGT, BINOP}, {"le", INTLE, BINOP}, {"lt", INTLT, BINOP}, {"ne", INTNE, BINOP}, {"nt", FILNT, BINOP}, {"ot", FILOT, BINOP}, }; static const struct t_op mop2[] = { {"G", FILGID, UNOP}, {"L", FILSYM, UNOP}, {"O", FILUID, UNOP}, {"S", FILSOCK,UNOP}, {"a", BAND, BBINOP}, {"b", FILBDEV,UNOP}, {"c", FILCDEV,UNOP}, {"d", FILDIR, UNOP}, {"e", FILEXIST,UNOP}, {"f", FILREG, UNOP}, {"g", FILSGID,UNOP}, {"h", FILSYM, UNOP}, /* for backwards compat */ {"k", FILSTCK,UNOP}, {"n", STRNZ, UNOP}, {"o", BOR, BBINOP}, {"p", FILFIFO,UNOP}, {"r", FILRD, UNOP}, {"s", FILGZ, UNOP}, {"t", FILTT, UNOP}, {"u", FILSUID,UNOP}, {"w", FILWR, UNOP}, {"x", FILEX, UNOP}, {"z", STREZ, UNOP}, }; /********************************************************************************************************************************* * Internal Functions * *********************************************************************************************************************************/ static int syntax(PTESTINSTANCE, const char *, const char *); static int oexpr(PTESTINSTANCE, enum token); static int aexpr(PTESTINSTANCE, enum token); static int nexpr(PTESTINSTANCE, enum token); static int primary(PTESTINSTANCE, enum token); static int binop(PTESTINSTANCE); static int test_access(struct stat *, mode_t); static int filstat(char *, enum token); static enum token t_lex(PTESTINSTANCE, char *); static int isoperand(PTESTINSTANCE); static int getn(PTESTINSTANCE, const char *); static int newerf(const char *, const char *); static int olderf(const char *, const char *); static int equalf(const char *, const char *); static int usage(PKMKBUILTINCTX, int); #if !defined(KMK_BUILTIN_STANDALONE) || defined(ELECTRIC_HEAP) extern void *xmalloc(unsigned int); #else extern void *xmalloc(unsigned int sz) { void *p = malloc(sz); if (!p) { fprintf(stderr, "kmk_test: malloc(%u) failed\n", sz); exit(1); } return p; } #endif int kmk_builtin_test(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, char ***ppapszArgvSpawn) { TESTINSTANCE This; int res; char **argv_spawn; int i; This.pCtx = pCtx; This.t_wp = NULL; This.t_wp_op = NULL; /* look for the '--', '--help' and '--version'. */ argv_spawn = NULL; for (i = 1; i < argc; i++) { if ( argv[i][0] == '-' && argv[i][1] == '-') { if (argv[i][2] == '\0') { argc = i; argv[i] = NULL; /* skip blank arguments (happens inside kmk) */ while (argv[++i]) { const char *psz = argv[i]; while (isspace(*psz)) psz++; if (*psz) break; } argv_spawn = &argv[i]; break; } if (!strcmp(argv[i], "--help")) return usage(pCtx, 0); if (!strcmp(argv[i], "--version")) return kbuild_version(argv[0]); } } /* are we '['? then check for ']'. */ if (strcmp(argv[0], "[") == 0) { /** @todo should skip the path in g_progname */ if (strcmp(argv[--argc], "]")) return errx(pCtx, 1, "missing ]"); argv[argc] = NULL; } /* evaluate the expression */ if (argc < 2) res = 1; else { This.t_wp = &argv[1]; res = oexpr(&This, t_lex(&This, *This.t_wp)); if (res != -42 && *This.t_wp != NULL && *++This.t_wp != NULL) res = syntax(&This, *This.t_wp, "unexpected operator"); if (res == -42) return 1; /* don't mix syntax errors with the argv_spawn ignore */ res = !res; } /* anything to execute on success? */ if (argv_spawn) { if (res != 0 || !argv_spawn[0]) res = 0; /* ignored */ else { #ifdef KMK_BUILTIN_STANDALONE /* try exec the specified process */ # if defined(_MSC_VER) int argc_spawn = 0; while (argv_spawn[argc_spawn]) argc_spawn++; if (quote_argv(argc, argv_spawn, 0 /*fWatcomBrainDamage*/, 0/*fFreeOrLeak*/) != -1) { res = _spawnvp(_P_WAIT, argv_spawn[0], argv_spawn); if (res == -1) res = err(pCtx, 1, "_spawnvp(_P_WAIT,%s,..)", argv_spawn[0]); } else res = err(pCtx, 1, "quote_argv: out of memory"); # else execvp(argv_spawn[0], argv_spawn); res = err(pCtx, 1, "execvp(%s,..)", argv_spawn[0]); # endif #else /* in kmk */ /* let job.c spawn the process, make a job.c style argv_spawn copy. */ char *cur, **argv_new; size_t sz = 0; int argc_new = 0; while (argv_spawn[argc_new]) { size_t len = strlen(argv_spawn[argc_new]) + 1; sz += (len + sizeof(void *) - 1) & ~(sizeof(void *) - 1); argc_new++; } argv_new = xmalloc((argc_new + 1) * sizeof(char *)); cur = xmalloc(sz); for (i = 0; i < argc_new; i++) { size_t len = strlen(argv_spawn[i]) + 1; argv_new[i] = memcpy(cur, argv_spawn[i], len); cur += (len + sizeof(void *) - 1) & ~(sizeof(void *) - 1); } argv_new[i] = NULL; *ppapszArgvSpawn = argv_new; res = 0; #endif /* in kmk */ } } return res; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_test", NULL }; return kmk_builtin_test(argc, argv, envp, &Ctx, NULL); } #endif static int syntax(PTESTINSTANCE pThis, const char *op, const char *msg) { if (op && *op) errx(pThis->pCtx, 1, "%s: %s", op, msg); else errx(pThis->pCtx, 1, "%s", msg); return -42; } static int oexpr(PTESTINSTANCE pThis, enum token n) { int res; res = aexpr(pThis, n); if (res == -42 || *pThis->t_wp == NULL) return res; if (t_lex(pThis, *++(pThis->t_wp)) == BOR) { int res2 = oexpr(pThis, t_lex(pThis, *++(pThis->t_wp))); return res2 != -42 ? res2 || res : res2; } pThis->t_wp--; return res; } static int aexpr(PTESTINSTANCE pThis, enum token n) { int res; res = nexpr(pThis, n); if (res == -42 || *pThis->t_wp == NULL) return res; if (t_lex(pThis, *++(pThis->t_wp)) == BAND) { int res2 = aexpr(pThis, t_lex(pThis, *++(pThis->t_wp))); return res2 != -42 ? res2 && res : res2; } pThis->t_wp--; return res; } static int nexpr(PTESTINSTANCE pThis, enum token n) { if (n == UNOT) { int res = nexpr(pThis, t_lex(pThis, *++(pThis->t_wp))); return res != -42 ? !res : res; } return primary(pThis, n); } static int primary(PTESTINSTANCE pThis, enum token n) { enum token nn; int res; if (n == EOI) return 0; /* missing expression */ if (n == LPAREN) { if ((nn = t_lex(pThis, *++(pThis->t_wp))) == RPAREN) return 0; /* missing expression */ res = oexpr(pThis, nn); if (res != -42 && t_lex(pThis, *++(pThis->t_wp)) != RPAREN) return syntax(pThis, NULL, "closing paren expected"); return res; } if (pThis->t_wp_op && pThis->t_wp_op->op_type == UNOP) { /* unary expression */ if (*++(pThis->t_wp) == NULL) return syntax(pThis, pThis->t_wp_op->op_text, "argument expected"); switch (n) { case STREZ: return strlen(*pThis->t_wp) == 0; case STRNZ: return strlen(*pThis->t_wp) != 0; case FILTT: return isatty(getn(pThis, *pThis->t_wp)); default: return filstat(*pThis->t_wp, n); } } if (t_lex(pThis, pThis->t_wp[1]), pThis->t_wp_op && pThis->t_wp_op->op_type == BINOP) { return binop(pThis); } return strlen(*pThis->t_wp) > 0; } static int binop(PTESTINSTANCE pThis) { const char *opnd1, *opnd2; struct t_op const *op; opnd1 = *pThis->t_wp; (void) t_lex(pThis, *++(pThis->t_wp)); op = pThis->t_wp_op; if ((opnd2 = *++(pThis->t_wp)) == NULL) return syntax(pThis, op->op_text, "argument expected"); switch (op->op_num) { case STREQ: return strcmp(opnd1, opnd2) == 0; case STRNE: return strcmp(opnd1, opnd2) != 0; case STRLT: return strcmp(opnd1, opnd2) < 0; case STRGT: return strcmp(opnd1, opnd2) > 0; case INTEQ: return getn(pThis, opnd1) == getn(pThis, opnd2); case INTNE: return getn(pThis, opnd1) != getn(pThis, opnd2); case INTGE: return getn(pThis, opnd1) >= getn(pThis, opnd2); case INTGT: return getn(pThis, opnd1) > getn(pThis, opnd2); case INTLE: return getn(pThis, opnd1) <= getn(pThis, opnd2); case INTLT: return getn(pThis, opnd1) < getn(pThis, opnd2); case FILNT: return newerf(opnd1, opnd2); case FILOT: return olderf(opnd1, opnd2); case FILEQ: return equalf(opnd1, opnd2); default: abort(); /* NOTREACHED */ #ifdef _MSC_VER return -42; #endif } } /* * The manual, and IEEE POSIX 1003.2, suggests this should check the mode bits, * not use access(): * * True shall indicate only that the write flag is on. The file is not * writable on a read-only file system even if this test indicates true. * * Unfortunately IEEE POSIX 1003.1-2001, as quoted in SuSv3, says only: * * True shall indicate that permission to read from file will be granted, * as defined in "File Read, Write, and Creation". * * and that section says: * * When a file is to be read or written, the file shall be opened with an * access mode corresponding to the operation to be performed. If file * access permissions deny access, the requested operation shall fail. * * and of course access permissions are described as one might expect: * * * If a process has the appropriate privilege: * * * If read, write, or directory search permission is requested, * access shall be granted. * * * If execute permission is requested, access shall be granted if * execute permission is granted to at least one user by the file * permission bits or by an alternate access control mechanism; * otherwise, access shall be denied. * * * Otherwise: * * * The file permission bits of a file contain read, write, and * execute/search permissions for the file owner class, file group * class, and file other class. * * * Access shall be granted if an alternate access control mechanism * is not enabled and the requested access permission bit is set for * the class (file owner class, file group class, or file other class) * to which the process belongs, or if an alternate access control * mechanism is enabled and it allows the requested access; otherwise, * access shall be denied. * * and when I first read this I thought: surely we can't go about using * open(O_WRONLY) to try this test! However the POSIX 1003.1-2001 Rationale * section for test does in fact say: * * On historical BSD systems, test -w directory always returned false * because test tried to open the directory for writing, which always * fails. * * and indeed this is in fact true for Seventh Edition UNIX, UNIX 32V, and UNIX * System III, and thus presumably also for BSD up to and including 4.3. * * Secondly I remembered why using open() and/or access() are bogus. They * don't work right for detecting read and write permissions bits when called * by root. * * Interestingly the 'test' in 4.4BSD was closer to correct (as per * 1003.2-1992) and it was implemented efficiently with stat() instead of * open(). * * This was apparently broken in NetBSD around about 1994/06/30 when the old * 4.4BSD implementation was replaced with a (arguably much better coded) * implementation derived from pdksh. * * Note that modern pdksh is yet different again, but still not correct, at * least not w.r.t. 1003.2-1992. * * As I think more about it and read more of the related IEEE docs I don't like * that wording about 'test -r' and 'test -w' in 1003.1-2001 at all. I very * much prefer the original wording in 1003.2-1992. It is much more useful, * and so that's what I've implemented. * * (Note that a strictly conforming implementation of 1003.1-2001 is in fact * totally useless for the case in question since its 'test -w' and 'test -r' * can never fail for root for any existing files, i.e. files for which 'test * -e' succeeds.) * * The rationale for 1003.1-2001 suggests that the wording was "clarified" in * 1003.1-2001 to align with the 1003.2b draft. 1003.2b Draft 12 (July 1999), * which is the latest copy I have, does carry the same suggested wording as is * in 1003.1-2001, with its rationale saying: * * This change is a clarification and is the result of interpretation * request PASC 1003.2-92 #23 submitted for IEEE Std 1003.2-1992. * * That interpretation can be found here: * * http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-23.html * * Not terribly helpful, unfortunately. I wonder who that fence sitter was. * * Worse, IMVNSHO, I think the authors of 1003.2b-D12 have mis-interpreted the * PASC interpretation and appear to be gone against at least one widely used * implementation (namely 4.4BSD). The problem is that for file access by root * this means that if test '-r' and '-w' are to behave as if open() were called * then there's no way for a shell script running as root to check if a file * has certain access bits set other than by the grotty means of interpreting * the output of 'ls -l'. This was widely considered to be a bug in V7's * "test" and is, I believe, one of the reasons why direct use of access() was * avoided in some more recent implementations! * * I have always interpreted '-r' to match '-w' and '-x' as per the original * wording in 1003.2-1992, not the other way around. I think 1003.2b goes much * too far the wrong way without any valid rationale and that it's best if we * stick with 1003.2-1992 and test the flags, and not mimic the behaviour of * open() since we already know very well how it will work -- existance of the * file is all that matters to open() for root. * * Unfortunately the SVID is no help at all (which is, I guess, partly why * we're in this mess in the first place :-). * * The SysV implementation (at least in the 'test' builtin in /bin/sh) does use * access(name, 2) even though it also goes to much greater lengths for '-x' * matching the 1003.2-1992 definition (which is no doubt where that definition * came from). * * The ksh93 implementation uses access() for '-r' and '-w' if * (euid==uid&&egid==gid), but uses st_mode for '-x' iff running as root. * i.e. it does strictly conform to 1003.1-2001 (and presumably 1003.2b). */ static int test_access(struct stat *sp, mode_t stmode) { #ifdef _MSC_VER /* just pretend to be root for now. */ stmode = (stmode << 6) | (stmode << 3) | stmode; return !!(sp->st_mode & stmode); #else gid_t *groups; register int n; uid_t euid; int maxgroups; /* * I suppose we could use access() if not running as root and if we are * running with ((euid == uid) && (egid == gid)), but we've already * done the stat() so we might as well just test the permissions * directly instead of asking the kernel to do it.... */ euid = geteuid(); if (euid == 0) /* any bit is good enough */ stmode = (stmode << 6) | (stmode << 3) | stmode; else if (sp->st_uid == euid) stmode <<= 6; else if (sp->st_gid == getegid()) stmode <<= 3; else { /* XXX stolen almost verbatim from ksh93.... */ /* on some systems you can be in several groups */ if ((maxgroups = getgroups(0, NULL)) <= 0) maxgroups = NGROUPS_MAX; /* pre-POSIX system? */ groups = xmalloc((maxgroups + 1) * sizeof(gid_t)); n = getgroups(maxgroups, groups); while (--n >= 0) { if (groups[n] == sp->st_gid) { stmode <<= 3; break; } } free(groups); } return !!(sp->st_mode & stmode); #endif } static int filstat(char *nm, enum token mode) { struct stat s; if (mode == FILSYM ? lstat(nm, &s) : stat(nm, &s)) return 0; switch (mode) { case FILRD: return test_access(&s, S_IROTH); case FILWR: return test_access(&s, S_IWOTH); case FILEX: return test_access(&s, S_IXOTH); case FILEXIST: return 1; /* the successful lstat()/stat() is good enough */ case FILREG: return S_ISREG(s.st_mode); case FILDIR: return S_ISDIR(s.st_mode); case FILCDEV: #ifdef S_ISCHR return S_ISCHR(s.st_mode); #else return 0; #endif case FILBDEV: #ifdef S_ISBLK return S_ISBLK(s.st_mode); #else return 0; #endif case FILFIFO: #ifdef S_ISFIFO return S_ISFIFO(s.st_mode); #else return 0; #endif case FILSOCK: #ifdef S_ISSOCK return S_ISSOCK(s.st_mode); #else return 0; #endif case FILSYM: #ifdef S_ISLNK return S_ISLNK(s.st_mode); #else return 0; #endif case FILSUID: return (s.st_mode & S_ISUID) != 0; case FILSGID: return (s.st_mode & S_ISGID) != 0; case FILSTCK: #ifdef S_ISVTX return (s.st_mode & S_ISVTX) != 0; #else return 0; #endif case FILGZ: return s.st_size > (off_t)0; case FILUID: return s.st_uid == geteuid(); case FILGID: return s.st_gid == getegid(); default: return 1; } } #define VTOC(x) (const unsigned char *)((const struct t_op *)x)->op_text static int compare1(const void *va, const void *vb) { const unsigned char *a = va; const unsigned char *b = VTOC(vb); return a[0] - b[0]; } static int compare2(const void *va, const void *vb) { const unsigned char *a = va; const unsigned char *b = VTOC(vb); int z = a[0] - b[0]; return z ? z : (a[1] - b[1]); } static struct t_op const * findop(const char *s) { if (s[0] == '-') { if (s[1] == '\0') return NULL; if (s[2] == '\0') return bsearch(s + 1, mop2, __arraycount(mop2), sizeof(*mop2), compare1); else if (s[3] != '\0') return NULL; else return bsearch(s + 1, mop3, __arraycount(mop3), sizeof(*mop3), compare2); } else { if (s[1] == '\0') return bsearch(s, cop, __arraycount(cop), sizeof(*cop), compare1); else if (strcmp(s, cop2[0].op_text) == 0) return cop2; else return NULL; } } static enum token t_lex(PTESTINSTANCE pThis, char *s) { struct t_op const *op; if (s == NULL) { pThis->t_wp_op = NULL; return EOI; } if ((op = findop(s)) != NULL) { if (!((op->op_type == UNOP && isoperand(pThis)) || (op->op_num == LPAREN && *(pThis->t_wp+1) == 0))) { pThis->t_wp_op = op; return op->op_num; } } pThis->t_wp_op = NULL; return OPERAND; } static int isoperand(PTESTINSTANCE pThis) { struct t_op const *op; char *s, *t; if ((s = *(pThis->t_wp+1)) == 0) return 1; if ((t = *(pThis->t_wp+2)) == 0) return 0; if ((op = findop(s)) != NULL) return op->op_type == BINOP && (t[0] != ')' || t[1] != '\0'); return 0; } /* atoi with error detection */ static int getn(PTESTINSTANCE pThis, const char *s) { char *p; long r; errno = 0; r = strtol(s, &p, 10); if (errno != 0) return errx(pThis->pCtx, -42, "%s: out of range", s); while (isspace((unsigned char)*p)) p++; if (*p) return errx(pThis->pCtx, -42, "%s: bad number", s); return (int) r; } static int newerf(const char *f1, const char *f2) { struct stat b1, b2; return (stat(f1, &b1) == 0 && stat(f2, &b2) == 0 && b1.st_mtime > b2.st_mtime); } static int olderf(const char *f1, const char *f2) { struct stat b1, b2; return (stat(f1, &b1) == 0 && stat(f2, &b2) == 0 && b1.st_mtime < b2.st_mtime); } static int equalf(const char *f1, const char *f2) { struct stat b1, b2; return (stat(f1, &b1) == 0 && stat(f2, &b2) == 0 && b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino); } static int usage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s expression [-- [args]]\n", pCtx->pszProgName); return 0; /* only used in --help. */ } kbuild-3686/src/kmk/kmkbuiltin/getopt_r.c0000664000175000017500000007743415053010074020437 0ustar locutuslocutus/* Reentrant version of getopt. Based on ../getopt*.*: Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! Copyright (C) 1987-2016 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . Modifications: Copyright (c) 2018 knut st. osmundsen */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO # define _NO_PROTO #endif #define FAKES_NO_GETOPT_H /* bird */ #ifdef HAVE_CONFIG_H # include #endif #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif #include #if 0 /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 # include # if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #endif #if 1 //ndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ # include # include #endif /* GNU C library. */ #include /* bird: we don't define getopt, so we're good. */ #ifdef VMS # include # if HAVE_STRING_H - 0 # include # endif #endif /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ macro is predefined. */ #include "gettext.h" #define _(msgid) gettext (msgid) /* This version of `getopt' appears to the caller like standard Unix 'getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt_r.h" #include "err.h" #include #if 0 /* Moved to state_getopt_r in getopt_r.h. */ /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ int optind = 1; /* Formerly, initialization of getopt depended on optind==0, which causes problems with re-calling getopt as programs generally don't know that. */ int __getopt_initialized = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; #endif /* Moved to state_getopt_r in getopt_r.h. */ /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ /*static*/ enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } /*ordering*/; #if 0 /* Moved to state_getopt_r in getopt_r.h. */ /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #endif #if 1 //def __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ # include //# define my_index strchr #else # if HAVE_STRING_H # include # else # include # endif #if 0 //def /* Avoid depending on library functions or files whose names are inconsistent. */ #ifndef getenv extern char *getenv (); #endif #endif static char * my_index (const char *str, int chr) { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ # if (!defined __STDC__ || !__STDC__) && !defined strlen /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); # endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ #if 0 /* Moved to state_getopt_r in getopt_r.h. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #endif #if 0 //def _LIBC /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; static int nonoption_flags_max_len; static int nonoption_flags_len; static int original_argc; static char *const *original_argv; /* Make sure the environment variable bash 2.0 puts in the environment is valid for the getopt call we must make sure that the ARGV passed to getopt is that one passed to the process. */ static void __attribute__ ((unused)) store_args_and_env (int argc, char *const *argv) { /* XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ original_argc = argc; original_argv = argv; } # ifdef text_set_element text_set_element (__libc_subinit, store_args_and_env); # endif /* text_set_element */ # define SWAP_FLAGS(ch1, ch2) \ if (nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } #else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) do { } while (0) #endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ static void exchange (struct getopt_state_r *gos, char **argv) { int bottom = gos->first_nonopt; int middle = gos->last_nonopt; int top = gos->optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ #if 0 //def _LIBC /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = malloc (top + 1); if (new_str == NULL) nonoption_flags_len = nonoption_flags_max_len = 0; else { memset (__mempcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len), '\0', top + 1 - nonoption_flags_max_len); nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } #endif while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; SWAP_FLAGS (bottom + i, middle + i); } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ gos->first_nonopt += (gos->optind - gos->last_nonopt); gos->last_nonopt = gos->optind; } /* Initialize the internal data */ void getopt_initialize_r (struct getopt_state_r *gos, int argc, char * const *argv, const char *shortopts, const struct option *long_options, char **envp, struct KMKBUILTINCTX *pCtx) { assert (shortopts != NULL); /* General initialization. */ gos->optarg = NULL; gos->optind = 1; gos->__getopt_initialized = (void *)(uintptr_t)&exchange; gos->opterr = 1; gos->optopt = '?'; gos->argc = argc; gos->argv = argv; gos->optstring = shortopts; gos->len_optstring = strlen (shortopts); gos->long_options = long_options; gos->pCtx = pCtx; /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ gos->first_nonopt = gos->last_nonopt = gos->optind; gos->nextchar = NULL; if (!envp) gos->posixly_correct = getenv("POSIXLY_CORRECT"); else { const char *psz; size_t i = 0; gos->posixly_correct = NULL; while ((psz = envp[i]) != NULL) { if ( psz[0] == 'P' && strncmp (psz, "POSIXLY_CORRECT=", sizeof("POSIXLY_CORRECT=") - 1) == 0) { gos->posixly_correct = psz + sizeof("POSIXLY_CORRECT=") - 1; break; } i++; } } /* Determine how to handle the ordering of options and nonoptions. */ if (shortopts[0] == '-') { gos->ordering = RETURN_IN_ORDER; gos->optstring++; gos->len_optstring--; } else if (shortopts[0] == '+') { gos->ordering = REQUIRE_ORDER; gos->optstring++; gos->len_optstring--; } else if (gos->posixly_correct != NULL) gos->ordering = REQUIRE_ORDER; else gos->ordering = PERMUTE; #if 0 //def _LIBC if (posixly_correct == NULL && argc == original_argc && argv == original_argv) { if (nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; int len = nonoption_flags_max_len = strlen (orig_str); if (nonoption_flags_max_len < argc) nonoption_flags_max_len = argc; __getopt_nonoption_flags = (char *) malloc (nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) nonoption_flags_max_len = -1; else memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), '\0', nonoption_flags_max_len - len); } } nonoption_flags_len = nonoption_flags_max_len; } else nonoption_flags_len = 0; #endif //return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal_r (struct getopt_state_r *gos, const struct option *longopts, int *longind, int long_only) { assert (gos->__getopt_initialized == (void *)(uintptr_t)&exchange); gos->optarg = NULL; #if 0 /* requires explicit call now */ if (gos->optind == 0 || !gos->__getopt_initialized) { if (gos->optind == 0) gos->optind = 1; /* Don't scan ARGV[0], the program name. */ optstring = _getopt_initialize_r (gos, gos->argc, gos->argv, optstring); gos->__getopt_initialized = 1; } #else assert (gos->__getopt_initialized == (void *)(uintptr_t)&exchange); #endif /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #if 0 //def _LIBC # define NONOPTION_P (gos->argv[gos->optind][0] != '-' || gos->argv[gos->optind][1] == '\0' \ || (gos->optind < gos->nonoption_flags_len \ && gos->__getopt_nonoption_flags[gos->optind] == '1')) #else # define NONOPTION_P (gos->argv[gos->optind][0] != '-' || gos->argv[gos->optind][1] == '\0') #endif if (gos->nextchar == NULL || *gos->nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (gos->last_nonopt > gos->optind) gos->last_nonopt = gos->optind; if (gos->first_nonopt > gos->optind) gos->first_nonopt = gos->optind; if (gos->ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (gos->first_nonopt != gos->last_nonopt && gos->last_nonopt != gos->optind) exchange (gos, (char **) gos->argv); else if (gos->last_nonopt != gos->optind) gos->first_nonopt = gos->optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (gos->optind < gos->argc && NONOPTION_P) gos->optind++; gos->last_nonopt = gos->optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (gos->optind != gos->argc && !strcmp (gos->argv[gos->optind], "--")) { gos->optind++; if (gos->first_nonopt != gos->last_nonopt && gos->last_nonopt != gos->optind) exchange (gos, (char **) gos->argv); else if (gos->first_nonopt == gos->last_nonopt) gos->first_nonopt = gos->optind; gos->last_nonopt = gos->argc; gos->optind = gos->argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (gos->optind == gos->argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (gos->first_nonopt != gos->last_nonopt) gos->optind = gos->first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (gos->ordering == REQUIRE_ORDER) return -1; gos->optarg = gos->argv[gos->optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ gos->nextchar = (gos->argv[gos->optind] + 1 + (longopts != NULL && gos->argv[gos->optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (gos->argv[gos->optind][1] == '-' || (long_only && ( gos->argv[gos->optind][2] || !memchr (gos->optstring, gos->argv[gos->optind][1], gos->len_optstring) ) ) ) ) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = gos->nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, gos->nextchar, nameend - gos->nextchar)) { if ((unsigned int) (nameend - gos->nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (gos->opterr) errx (gos->pCtx, 2, _("%s: option '%s' is ambiguous"), gos->argv[0], gos->argv[gos->optind]); gos->nextchar += strlen (gos->nextchar); gos->optind++; gos->optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; gos->optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) gos->optarg = nameend + 1; else { if (gos->opterr) { /* bird: disambiguate */ if (gos->argv[gos->optind - 1][1] == '-') /* --option */ errx (gos->pCtx, 2, _("%s: option '--%s' doesn't allow an argument\n"), gos->argv[0], pfound->name); else /* +option or -option */ errx (gos->pCtx, 2, _("%s: option '%c%s' doesn't allow an argument\n"), gos->argv[0], gos->argv[gos->optind - 1][0], pfound->name); } gos->nextchar += strlen (gos->nextchar); gos->optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (gos->optind < gos->argc) gos->optarg = gos->argv[gos->optind++]; else { if (gos->opterr) errx (gos->pCtx, 2, _("%s: option '%s' requires an argument\n"), gos->argv[0], gos->argv[gos->optind - 1]); gos->nextchar += strlen (gos->nextchar); gos->optopt = pfound->val; return gos->optstring[0] == ':' ? ':' : '?'; } } gos->nextchar += strlen (gos->nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || gos->argv[gos->optind][1] == '-' || memchr(gos->optstring, *gos->nextchar, gos->len_optstring) == NULL) { if (gos->opterr) { if (gos->argv[gos->optind][1] == '-') /* --option */ errx (gos->pCtx, 2, _("%s: unrecognized option '--%s'\n"), gos->argv[0], gos->nextchar); else /* +option or -option */ errx (gos->pCtx, 2, _("%s: unrecognized option '%c%s'\n"), gos->argv[0], gos->argv[gos->optind][0], gos->nextchar); } gos->nextchar = (char *) ""; gos->optind++; gos->optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *gos->nextchar++; char *temp = (char *)memchr (gos->optstring, c, gos->len_optstring); /* Increment `optind' when we start to process its last character. */ if (*gos->nextchar == '\0') ++gos->optind; if (temp == NULL || c == ':') { if (gos->opterr) { if (gos->posixly_correct) /* 1003.2 specifies the format of this message. */ errx (gos->pCtx, 2, _("%s: illegal option -- %c\n"), gos->argv[0], c); else errx (gos->pCtx, 2, _("%s: invalid option -- %c\n"), gos->argv[0], c); } gos->optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*gos->nextchar != '\0') { gos->optarg = gos->nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ gos->optind++; } else if (gos->optind == gos->argc) { if (gos->opterr) { /* 1003.2 specifies the format of this message. */ errx (gos->pCtx, 2, _("%s: option requires an argument -- %c\n"), gos->argv[0], c); } gos->optopt = c; if (gos->optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ gos->optarg = gos->argv[gos->optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (gos->nextchar = nameend = gos->optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, gos->nextchar, nameend - gos->nextchar)) { if ((unsigned int) (nameend - gos->nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (gos->opterr) errx (gos->pCtx, 2, _("%s: option '-W %s' is ambiguous\n"), gos->argv[0], gos->argv[gos->optind]); gos->nextchar += strlen (gos->nextchar); gos->optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) gos->optarg = nameend + 1; else { if (gos->opterr) errx (gos->pCtx, 2, _("%s: option '-W %s' doesn't allow an argument\n"), gos->argv[0], pfound->name); gos->nextchar += strlen (gos->nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (gos->optind < gos->argc) gos->optarg = gos->argv[gos->optind++]; else { if (gos->opterr) errx (gos->pCtx, 2, _("%s: option '%s' requires an argument\n"), gos->argv[0], gos->argv[gos->optind - 1]); gos->nextchar += strlen (gos->nextchar); return gos->optstring[0] == ':' ? ':' : '?'; } } gos->nextchar += strlen (gos->nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } gos->nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*gos->nextchar != '\0') { gos->optarg = gos->nextchar; gos->optind++; } else gos->optarg = NULL; gos->nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*gos->nextchar != '\0') { gos->optarg = gos->nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ gos->optind++; } else if (gos->optind == gos->argc) { if (gos->opterr) { /* 1003.2 specifies the format of this message. */ errx (gos->pCtx, 2, _("%s: option requires an argument -- %c\n"), gos->argv[0], c); } gos->optopt = c; if (gos->optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ gos->optarg = gos->argv[gos->optind++]; gos->nextchar = NULL; } } return c; } } int getopt_r (struct getopt_state_r *gos) { return _getopt_internal_r (gos, NULL, NULL, 0); } #endif /* #if 1 */ /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (int argc, char **argv) { int c; int digit_optind = 0; struct getopt_state_r = gos; getopt_initialize_r (&gos, argc, argv, "abc:d:0123456789", NULL, NULL, NULL); while (1) { int this_option_optind = gos.optind ? gos.optind : 1; c = getopt_r (&gos); if (c == -1) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value '%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (gos.optind < argc) { printf ("non-option ARGV-elements: "); while (gos.optind < argc) printf ("%s ", argv[gos.optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ kbuild-3686/src/kmk/kmkbuiltin/cmp_util.c0000664000175000017500000003705615053010074020424 0ustar locutuslocutus/* $NetBSD: cmp.c,v 1.15 2006/01/19 20:44:57 garbled Exp $ */ /* $NetBSD: misc.c,v 1.11 2007/08/22 16:59:19 christos Exp $ */ /* $NetBSD: regular.c,v 1.20 2006/06/03 21:47:55 christos Exp $ */ /* $NetBSD: special.c,v 1.12 2007/08/21 14:09:54 christos Exp $ */ /* * Copyright (c) 1987, 1990, 1993, 1994 * 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. 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. */ /*__COPYRIGHT("@(#) Copyright (c) 1987, 1990, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n");*/ #ifdef _MSC_VER # define MSC_DO_64_BIT_IO #endif #include "config.h" #include #include #if defined(__FreeBSD__) || defined(__NetBSD__) /** @todo more mmap capable OSes. */ # define CMP_USE_MMAP # include # include #endif #include #include #include #include #include #ifndef _MSC_VER # include # ifndef O_BINARY # define O_BINARY 0 # endif #else # include "mscfakes.h" #endif #include "err.h" #include "cmp_extern.h" static int errmsg(PKMKBUILTINCTX pCtx, const char *file, off_t byte, off_t line, int lflag) { if (lflag) #ifdef _MSC_VER return err(pCtx, ERR_EXIT, "%s: char %I64d, line %lld", file, (__int64)byte, (long long)line); #else return err(pCtx, ERR_EXIT, "%s: char %lld, line %lld", file, (long long)byte, (long long)line); #endif return err(pCtx, ERR_EXIT, "%s", file); } static int eofmsg(PKMKBUILTINCTX pCtx, const char *file, off_t byte, off_t line, int sflag, int lflag) { if (!sflag) { if (!lflag) warnx(pCtx, "EOF on %s", file); else { #ifdef _MSC_VER if (line > 0) warnx(pCtx, "EOF on %s: char %I64d, line %I64d", file, (__int64)byte, (__int64)line); else warnx(pCtx, "EOF on %s: char %I64d", file, (__int64)byte); #else if (line > 0) warnx(pCtx, "EOF on %s: char %lld, line %lld", file, (long long)byte, (long long)line); else warnx(pCtx, "EOF on %s: char %lld", file, (long long)byte); #endif } } return DIFF_EXIT; } static int diffmsg(PKMKBUILTINCTX pCtx, const char *file1, const char *file2, off_t byte, off_t line, int sflag) { if (!sflag) #ifdef _MSC_VER kmk_builtin_ctx_printf(pCtx, 0, "%s %s differ: char %I64d, line %I64d\n", file1, file2, (__int64)byte, (__int64)line); #else kmk_builtin_ctx_printf(pCtx, 0, "%s %s differ: char %lld, line %lld\n", file1, file2, (long long)byte, (long long)line); #endif return DIFF_EXIT; } /** * Compares two files, where one or both are non-regular ones. */ static int c_special(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, int fd2, const char *file2, off_t skip2, int lflag, int sflag) { int fd1dup, fd2dup; FILE *fp1; int rc; /* duplicate because fdopen+fclose will otherwise close the handle. */ fd1dup = dup(fd1); if (fd1 < 0) return err(pCtx, ERR_EXIT, "%s", file1); fp1 = fdopen(fd1dup, "rb"); if (!fp1) fp1 = fdopen(fd1dup, "r"); if (!fp1) { err(pCtx, ERR_EXIT, "%s", file1); close(fd1dup); return ERR_EXIT; } fd2dup = dup(fd2); if (fd2dup >= 0) { FILE *fp2 = fdopen(fd2dup, "rb"); if (!fp2) fp2 = fdopen(fd2dup, "r"); if (fp2) { off_t byte; off_t line; int ch1 = 0; int ch2 = 0; /* skipping ahead */ rc = OK_EXIT; for (byte = line = 1; skip1--; byte++) { ch1 = getc(fp1); if (ch1 == EOF) break; if (ch1 == '\n') line++; } for (byte = line = 1; skip2--; byte++) { ch2 = getc(fp2); if (ch2 == EOF) break; if (ch2 == '\n') line++; } if (ch2 != EOF && ch1 != EOF) { /* compare byte by byte */ for (byte = line = 1;; ++byte) { ch1 = getc(fp1); ch2 = getc(fp2); if (ch1 == EOF || ch2 == EOF) break; if (ch1 != ch2) { if (!lflag) { rc = diffmsg(pCtx, file1, file2, byte, line, sflag); break; } rc = DIFF_EXIT; #ifdef _MSC_VER kmk_builtin_ctx_printf(pCtx, 0, "%6i64d %3o %3o\n", (__int64)byte, ch1, ch2); #else kmk_builtin_ctx_printf(pCtx, 0, "%6lld %3o %3o\n", (long long)byte, ch1, ch2); #endif } if (ch1 == '\n') ++line; } } /* Check for errors and length differences (EOF). */ if (ferror(fp1) && rc != ERR_EXIT) rc = errmsg(pCtx, file1, byte, line, lflag); if (ferror(fp2) && rc != ERR_EXIT) rc = errmsg(pCtx, file2, byte, line, lflag); if (rc == OK_EXIT) { if (feof(fp1)) { if (!feof(fp2)) rc = eofmsg(pCtx, file1, byte, line, sflag, lflag); } else if (feof(fp2)) rc = eofmsg(pCtx, file2, byte, line, sflag, lflag); } fclose(fp2); } else { rc = err(pCtx, ERR_EXIT, "%s", file2); close(fd2dup); } } else rc = err(pCtx, ERR_EXIT, "%s", file2); fclose(fp1); return rc; } #ifdef CMP_USE_MMAP /** * Compare two files using mmap. */ static int c_regular(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, off_t len1, int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag) { unsigned char ch, *p1, *p2, *b1, *b2; off_t byte, length, line; int dfound; size_t blk_sz, blk_cnt; if (sflag && len1 != len2) return DIFF_EXIT; if (skip1 > len1) return eofmsg(pCtx, file1, len1 + 1, 0, sflag, lflag); len1 -= skip1; if (skip2 > len2) return eofmsg(pCtx, file2, len2 + 1, 0, sflag, lflag); len2 -= skip2; byte = line = 1; dfound = 0; length = len1 <= len2 ? len1 : len2; for (blk_sz = 1024 * 1024; length != 0; length -= blk_sz) { if (blk_sz > length) blk_sz = length; b1 = p1 = mmap(NULL, blk_sz, PROT_READ, MAP_FILE | MAP_SHARED, fd1, skip1); if (p1 == MAP_FAILED) goto l_mmap_failed; b2 = p2 = mmap(NULL, blk_sz, PROT_READ, MAP_FILE | MAP_SHARED, fd2, skip2); if (p2 == MAP_FAILED) { munmap(p1, blk_sz); goto l_mmap_failed; } blk_cnt = blk_sz; for (; blk_cnt--; ++p1, ++p2, ++byte) { if ((ch = *p1) != *p2) { if (!lflag) { munmap(b1, blk_sz); munmap(b2, blk_sz); return diffmsg(pCtx, file1, file2, byte, line, sflag); } dfound = 1; #ifdef _MSC_VER kmk_builtin_ctx_printf(pCtx, 0, "%6I64d %3o %3o\n", (__int64)byte, ch, *p2); #else kmk_builtin_ctx_printf(pCtx, 0, "%6lld %3o %3o\n", (long long)byte, ch, *p2); #endif } if (ch == '\n') ++line; } munmap(p1 - blk_sz, blk_sz); munmap(p2 - blk_sz, blk_sz); skip1 += blk_sz; skip2 += blk_sz; } if (len1 != len2) return eofmsg(pCtx, len1 > len2 ? file2 : file1, byte, line, sflag, lflag); if (dfound) return DIFF_EXIT; return OK_EXIT; l_mmap_failed: return c_special(pCtx, fd1, file1, skip1, fd2, file2, skip2, lflag, sflag); } #else /* non-mmap c_regular: */ /** * Compare two files without mmaping them. */ static int c_regular(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, off_t len1, int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag) { unsigned char ch, *p1, *p2, *b1 = 0, *b2 = 0; off_t byte, length, line, bytes_read; int dfound; size_t blk_sz, blk_cnt; if (sflag && len1 != len2) return DIFF_EXIT; if (skip1 > len1) return eofmsg(pCtx, file1, len1 + 1, 0, sflag, lflag); len1 -= skip1; if (skip2 > len2) return eofmsg(pCtx, file2, len2 + 1, 0, sflag, lflag); len2 -= skip2; if (skip1 && lseek(fd1, skip1, SEEK_SET) < 0) goto l_special; if (skip2 && lseek(fd2, skip2, SEEK_SET) < 0) { if (skip1 && lseek(fd1, 0, SEEK_SET) < 0) return err(pCtx, 1, "seek failed"); goto l_special; } #define CMP_BUF_SIZE (128*1024) b1 = malloc(CMP_BUF_SIZE); b2 = malloc(CMP_BUF_SIZE); if (!b1 || !b2) goto l_malloc_failed; byte = line = 1; dfound = 0; length = len1; if (length > len2) length = len2; for (blk_sz = CMP_BUF_SIZE; length != 0; length -= blk_sz) { if ((off_t)blk_sz > length) blk_sz = (size_t)length; bytes_read = read(fd1, b1, blk_sz); if (bytes_read != (off_t)blk_sz) goto l_read_error; bytes_read = read(fd2, b2, blk_sz); if (bytes_read != (off_t)blk_sz) goto l_read_error; blk_cnt = blk_sz; p1 = b1; p2 = b2; for (; blk_cnt--; ++p1, ++p2, ++byte) { if ((ch = *p1) != *p2) { if (!lflag) { free(b1); free(b2); return diffmsg(pCtx, file1, file2, byte, line, sflag); } dfound = 1; #ifdef _MSC_VER kmk_builtin_ctx_printf(pCtx, 0, "%6I64d %3o %3o\n", (__int64)byte, ch, *p2); #else kmk_builtin_ctx_printf(pCtx, 0, "%6lld %3o %3o\n", (long long)byte, ch, *p2); #endif } if (ch == '\n') ++line; } skip1 += blk_sz; skip2 += blk_sz; } if (len1 != len2) return eofmsg(pCtx, len1 > len2 ? file2 : file1, byte, line, sflag, lflag); if (dfound) return DIFF_EXIT; return OK_EXIT; l_read_error: if ( lseek(fd1, 0, SEEK_SET) < 0 || lseek(fd2, 0, SEEK_SET) < 0) { err(pCtx, 1, "seek failed"); free(b1); free(b2); return 1; } l_malloc_failed: free(b1); free(b2); l_special: return c_special(pCtx, fd1, file1, skip1, fd2, file2, skip2, lflag, sflag); } #endif /* non-mmap c_regular */ /** * Compares two open files. */ int cmp_fd_and_fd_ex(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, int fd2, const char *file2, off_t skip2, int sflag, int lflag, int special) { struct stat st1, st2; int rc; if (fstat(fd1, &st1)) return err(pCtx, ERR_EXIT, "%s", file1); if (fstat(fd2, &st2)) return err(pCtx, ERR_EXIT, "%s", file2); if ( !S_ISREG(st1.st_mode) || !S_ISREG(st2.st_mode) || special) rc = c_special(pCtx, fd1, file1, skip1, fd2, file2, skip2, sflag, lflag); else rc = c_regular(pCtx, fd1, file1, skip1, st1.st_size, fd2, file2, skip2, st2.st_size, sflag, lflag); return rc; } /** * Compares two open files. */ int cmp_fd_and_fd(PKMKBUILTINCTX pCtx, int fd1, const char *file1, int fd2, const char *file2, int sflag, int lflag, int special) { return cmp_fd_and_fd_ex(pCtx, fd1, file1, 0, fd2, file2, 0, sflag, lflag, special); } /** * Compares an open file with another that isn't open yet. */ int cmp_fd_and_file_ex(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, const char *file2, off_t skip2, int sflag, int lflag, int special) { int rc; int fd2; if (!strcmp(file2, "-")) { fd2 = 0 /* stdin */; special = 1; file2 = "stdin"; } else fd2 = open(file2, O_RDONLY | O_BINARY | KMK_OPEN_NO_INHERIT, 0); if (fd2 >= 0) { rc = cmp_fd_and_fd_ex(pCtx, fd1, file1, skip1, fd2, file2, skip2, sflag, lflag, special); close(fd2); } else { if (!sflag) warn(pCtx, "%s", file2); rc = ERR_EXIT; } return rc; } /** * Compares an open file with another that isn't open yet. */ int cmp_fd_and_file(PKMKBUILTINCTX pCtx, int fd1, const char *file1, const char *file2, int sflag, int lflag, int special) { return cmp_fd_and_file_ex(pCtx, fd1, file1, 0, file2, 0, sflag, lflag, special); } /** * Opens and compare two files. */ int cmp_file_and_file_ex(PKMKBUILTINCTX pCtx, const char *file1, off_t skip1, const char *file2, off_t skip2, int sflag, int lflag, int special) { int fd1; int rc; if (lflag && sflag) return errx(pCtx, ERR_EXIT, "only one of -l and -s may be specified"); if (!strcmp(file1, "-")) { if (!strcmp(file2, "-")) return errx(pCtx, ERR_EXIT, "standard input may only be specified once"); file1 = "stdin"; fd1 = 1; special = 1; } else fd1 = open(file1, O_RDONLY | O_BINARY | KMK_OPEN_NO_INHERIT, 0); if (fd1 >= 0) { rc = cmp_fd_and_file_ex(pCtx, fd1, file1, skip1, file2, skip2, sflag, lflag, special); close(fd1); } else { if (!sflag) warn(pCtx, "%s", file1); rc = ERR_EXIT; } return rc; } /** * Opens and compare two files. */ int cmp_file_and_file(PKMKBUILTINCTX pCtx, const char *file1, const char *file2, int sflag, int lflag, int special) { return cmp_file_and_file_ex(pCtx, file1, 0, file2, 0, sflag, lflag, special); } kbuild-3686/src/kmk/kmkbuiltin/cp.c0000664000175000017500000006057615053010074017215 0ustar locutuslocutus/* * Copyright (c) 1988, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * David Hitz of Auspex Systems Inc. * * 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. * 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 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1988, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)cp.c 8.2 (Berkeley) 4/1/94"; #endif /* not lint */ #include __FBSDID("$FreeBSD: src/bin/cp/cp.c,v 1.50 2004/04/06 20:06:44 markm Exp $"); #endif /* * Cp copies source files to target files. * * The global PATH_T structure "to" always contains the path to the * current target file. Since fts(3) does not change directories, * this path can be either absolute or dot-relative. * * The basic algorithm is to initialize "to" and use fts(3) to traverse * the file hierarchy rooted in the argument list. A trivial case is the * case of 'cp file1 file2'. The more interesting case is the case of * 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the * path (relative to the root of the traversal) is appended to dir (stored * in "to") to form the final target path. */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #define FAKES_NO_GETOPT_H /* bird */ #include "config.h" #include #include #include #include "err.h" #include #include "fts.h" #include #include #include #include #include #include #include "getopt_r.h" #include "k/kDefs.h" #ifdef _MSC_VER # include "mscfakes.h" #endif #include "cp_extern.h" #include "kmkbuiltin.h" #include "kbuild_protection.h" #if defined(_MSC_VER) || defined(__gnu_linux__) || defined(__linux__) extern size_t strlcpy(char *, const char *, size_t); #endif /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ #ifndef S_IFWHT #define S_IFWHT 0 #define S_ISWHT(s) 0 #define undelete(s) (-1) #endif #ifndef S_ISTXT #ifdef S_ISVTX #define S_ISTXT S_ISVTX #else #define S_ISTXT 0 #endif #endif /* !S_ISTXT */ #ifndef __unused # define __unused #endif #if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 # define IS_SLASH(ch) ((ch) == '/' || (ch) == '\\') #else # define IS_SLASH(ch) ((ch) == '/') #endif #define STRIP_TRAILING_SLASH(p) { \ while ((p).p_end > (p).p_path + 1 && IS_SLASH((p).p_end[-1])) \ *--(p).p_end = 0; \ } /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ typedef struct CPINSTANCE { CPUTILSINSTANCE Utils; int Rflag, rflag; int cp_ignore_non_existing, cp_changed_only; KBUILDPROTECTION g_ProtData; } CPINSTANCE; /* have wrappers for globals in cp_extern! */ enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE }; /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ enum cp_arg { CP_OPT_HELP = 261, CP_OPT_VERSION, CP_OPT_IGNORE_NON_EXISTING, CP_OPT_CHANGED, CP_OPT_DISABLE_PROTECTION, CP_OPT_ENABLE_PROTECTION, CP_OPT_ENABLE_FULL_PROTECTION, CP_OPT_DISABLE_FULL_PROTECTION, CP_OPT_PROTECTION_DEPTH }; static struct option long_options[] = { { "help", no_argument, 0, CP_OPT_HELP }, { "version", no_argument, 0, CP_OPT_VERSION }, { "ignore-non-existing", no_argument, 0, CP_OPT_IGNORE_NON_EXISTING }, { "changed", no_argument, 0, CP_OPT_CHANGED }, { "disable-protection", no_argument, 0, CP_OPT_DISABLE_PROTECTION }, { "enable-protection", no_argument, 0, CP_OPT_ENABLE_PROTECTION }, { "enable-full-protection", no_argument, 0, CP_OPT_ENABLE_FULL_PROTECTION }, { "disable-full-protection", no_argument, 0, CP_OPT_DISABLE_FULL_PROTECTION }, { "protection-depth", required_argument, 0, CP_OPT_PROTECTION_DEPTH }, { 0, 0, 0, 0 }, }; static char emptystring[] = ""; #if defined(SIGINFO) && defined(KMK_BUILTIN_STANDALONE) volatile sig_atomic_t g_cp_info; #endif extern mode_t g_fUMask; /********************************************************************************************************************************* * Internal Functions * *********************************************************************************************************************************/ static int copy(CPINSTANCE *pThis, char * const *, enum op, int); #ifdef FTSCALL static int FTSCALL mastercmp(const FTSENT * const *, const FTSENT * const *); #else static int mastercmp(const FTSENT **, const FTSENT **); #endif #if defined(SIGINFO) && defined(KMK_BUILTIN_STANDALONE) static void siginfo(int __unused); #endif static int usage(PKMKBUILTINCTX, int); int kmk_builtin_cp(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { CPINSTANCE This; struct getopt_state_r gos; struct stat to_stat, tmp_stat; enum op type; int Hflag, Lflag, Pflag, ch, fts_options, r, have_trailing_slash, rc; char *target; /* init globals */ This.Utils.pCtx = pCtx; This.Utils.to.p_end = This.Utils.to.p_path; This.Utils.to.target_end = emptystring; memset(This.Utils.to.p_path, 0, sizeof(This.Utils.to.p_path)); This.Utils.fflag = 0; This.Utils.iflag = 0; This.Utils.nflag = 0; This.Utils.pflag = 0; This.Utils.vflag = 0; This.Rflag = 0; This.rflag = 0; This.cp_ignore_non_existing = This.cp_changed_only = 0; kBuildProtectionInit(&This.g_ProtData, pCtx); Hflag = Lflag = Pflag = 0; getopt_initialize_r(&gos, argc, argv, "HLPRfinprv", long_options, envp, pCtx); while ((ch = getopt_long_r(&gos, NULL)) != -1) switch (ch) { case 'H': Hflag = 1; Lflag = Pflag = 0; break; case 'L': Lflag = 1; Hflag = Pflag = 0; break; case 'P': Pflag = 1; Hflag = Lflag = 0; break; case 'R': This.Rflag = 1; break; case 'f': This.Utils.fflag = 1; This.Utils.iflag = This.Utils.nflag = 0; break; case 'i': This.Utils.iflag = 1; This.Utils.fflag = This.Utils.nflag = 0; break; case 'n': This.Utils.nflag = 1; This.Utils.fflag = This.Utils.iflag = 0; break; case 'p': This.Utils.pflag = 1; break; case 'r': This.rflag = 1; break; case 'v': This.Utils.vflag = 1; break; case CP_OPT_HELP: usage(pCtx, 0); kBuildProtectionTerm(&This.g_ProtData); return 0; case CP_OPT_VERSION: kBuildProtectionTerm(&This.g_ProtData); return kbuild_version(argv[0]); case CP_OPT_IGNORE_NON_EXISTING: This.cp_ignore_non_existing = 1; break; case CP_OPT_CHANGED: This.cp_changed_only = 1; break; case CP_OPT_DISABLE_PROTECTION: kBuildProtectionDisable(&This.g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); break; case CP_OPT_ENABLE_PROTECTION: kBuildProtectionEnable(&This.g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); break; case CP_OPT_ENABLE_FULL_PROTECTION: kBuildProtectionEnable(&This.g_ProtData, KBUILDPROTECTIONTYPE_FULL); break; case CP_OPT_DISABLE_FULL_PROTECTION: kBuildProtectionDisable(&This.g_ProtData, KBUILDPROTECTIONTYPE_FULL); break; case CP_OPT_PROTECTION_DEPTH: if (kBuildProtectionSetDepth(&This.g_ProtData, gos.optarg)) { kBuildProtectionTerm(&This.g_ProtData); return 1; } break; default: kBuildProtectionTerm(&This.g_ProtData); return usage(pCtx, 1); } argc -= gos.optind; argv += gos.optind; if (argc < 2) { kBuildProtectionTerm(&This.g_ProtData); return usage(pCtx, 1); } fts_options = FTS_NOCHDIR | FTS_PHYSICAL; if (This.rflag) { if (This.Rflag) { kBuildProtectionTerm(&This.g_ProtData); return errx(pCtx, 1, "the -R and -r options may not be specified together."); } if (Hflag || Lflag || Pflag) errx(pCtx, 1, "the -H, -L, and -P options may not be specified with the -r option."); fts_options &= ~FTS_PHYSICAL; fts_options |= FTS_LOGICAL; } if (This.Rflag) { if (Hflag) fts_options |= FTS_COMFOLLOW; if (Lflag) { fts_options &= ~FTS_PHYSICAL; fts_options |= FTS_LOGICAL; } } else { fts_options &= ~FTS_PHYSICAL; fts_options |= FTS_LOGICAL | FTS_COMFOLLOW; } #if defined(SIGINFO) && defined(KMK_BUILTIN_STANDALONE) (void)signal(SIGINFO, siginfo); #endif /* Save the target base in "to". */ target = argv[--argc]; if (strlcpy(This.Utils.to.p_path, target, sizeof(This.Utils.to.p_path)) >= sizeof(This.Utils.to.p_path)) { kBuildProtectionTerm(&This.g_ProtData); return errx(pCtx, 1, "%s: name too long", target); } This.Utils.to.p_end = This.Utils.to.p_path + strlen(This.Utils.to.p_path); if (This.Utils.to.p_path == This.Utils.to.p_end) { *This.Utils.to.p_end++ = '.'; *This.Utils.to.p_end = 0; } have_trailing_slash = IS_SLASH(This.Utils.to.p_end[-1]); if (have_trailing_slash) STRIP_TRAILING_SLASH(This.Utils.to); This.Utils.to.target_end = This.Utils.to.p_end; /* Set end of argument list for fts(3). */ argv[argc] = NULL; /* * Cp has two distinct cases: * * cp [-R] source target * cp [-R] source1 ... sourceN directory * * In both cases, source can be either a file or a directory. * * In (1), the target becomes a copy of the source. That is, if the * source is a file, the target will be a file, and likewise for * directories. * * In (2), the real target is not directory, but "directory/source". */ r = stat(This.Utils.to.p_path, &to_stat); if (r == -1 && errno != ENOENT) { kBuildProtectionTerm(&This.g_ProtData); return err(pCtx, 1, "stat: %s", This.Utils.to.p_path); } if (r == -1 || !S_ISDIR(to_stat.st_mode)) { /* * Case (1). Target is not a directory. */ if (argc > 1) { kBuildProtectionTerm(&This.g_ProtData); return usage(pCtx, 1); } /* * Need to detect the case: * cp -R dir foo * Where dir is a directory and foo does not exist, where * we want pathname concatenations turned on but not for * the initial mkdir(). */ if (r == -1) { if (This.rflag || (This.Rflag && (Lflag || Hflag))) stat(*argv, &tmp_stat); else lstat(*argv, &tmp_stat); if (S_ISDIR(tmp_stat.st_mode) && (This.Rflag || This.rflag)) type = DIR_TO_DNE; else type = FILE_TO_FILE; } else type = FILE_TO_FILE; if (have_trailing_slash && type == FILE_TO_FILE) { kBuildProtectionTerm(&This.g_ProtData); if (r == -1) return errx(pCtx, 1, "directory %s does not exist", This.Utils.to.p_path); else return errx(pCtx, 1, "%s is not a directory", This.Utils.to.p_path); } } else /* * Case (2). Target is a directory. */ type = FILE_TO_DIR; /* Finally, check that the "to" directory isn't protected. */ rc = 1; if (!kBuildProtectionScanEnv(&This.g_ProtData, envp, "KMK_CP_") && !kBuildProtectionEnforce(&This.g_ProtData, This.Rflag || This.rflag ? KBUILDPROTECTIONTYPE_RECURSIVE : KBUILDPROTECTIONTYPE_FULL, This.Utils.to.p_path)) { rc = copy(&This, argv, type, fts_options); } kBuildProtectionTerm(&This.g_ProtData); return rc; } #ifdef KMK_BUILTIN_STANDALONE mode_t g_fUMask; int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_cp", NULL }; umask(g_fUMask = umask(0077)); return kmk_builtin_cp(argc, argv, envp, &Ctx); } #endif static int copy(CPINSTANCE *pThis, char * const *argv, enum op type, int fts_options) { struct stat to_stat; FTS *ftsp; FTSENT *curr; int base = 0, dne, badcp, rval; size_t nlen; char *p, *target_mid; mode_t mask, mode; /* * Keep an inverted copy of the umask, for use in correcting * permissions on created directories when not using -p. */ mask = g_fUMask; assert(mask == umask(mask)); mask = ~mask; if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL) return err(pThis->Utils.pCtx, 1, "fts_open"); for (badcp = rval = 0; (curr = fts_read(ftsp)) != NULL; badcp = 0) { int copied = 0; switch (curr->fts_info) { case FTS_NS: if ( pThis->cp_ignore_non_existing && curr->fts_errno == ENOENT) { if (pThis->Utils.vflag) { warnx(pThis->Utils.pCtx, "fts: %s: %s", curr->fts_path, strerror(curr->fts_errno)); } continue; } /* fall thru */ case FTS_DNR: case FTS_ERR: warnx(pThis->Utils.pCtx, "fts: %s: %s", curr->fts_path, strerror(curr->fts_errno)); badcp = rval = 1; continue; case FTS_DC: /* Warn, continue. */ warnx(pThis->Utils.pCtx, "%s: directory causes a cycle", curr->fts_path); badcp = rval = 1; continue; default: ; } /* * If we are in case (2) or (3) above, we need to append the * source name to the target name. */ if (type != FILE_TO_FILE) { /* * Need to remember the roots of traversals to create * correct pathnames. If there's a directory being * copied to a non-existent directory, e.g. * cp -R a/dir noexist * the resulting path name should be noexist/foo, not * noexist/dir/foo (where foo is a file in dir), which * is the case where the target exists. * * Also, check for "..". This is for correct path * concatenation for paths ending in "..", e.g. * cp -R .. /tmp * Paths ending in ".." are changed to ".". This is * tricky, but seems the easiest way to fix the problem. * * XXX * Since the first level MUST be FTS_ROOTLEVEL, base * is always initialized. */ if (curr->fts_level == FTS_ROOTLEVEL) { if (type != DIR_TO_DNE) { p = strrchr(curr->fts_path, '/'); #if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 if (strrchr(curr->fts_path, '\\') > p) p = strrchr(curr->fts_path, '\\'); #endif base = (p == NULL) ? 0 : (int)(p - curr->fts_path + 1); if (!strcmp(&curr->fts_path[base], "..")) base += 1; } else base = curr->fts_pathlen; } p = &curr->fts_path[base]; nlen = curr->fts_pathlen - base; target_mid = pThis->Utils.to.target_end; if (!IS_SLASH(*p) && !IS_SLASH(target_mid[-1])) *target_mid++ = '/'; *target_mid = 0; if (target_mid - pThis->Utils.to.p_path + nlen >= PATH_MAX) { warnx(pThis->Utils.pCtx, "%s%s: name too long (not copied)", pThis->Utils.to.p_path, p); badcp = rval = 1; continue; } (void)strncat(target_mid, p, nlen); pThis->Utils.to.p_end = target_mid + nlen; *pThis->Utils.to.p_end = 0; STRIP_TRAILING_SLASH(pThis->Utils.to); } if (curr->fts_info == FTS_DP) { /* * We are nearly finished with this directory. If we * didn't actually copy it, or otherwise don't need to * change its attributes, then we are done. */ if (!curr->fts_number) continue; /* * If -p is in effect, set all the attributes. * Otherwise, set the correct permissions, limited * by the umask. Optimise by avoiding a chmod() * if possible (which is usually the case if we * made the directory). Note that mkdir() does not * honour setuid, setgid and sticky bits, but we * normally want to preserve them on directories. */ if (pThis->Utils.pflag) { if (copy_file_attribs(&pThis->Utils, curr->fts_statp, -1)) rval = 1; } else { mode = curr->fts_statp->st_mode; if ((mode & (S_ISUID | S_ISGID | S_ISTXT)) || ((mode | S_IRWXU) & mask) != (mode & mask)) if (chmod(pThis->Utils.to.p_path, mode & mask) != 0){ warn(pThis->Utils.pCtx, "chmod: %s", pThis->Utils.to.p_path); rval = 1; } } continue; } /* Not an error but need to remember it happened */ if (stat(pThis->Utils.to.p_path, &to_stat) == -1) dne = 1; else { if (to_stat.st_dev == curr->fts_statp->st_dev && to_stat.st_dev != 0 && to_stat.st_ino == curr->fts_statp->st_ino && to_stat.st_ino != 0) { warnx(pThis->Utils.pCtx, "%s and %s are identical (not copied).", pThis->Utils.to.p_path, curr->fts_path); badcp = rval = 1; if (S_ISDIR(curr->fts_statp->st_mode)) (void)fts_set(ftsp, curr, FTS_SKIP); continue; } if (!S_ISDIR(curr->fts_statp->st_mode) && S_ISDIR(to_stat.st_mode)) { warnx(pThis->Utils.pCtx, "cannot overwrite directory %s with " "non-directory %s", pThis->Utils.to.p_path, curr->fts_path); badcp = rval = 1; continue; } dne = 0; } switch (curr->fts_statp->st_mode & S_IFMT) { #ifdef S_IFLNK case S_IFLNK: /* Catch special case of a non-dangling symlink */ if ((fts_options & FTS_LOGICAL) || ((fts_options & FTS_COMFOLLOW) && curr->fts_level == 0)) { if (copy_file(&pThis->Utils, curr, dne, pThis->cp_changed_only, &copied)) badcp = rval = 1; } else { if (copy_link(&pThis->Utils, curr, !dne)) badcp = rval = 1; } break; #endif case S_IFDIR: if (!pThis->Rflag && !pThis->rflag) { warnx(pThis->Utils.pCtx, "%s is a directory (not copied).", curr->fts_path); (void)fts_set(ftsp, curr, FTS_SKIP); badcp = rval = 1; break; } /* * If the directory doesn't exist, create the new * one with the from file mode plus owner RWX bits, * modified by the umask. Trade-off between being * able to write the directory (if from directory is * 555) and not causing a permissions race. If the * umask blocks owner writes, we fail.. */ if (dne) { if (mkdir(pThis->Utils.to.p_path, curr->fts_statp->st_mode | S_IRWXU) < 0) return err(pThis->Utils.pCtx, 1, "mkdir: %s", pThis->Utils.to.p_path); } else if (!S_ISDIR(to_stat.st_mode)) { errno = ENOTDIR; return err(pThis->Utils.pCtx, 1, "to-mode: %s", pThis->Utils.to.p_path); } /* * Arrange to correct directory attributes later * (in the post-order phase) if this is a new * directory, or if the -p flag is in effect. */ curr->fts_number = pThis->Utils.pflag || dne; break; #ifdef S_IFBLK case S_IFBLK: #endif case S_IFCHR: if (pThis->Rflag) { if (copy_special(&pThis->Utils, curr->fts_statp, !dne)) badcp = rval = 1; } else { if (copy_file(&pThis->Utils, curr, dne, pThis->cp_changed_only, &copied)) badcp = rval = 1; } break; #ifdef S_IFIFO case S_IFIFO: #endif if (pThis->Rflag) { if (copy_fifo(&pThis->Utils, curr->fts_statp, !dne)) badcp = rval = 1; } else { if (copy_file(&pThis->Utils, curr, dne, pThis->cp_changed_only, &copied)) badcp = rval = 1; } break; default: if (copy_file(&pThis->Utils, curr, dne, pThis->cp_changed_only, &copied)) badcp = rval = 1; break; } if (pThis->Utils.vflag && !badcp) kmk_builtin_ctx_printf(pThis->Utils.pCtx, 0, copied ? "%s -> %s\n" : "%s matches %s - not copied\n", curr->fts_path, pThis->Utils.to.p_path); } if (errno) return err(pThis->Utils.pCtx, 1, "fts_read"); return (rval); } /* * mastercmp -- * The comparison function for the copy order. The order is to copy * non-directory files before directory files. The reason for this * is because files tend to be in the same cylinder group as their * parent directory, whereas directories tend not to be. Copying the * files first reduces seeking. */ #ifdef FTSCALL static int FTSCALL mastercmp(const FTSENT * const *a, const FTSENT * const *b) #else static int mastercmp(const FTSENT **a, const FTSENT **b) #endif { int a_info, b_info; a_info = (*a)->fts_info; if (a_info == FTS_ERR || a_info == FTS_NS || a_info == FTS_DNR) return (0); b_info = (*b)->fts_info; if (b_info == FTS_ERR || b_info == FTS_NS || b_info == FTS_DNR) return (0); if (a_info == FTS_D) return (-1); if (b_info == FTS_D) return (1); return (0); } #if defined(SIGINFO) && defined(KMK_BUILTIN_STANDALONE) static void siginfo(int sig __unused) { g_cp_info = 1; } #endif static int usage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s [options] src target\n" " or: %s [options] src1 ... srcN directory\n" " or: %s --help\n" " or: %s --version\n" "\n" "Options:\n" " -R Recursive copy.\n" " -H Follow symbolic links on the commandline. Only valid with -R.\n" " -L Follow all symbolic links. Only valid with -R.\n" " -P Do not follow symbolic links. Default. Only valid with -R\n" " -f Force. Overrides -i and -n.\n" " -i Iteractive. Overrides -n and -f.\n" " -n Don't overwrite any files. Overrides -i and -f.\n" " -v Verbose.\n" " --ignore-non-existing\n" " Don't fail if the specified source file doesn't exist.\n" " --changed\n" " Only copy if changed (i.e. compare first).\n" " --disable-protection\n" " Will disable the protection file protection applied with -R.\n" " --enable-protection\n" " Will enable the protection file protection applied with -R.\n" " --enable-full-protection\n" " Will enable the protection file protection for all operations.\n" " --disable-full-protection\n" " Will disable the protection file protection for all operations.\n" " --protection-depth\n" " Number or path indicating the file protection depth. Default: %d\n" "\n" "Environment:\n" " KMK_CP_DISABLE_PROTECTION\n" " Same as --disable-protection. Overrides command line.\n" " KMK_CP_ENABLE_PROTECTION\n" " Same as --enable-protection. Overrides everyone else.\n" " KMK_CP_ENABLE_FULL_PROTECTION\n" " Same as --enable-full-protection. Overrides everyone else.\n" " KMK_CP_DISABLE_FULL_PROTECTION\n" " Same as --disable-full-protection. Overrides command line.\n" " KMK_CP_PROTECTION_DEPTH\n" " Same as --protection-depth. Overrides command line.\n" "\n" "The file protection of the top %d layers of the file hierarchy is there\n" "to try prevent makefiles from doing bad things to your system. This\n" "protection is not bulletproof, but should help prevent you from shooting\n" "yourself in the foot.\n" , pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth()); return 1; } kbuild-3686/src/kmk/kmkbuiltin/append.c0000664000175000017500000003455515053010074020060 0ustar locutuslocutus/* $Id: append.c 3246 2018-12-25 21:02:04Z bird $ */ /** @file * kMk Builtin command - append text to file. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #ifndef KMK_BUILTIN_STANDALONE # include "makeint.h" # include "filedef.h" # include "variable.h" #else # include "config.h" #endif #include #include #include #include #ifdef HAVE_UNISTD_H # include #endif #ifdef _MSC_VER # include #endif #ifdef HAVE_ALLOCA_H # include #endif #if !defined(KMK_BUILTIN_STANDALONE) && defined(KBUILD_OS_WINDOWS) && defined(CONFIG_NEW_WIN_CHILDREN) # include "../w32/winchildren.h" #endif #include "err.h" #include "kmkbuiltin.h" /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ #define STR_TUPLE(a_sz) a_sz, (sizeof(a_sz) - 1) /** No-inherit open flag. */ #ifdef _O_NOINHERIT # define MY_O_NOINHERIT _O_NOINHERIT #elif defined(O_NOINHERIT) # define MY_O_NOINHERIT O_NOINHERIT #elif defined(O_CLOEXEC) # define MY_O_NOINHERIT O_CLOEXEC #else # define MY_O_NOINHERIT 0 #endif /** Binary mode open flag. */ #ifdef _O_BINARY # define MY_O_BINARY _O_BINARY #elif defined(O_BINARY) # define MY_O_BINARY O_BINARY #else # define MY_O_BINARY 0 #endif /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ /** * Append output buffer. */ typedef struct KMKBUILTINAPPENDBUF { /** Buffer pointer. */ char *pszBuf; /** The buffer allocation size. */ size_t cbBuf; /** The current buffer offset. */ size_t offBuf; /** Set if we ran out of memory. */ int fOutOfMemory; } KMKBUILTINAPPENDBUF; /** * Appends a substring to the output buffer. * * @param pBuf The output buffer. * @param pch The substring pointer. * @param cch The substring length. */ static void write_to_buf(KMKBUILTINAPPENDBUF *pBuf, const char *pch, size_t cch) { size_t const offCur = pBuf->offBuf; size_t offNew = offCur + cch; if (offNew >= pBuf->cbBuf) { size_t cbNew = offNew + 1 + 256; void *pvNew; cbNew = (cbNew + 511) & ~(size_t)511; pvNew = realloc(pBuf->pszBuf, cbNew); if (pvNew) pBuf->pszBuf = (char *)pvNew; else { free(pBuf->pszBuf); pBuf->pszBuf = NULL; pBuf->cbBuf = 0; pBuf->offBuf = offNew; pBuf->fOutOfMemory = 1; return; } } memcpy(&pBuf->pszBuf[offCur], pch, cch); pBuf->pszBuf[offNew] = '\0'; pBuf->offBuf = offNew; } /** * Adds a string to the output buffer. * * @param pBuf The output buffer. * @param psz The string. */ static void string_to_buf(KMKBUILTINAPPENDBUF *pBuf, const char *psz) { write_to_buf(pBuf, psz, strlen(psz)); } /** * Prints the usage and return 1. */ static int kmk_builtin_append_usage(const char *arg0, FILE *pf) { fprintf(pf, "usage: %s [-dcnNtv] file [string ...]\n" " or: %s --version\n" " or: %s --help\n" "\n" "Options:\n" " -d Enclose the output in define ... endef, taking the name from\n" " the first argument following the file name.\n" " -c Output the command for specified target(s). [builtin only]\n" " -i look for --insert-command=trg and --insert-variable=var. [builtin only]\n" " -n Insert a newline between the strings.\n" " -N Suppress the trailing newline.\n" " -t Truncate the file instead of appending\n" " -v Output the value(s) for specified variable(s). [builtin only]\n" , arg0, arg0, arg0); return 1; } /** * Appends text to a textfile, creating the textfile if necessary. */ int kmk_builtin_append(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned) { #if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2) static const char s_szNewLine[] = "\r\n"; #else static const char s_szNewLine[] = "\n"; #endif KMKBUILTINAPPENDBUF OutBuf = { NULL, 0, 0, 0 }; const char *pszFilename; int rc = 88; int i; int fFirst; int fNewline = 0; int fNoTrailingNewline = 0; int fTruncate = 0; int fDefine = 0; int fVariables = 0; int fCommands = 0; #ifndef KMK_BUILTIN_STANDALONE int fLookForInserts = 0; #else (void)pChild; (void)pPidSpawned; #endif /* * Parse options. */ i = 1; while (i < argc && argv[i][0] == '-' && argv[i][1] != '\0' /* '-' is a file */ && strchr("-cdinNtv", argv[i][1]) /* valid option char */ ) { char *psz = &argv[i][1]; if (*psz != '-') { do { switch (*psz) { case 'c': if (fVariables) { errx(pCtx, 1, "Option '-c' clashes with '-v'."); return kmk_builtin_append_usage(argv[0], stderr); } #ifndef KMK_BUILTIN_STANDALONE fCommands = 1; break; #else errx(pCtx, 1, "Option '-c' isn't supported in external mode."); return kmk_builtin_append_usage(argv[0], stderr); #endif case 'd': if (fVariables) { errx(pCtx, 1, "Option '-d' must come before '-v'!"); return kmk_builtin_append_usage(argv[0], stderr); } fDefine = 1; break; case 'i': if (fVariables || fCommands) { errx(pCtx, 1, fVariables ? "Option '-i' clashes with '-v'." : "Option '-i' clashes with '-c'."); return kmk_builtin_append_usage(argv[0], stderr); } #ifndef KMK_BUILTIN_STANDALONE fLookForInserts = 1; break; #else errx(pCtx, 1, "Option '-C' isn't supported in external mode."); return kmk_builtin_append_usage(argv[0], stderr); #endif case 'n': fNewline = 1; break; case 'N': fNoTrailingNewline = 1; break; case 't': fTruncate = 1; break; case 'v': if (fCommands) { errx(pCtx, 1, "Option '-v' clashes with '-c'."); return kmk_builtin_append_usage(argv[0], stderr); } #ifndef KMK_BUILTIN_STANDALONE fVariables = 1; break; #else errx(pCtx, 1, "Option '-v' isn't supported in external mode."); return kmk_builtin_append_usage(argv[0], stderr); #endif default: errx(pCtx, 1, "Invalid option '%c'! (%s)", *psz, argv[i]); return kmk_builtin_append_usage(argv[0], stderr); } } while (*++psz); } else if (!strcmp(psz, "-help")) { kmk_builtin_append_usage(argv[0], stdout); return 0; } else if (!strcmp(psz, "-version")) return kbuild_version(argv[0]); else break; i++; } /* * Take down the filename. */ if (i + fDefine < argc) pszFilename = argv[i++]; else { if (i <= argc) errx(pCtx, 1, "missing filename!"); else errx(pCtx, 1, "missing define name!"); return kmk_builtin_append_usage(argv[0], stderr); } /* Start of no-return zone! */ /* * Start define? */ if (fDefine) { write_to_buf(&OutBuf, STR_TUPLE("define ")); string_to_buf(&OutBuf, argv[i]); write_to_buf(&OutBuf, STR_TUPLE(s_szNewLine)); i++; } /* * Append the argument strings to the file */ fFirst = 1; for (; i < argc; i++) { const char *psz = argv[i]; size_t cch = strlen(psz); if (!fFirst) { if (fNewline) write_to_buf(&OutBuf, STR_TUPLE(s_szNewLine)); else write_to_buf(&OutBuf, STR_TUPLE(" ")); } #ifndef KMK_BUILTIN_STANDALONE if (fCommands) { char *pszOldBuf; unsigned cchOldBuf; char *pchEnd; install_variable_buffer(&pszOldBuf, &cchOldBuf); pchEnd = func_commands(variable_buffer, &argv[i], "commands"); write_to_buf(&OutBuf, variable_buffer, pchEnd - variable_buffer); restore_variable_buffer(pszOldBuf, cchOldBuf); } else if (fVariables) { struct variable *pVar = lookup_variable(psz, cch); if (!pVar) continue; if ( !pVar->recursive || IS_VARIABLE_RECURSIVE_WITHOUT_DOLLAR(pVar)) write_to_buf(&OutBuf, pVar->value, pVar->value_length); else { char *pszExpanded = allocated_variable_expand(pVar->value); string_to_buf(&OutBuf, pszExpanded); free(pszExpanded); } } else if (fLookForInserts && strncmp(psz, "--insert-command=", 17) == 0) { char *pszOldBuf; unsigned cchOldBuf; char *pchEnd; install_variable_buffer(&pszOldBuf, &cchOldBuf); psz += 17; pchEnd = func_commands(variable_buffer, (char **)&psz, "commands"); write_to_buf(&OutBuf, variable_buffer, pchEnd - variable_buffer); restore_variable_buffer(pszOldBuf, cchOldBuf); } else if (fLookForInserts && strncmp(psz, "--insert-variable=", 18) == 0) { struct variable *pVar = lookup_variable(psz + 18, cch); if (!pVar) continue; if ( !pVar->recursive || IS_VARIABLE_RECURSIVE_WITHOUT_DOLLAR(pVar)) write_to_buf(&OutBuf, pVar->value, pVar->value_length); else { char *pszExpanded = allocated_variable_expand(pVar->value); string_to_buf(&OutBuf, pszExpanded); free(pszExpanded); } } else #endif write_to_buf(&OutBuf, psz, cch); fFirst = 0; } /* * End the define? */ if (fDefine) { if (fFirst) write_to_buf(&OutBuf, STR_TUPLE(s_szNewLine)); write_to_buf(&OutBuf, STR_TUPLE("endef")); } /* * Add final newline (unless supressed) and check for errors. */ if (!fNoTrailingNewline) write_to_buf(&OutBuf, STR_TUPLE(s_szNewLine)); /* * Write the buffer (unless we ran out of heap already). */ #if !defined(KMK_BUILTIN_STANDALONE) && defined(KBUILD_OS_WINDOWS) && defined(CONFIG_NEW_WIN_CHILDREN) if (!OutBuf.fOutOfMemory) { rc = MkWinChildCreateAppend(pszFilename, &OutBuf.pszBuf, OutBuf.offBuf, fTruncate, pChild, pPidSpawned); if (rc != 0) rc = errx(pCtx, rc, "MkWinChildCreateAppend failed: %u", rc); if (OutBuf.pszBuf) free(OutBuf.pszBuf); } else #endif if (!OutBuf.fOutOfMemory) { int fd = open(pszFilename, fTruncate ? O_WRONLY | O_TRUNC | O_CREAT | MY_O_NOINHERIT | MY_O_BINARY : O_WRONLY | O_APPEND | O_CREAT | MY_O_NOINHERIT | MY_O_BINARY, 0666); if (fd >= 0) { ssize_t cbWritten = write(fd, OutBuf.pszBuf, OutBuf.offBuf); if (cbWritten == (ssize_t)OutBuf.offBuf) rc = 0; else rc = err(pCtx, 1, "error writing %lu bytes to '%s'", (unsigned long)OutBuf.offBuf, pszFilename); if (close(fd) < 0) rc = err(pCtx, 1, "error closing '%s'", pszFilename); } else rc = err(pCtx, 1, "failed to open '%s'", pszFilename); free(OutBuf.pszBuf); } else rc = errx(pCtx, 1, "out of memory for output buffer! (%u needed)", OutBuf.offBuf + 1); return rc; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_append", NULL }; return kmk_builtin_append(argc, argv, envp, &Ctx, NULL, NULL); } #endif kbuild-3686/src/kmk/kmkbuiltin/osdep.c0000664000175000017500000000233015053010074017705 0ustar locutuslocutus/* $Id: osdep.c 2656 2012-09-10 20:39:16Z bird $ */ /** @file * Include all the OS dependent bits when bootstrapping. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ #include /** @todo replace this by proper configure.in tests. */ #if defined(_MSC_VER) # include "mscfakes.c" # include "fts.c" #elif defined(__sun__) # include "solfakes.c" # include "fts.c" #elif defined(__APPLE__) # include "darwin.c" #elif defined(__OpenBSD__) # include "openbsd.c" #elif defined(__HAIKU__) # include "haikufakes.c" #endif kbuild-3686/src/kmk/kmkbuiltin/mkdir.c0000664000175000017500000001735115053010075017713 0ustar locutuslocutus/* * Copyright (c) 1983, 1992, 1993 * 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. * 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 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1983, 1992, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)mkdir.c 8.2 (Berkeley) 1/25/94"; #endif /* not lint */ #include __FBSDID("$FreeBSD: src/bin/mkdir/mkdir.c,v 1.28 2004/04/06 20:06:48 markm Exp $"); #endif #define FAKES_NO_GETOPT_H /* bird */ #include "config.h" #include #include #include "err.h" #include #include #ifndef _MSC_VER # include #endif #include #include #include #ifndef __HAIKU__ # include #endif #include #ifdef HAVE_ALLOCA_H # include #endif #include "getopt_r.h" #ifdef __HAIKU__ # include "haikufakes.h" #endif #ifdef _MSC_VER # include # include "mscfakes.h" #endif #include "kmkbuiltin.h" static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; extern mode_t g_fUMask; extern void * bsd_setmode(const char *p); extern mode_t bsd_getmode(const void *bbox, mode_t omode); static int build(PKMKBUILTINCTX pCtx, char *, mode_t, int); static int usage(PKMKBUILTINCTX pCtx, int fIsErr); int kmk_builtin_mkdir(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { struct getopt_state_r gos; int ch, exitval, success, pflag, vflag; mode_t omode, *set = (mode_t *)NULL; char *mode; omode = pflag = vflag = 0; mode = NULL; getopt_initialize_r(&gos, argc, argv, "m:pv", long_options, envp, pCtx); while ((ch = getopt_long_r(&gos, NULL)) != -1) switch(ch) { case 'm': mode = gos.optarg; break; case 'p': pflag = 1; break; case 'v': vflag = 1; break; case 261: usage(pCtx, 0); return 0; case 262: return kbuild_version(argv[0]); case '?': default: return usage(pCtx, 1); } argc -= gos.optind; argv += gos.optind; if (argv[0] == NULL) return usage(pCtx, 1); if (mode == NULL) { omode = S_IRWXU | S_IRWXG | S_IRWXO; } else { if ((set = bsd_setmode(mode)) == NULL) return errx(pCtx, 1, "invalid file mode: %s", mode); omode = bsd_getmode(set, S_IRWXU | S_IRWXG | S_IRWXO); free(set); } for (exitval = 0; *argv != NULL; ++argv) { success = 1; if (pflag) { if (build(pCtx, *argv, omode, vflag)) success = 0; } else if (mkdir(*argv, omode) < 0) { if (errno == ENOTDIR || errno == ENOENT) warn(pCtx, "mkdir: %s", dirname(*argv)); else warn(pCtx, "mkdir: %s", *argv); success = 0; } else if (vflag) kmk_builtin_ctx_printf(pCtx, 0, "%s\n", *argv); if (!success) exitval = 1; /* * The mkdir() and umask() calls both honor only the low * nine bits, so if you try to set a mode including the * sticky, setuid, setgid bits you lose them. Don't do * this unless the user has specifically requested a mode, * as chmod will (obviously) ignore the umask. */ if (success && mode != NULL && chmod(*argv, omode) == -1) { warn(pCtx, "chmod: %s", *argv); exitval = 1; } } return exitval; } #ifdef KMK_BUILTIN_STANDALONE mode_t g_fUMask; int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_mkdir", NULL }; umask(g_fUMask = umask(0077)); return kmk_builtin_mkdir(argc, argv, envp, &Ctx); } #endif static int build(PKMKBUILTINCTX pCtx, char *path, mode_t omode, int vflag) { struct stat sb; mode_t numask, oumask; int first, last, retval; char *p; const size_t len = strlen(path); p = alloca(len + 1); path = memcpy(p, path, len + 1); #if defined(_MSC_VER) || defined(__EMX__) /* correct slashes. */ p = strchr(path, '\\'); while (p) { *p++ = '/'; p = strchr(p, '\\'); } #endif p = path; oumask = 0; retval = 0; #if defined(_MSC_VER) || defined(__EMX__) if ( ( (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z')) && p[1] == ':') p += 2; /* skip the drive letter */ else if ( p[0] == '/' && p[1] == '/' && p[2] != '/') { /* UNC */ p += 2; while (*p && *p != '/') /* server */ p++; while (*p == '/') p++; while (*p && *p != '/') /* share */ p++; } #endif if (p[0] == '/') /* Skip leading '/'. */ ++p; for (first = 1, last = 0; !last ; ++p) { if (p[0] == '\0') last = 1; else if (p[0] != '/') continue; *p = '\0'; if (!last && p[1] == '\0') last = 1; if (first) { /* * POSIX 1003.2: * For each dir operand that does not name an existing * directory, effects equivalent to those cased by the * following command shall occcur: * * mkdir -p -m $(umask -S),u+wx $(dirname dir) && * mkdir [-m mode] dir * * We change the user's umask and then restore it, * instead of doing chmod's. */ #ifdef KMK_BUILTIN_STANDALONE oumask = umask(0077); #else oumask = g_fUMask; assert(oumask == umask(g_fUMask)); #endif numask = oumask & ~(S_IWUSR | S_IXUSR); if (numask != oumask) (void)umask(numask); first = 0; } if (last && oumask != numask) (void)umask(oumask); if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0) { if (errno == EEXIST || errno == EISDIR || errno == ENOSYS /* (solaris crap) */ || errno == EACCES /* (ditto) */) { if (stat(path, &sb) < 0) { warn(pCtx, "stat: %s", path); retval = 1; break; } if (!S_ISDIR(sb.st_mode)) { if (last) errno = EEXIST; else errno = ENOTDIR; warn(pCtx, "st_mode: %s", path); retval = 1; break; } } else { warn(pCtx, "mkdir: %s", path); retval = 1; break; } } else if (vflag) kmk_builtin_ctx_printf(pCtx, 0, "%s\n", path); if (!last) *p = '/'; } if (!first && !last && oumask != numask) (void)umask(oumask); return (retval); } static int usage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s [-pv] [-m mode] directory ...\n" " or: %s --help\n" " or: %s --version\n", pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); return EX_USAGE; } kbuild-3686/src/kmk/kmkbuiltin/strlcpy.c0000664000175000017500000000525315053010074020302 0ustar locutuslocutus/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * 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. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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) && !defined(lint) static char *rcsid = "$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $"); #include //__FBSDID("$FreeBSD: src/lib/libc/string/strlcpy.c,v 1.7 2003/05/01 19:03:14 nectar Exp $"); #endif /* LIBC_SCCS and not lint */ #include #include /* This trick is for bootstrap.gmk. */ #if defined(__DARWIN_C_LEVEL) && defined(__DARWIN_C_FULL) # define SKIP_STRLCPY #endif #ifndef SKIP_STRLCPY /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(dst, src, siz) char *dst; const char *src; size_t siz; { char *d = dst; const char *s = src; size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } #endif /* !SKIP_STRLCPY */ kbuild-3686/src/kmk/kmkbuiltin/ln.c0000664000175000017500000001743715053010074017222 0ustar locutuslocutus/*- * Copyright (c) 1987, 1993, 1994 * 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. * 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 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1987, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)ln.c 8.2 (Berkeley) 3/31/94"; #endif /* not lint */ #include __FBSDID("$FreeBSD: src/bin/ln/ln.c,v 1.33 2005/02/09 17:37:37 ru Exp $"); #endif /* no $id */ #define FAKES_NO_GETOPT_H /* bird */ #include "config.h" #ifndef _MSC_VER # include #endif #include #include "err.h" #include #include #include #include #include #include #include "getopt_r.h" #ifdef _MSC_VER # include "mscfakes.h" #endif #include "kmkbuiltin.h" /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ typedef struct LNINSTANCE { PKMKBUILTINCTX pCtx; int fflag; /* Unlink existing files. */ int hflag; /* Check new name for symlink first. */ int iflag; /* Interactive mode. */ int sflag; /* Symbolic, not hard, link. */ int vflag; /* Verbose output. */ int (*linkf)(const char *, const char *); /* System link call. */ char linkch; } LNINSTANCE; typedef LNINSTANCE *PLNINSTANCE; static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; static int linkit(PLNINSTANCE,const char *, const char *, int); static int usage(PKMKBUILTINCTX, int); int kmk_builtin_ln(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { LNINSTANCE This; struct getopt_state_r gos; struct stat sb; char *sourcedir; int ch, exitval; /* initialize globals. */ This.pCtx = pCtx; This.fflag = 0; This.hflag = 0; This.iflag = 0; This.sflag = 0; This.vflag = 0; This.linkch = 0; This.linkf = NULL; getopt_initialize_r(&gos, argc, argv, "fhinsv", long_options, envp, pCtx); while ((ch = getopt_long_r(&gos, NULL)) != -1) switch (ch) { case 'f': This.fflag = 1; This.iflag = 0; break; case 'h': case 'n': This.hflag = 1; break; case 'i': This.iflag = 1; This.fflag = 0; break; case 's': This.sflag = 1; break; case 'v': This.vflag = 1; break; case 261: usage(pCtx, 0); return 0; case 262: return kbuild_version(argv[0]); case '?': default: return usage(pCtx, 1); } argv += gos.optind; argc -= gos.optind; This.linkf = This.sflag ? symlink : link; This.linkch = This.sflag ? '-' : '='; switch(argc) { case 0: return usage(pCtx, 1); /* NOTREACHED */ case 1: /* ln target */ return linkit(&This, argv[0], ".", 1); case 2: /* ln target source */ return linkit(&This, argv[0], argv[1], 0); default: ; } /* ln target1 target2 directory */ sourcedir = argv[argc - 1]; if (This.hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) { /* * We were asked not to follow symlinks, but found one at * the target--simulate "not a directory" error */ errno = ENOTDIR; return err(pCtx, 1, "st_mode: %s", sourcedir); } if (stat(sourcedir, &sb)) return err(pCtx, 1, "stat: %s", sourcedir); if (!S_ISDIR(sb.st_mode)) return usage(pCtx, 1); for (exitval = 0; *argv != sourcedir; ++argv) exitval |= linkit(&This, *argv, sourcedir, 1); return exitval; } static int linkit(PLNINSTANCE pThis, const char *target, const char *source, int isdir) { struct stat sb; const char *p; int ch, exists, first; char path[PATH_MAX]; if (!pThis->sflag) { /* If target doesn't exist, quit now. */ if (stat(target, &sb)) { warn(pThis->pCtx, "stat: %s", target); return (1); } /* Only symbolic links to directories. */ if (S_ISDIR(sb.st_mode)) { errno = EISDIR; warn(pThis->pCtx, "st_mode: %s", target); return (1); } } /* * If the source is a directory (and not a symlink if hflag), * append the target's name. */ if (isdir || (lstat(source, &sb) == 0 && S_ISDIR(sb.st_mode)) || (!pThis->hflag && stat(source, &sb) == 0 && S_ISDIR(sb.st_mode))) { #if defined(_MSC_VER) || defined(__OS2__) char *p2 = strrchr(target, '\\'); p = strrchr(target, '/'); if (p2 != NULL && (p == NULL || p2 > p)) p = p2; if (p == NULL) #else if ((p = strrchr(target, '/')) == NULL) #endif p = target; else ++p; if (snprintf(path, sizeof(path), "%s/%s", source, p) >= (ssize_t)sizeof(path)) { errno = ENAMETOOLONG; warn(pThis->pCtx, "snprintf: %s", target); return (1); } source = path; } exists = !lstat(source, &sb); /* * If the file exists, then unlink it forcibly if -f was specified * and interactively if -i was specified. */ if (pThis->fflag && exists) { if (unlink(source)) { warn(pThis->pCtx, "unlink: %s", source); return (1); } } else if (pThis->iflag && exists) { fflush(stdout); fprintf(stderr, "replace %s? ", source); first = ch = getchar(); while(ch != '\n' && ch != EOF) ch = getchar(); if (first != 'y' && first != 'Y') { kmk_builtin_ctx_printf(pThis->pCtx, 1, "not replaced\n"); return (1); } if (unlink(source)) { warn(pThis->pCtx, "unlink: %s", source); return (1); } } /* Attempt the link. */ if ((*pThis->linkf)(target, source)) { warn(pThis->pCtx, "%s: %s", pThis->linkf == link ? "link" : "symlink", source); return (1); } if (pThis->vflag) kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s %c> %s\n", source, pThis->linkch, target); return (0); } static int usage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx,fIsErr, "usage: %s [-fhinsv] source_file [target_file]\n" " or: %s [-fhinsv] source_file ... target_dir\n" " or: %s source_file target_file\n" " or: %s --help\n" " or: %s --version\n", pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); return 1; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_ln", NULL }; return kmk_builtin_ln(argc, argv, envp, &Ctx); } #endif kbuild-3686/src/kmk/kmkbuiltin/mscfakes.c0000664000175000017500000005600215053010075020375 0ustar locutuslocutus/* $Id: mscfakes.c 3682 2025-08-12 23:34:19Z bird $ */ /** @file * Fake Unix stuff for MSC. */ /* * Copyright (c) 2005-2015 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "err.h" #include "mscfakes.h" #include "nt/ntutimes.h" #undef utimes #undef lutimes #include "nt/ntmkdirat.h" #undef mkdir #undef mkdirat #include "console.h" /******************************************************************************* * Internal Functions * *******************************************************************************/ static BOOL isPipeFd(int fd); /** * Makes corrections to a directory path that ends with a trailing slash. * * @returns temporary buffer to free. * @param ppszPath The path pointer. This is updated when necessary. * @param pfMustBeDir This is set if it must be a directory, otherwise it's cleared. */ static char * msc_fix_path(const char **ppszPath, int *pfMustBeDir) { const char *pszPath = *ppszPath; const char *psz; char *pszNew; *pfMustBeDir = 0; /* * Skip any compusory trailing slashes */ if (pszPath[0] == '/' || pszPath[0] == '\\') { if ( (pszPath[1] == '/' || pszPath[1] == '\\') && pszPath[2] != '/' && pszPath[2] != '\\') /* unc */ pszPath += 2; else /* root slash(es) */ pszPath++; } else if ( isalpha(pszPath[0]) && pszPath[1] == ':') { if (pszPath[2] == '/' || pszPath[2] == '\\') /* drive w/ slash */ pszPath += 3; else /* drive relative path. */ pszPath += 2; } /* else: relative path, no skipping necessary. */ /* * Any trailing slashes to drop off? */ psz = strchr(pszPath, '\0'); if (pszPath <= psz) return NULL; if ( psz[-1] != '/' || psz[-1] != '\\') return NULL; /* figure how many, make a copy and strip them off. */ while ( psz > pszPath && ( psz[-1] == '/' || psz[-1] == '\\')) psz--; pszNew = strdup(pszPath); pszNew[psz - pszPath] = '\0'; *pfMustBeDir = 1; *ppszPath = pszNew; /* use this one */ return pszNew; } int birdSetErrno(unsigned dwErr) { switch (dwErr) { default: case ERROR_INVALID_FUNCTION: errno = EINVAL; break; case ERROR_FILE_NOT_FOUND: errno = ENOENT; break; case ERROR_PATH_NOT_FOUND: errno = ENOENT; break; case ERROR_TOO_MANY_OPEN_FILES: errno = EMFILE; break; case ERROR_ACCESS_DENIED: errno = EACCES; break; case ERROR_INVALID_HANDLE: errno = EBADF; break; case ERROR_ARENA_TRASHED: errno = ENOMEM; break; case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; case ERROR_INVALID_BLOCK: errno = ENOMEM; break; case ERROR_BAD_ENVIRONMENT: errno = E2BIG; break; case ERROR_BAD_FORMAT: errno = ENOEXEC; break; case ERROR_INVALID_ACCESS: errno = EINVAL; break; case ERROR_INVALID_DATA: errno = EINVAL; break; case ERROR_INVALID_DRIVE: errno = ENOENT; break; case ERROR_CURRENT_DIRECTORY: errno = EACCES; break; case ERROR_NOT_SAME_DEVICE: errno = EXDEV; break; case ERROR_NO_MORE_FILES: errno = ENOENT; break; case ERROR_LOCK_VIOLATION: errno = EACCES; break; case ERROR_BAD_NETPATH: errno = ENOENT; break; case ERROR_NETWORK_ACCESS_DENIED: errno = EACCES; break; case ERROR_BAD_NET_NAME: errno = ENOENT; break; case ERROR_FILE_EXISTS: errno = EEXIST; break; case ERROR_CANNOT_MAKE: errno = EACCES; break; case ERROR_FAIL_I24: errno = EACCES; break; case ERROR_INVALID_PARAMETER: errno = EINVAL; break; case ERROR_NO_PROC_SLOTS: errno = EAGAIN; break; case ERROR_DRIVE_LOCKED: errno = EACCES; break; case ERROR_BROKEN_PIPE: errno = EPIPE; break; case ERROR_DISK_FULL: errno = ENOSPC; break; case ERROR_INVALID_TARGET_HANDLE: errno = EBADF; break; case ERROR_WAIT_NO_CHILDREN: errno = ECHILD; break; case ERROR_CHILD_NOT_COMPLETE: errno = ECHILD; break; case ERROR_DIRECT_ACCESS_HANDLE: errno = EBADF; break; case ERROR_NEGATIVE_SEEK: errno = EINVAL; break; case ERROR_SEEK_ON_DEVICE: errno = EACCES; break; case ERROR_DIR_NOT_EMPTY: errno = ENOTEMPTY; break; case ERROR_NOT_LOCKED: errno = EACCES; break; case ERROR_BAD_PATHNAME: errno = ENOENT; break; case ERROR_MAX_THRDS_REACHED: errno = EAGAIN; break; case ERROR_LOCK_FAILED: errno = EACCES; break; case ERROR_ALREADY_EXISTS: errno = EEXIST; break; case ERROR_FILENAME_EXCED_RANGE: errno = ENOENT; break; case ERROR_NESTING_NOT_ALLOWED: errno = EAGAIN; break; #ifdef EMLINK case ERROR_TOO_MANY_LINKS: errno = EMLINK; break; #endif } return -1; } char *dirname(char *path) { /** @todo later */ return path; } int lchmod(const char *pszPath, mode_t mode) { int rc = 0; int fMustBeDir; char *pszPathFree = msc_fix_path(&pszPath, &fMustBeDir); /* * Get the current attributes */ DWORD fAttr = GetFileAttributes(pszPath); if (fAttr == INVALID_FILE_ATTRIBUTES) rc = birdSetErrno(GetLastError()); else if (fMustBeDir & !(fAttr & FILE_ATTRIBUTE_DIRECTORY)) { errno = ENOTDIR; rc = -1; } else { /* * Modify the attributes and try set them. */ if (mode & _S_IWRITE) { fAttr &= ~FILE_ATTRIBUTE_READONLY; if (fAttr == 0) fAttr = FILE_ATTRIBUTE_NORMAL; } else { fAttr &= ~FILE_ATTRIBUTE_NORMAL; fAttr |= FILE_ATTRIBUTE_READONLY; } if (!SetFileAttributes(pszPath, fAttr)) rc = birdSetErrno(GetLastError()); } if (pszPathFree) { int saved_errno = errno; free(pszPathFree); errno = saved_errno; } return rc; } int msc_chmod(const char *pszPath, mode_t mode) { int rc = 0; int fMustBeDir; char *pszPathFree = msc_fix_path(&pszPath, &fMustBeDir); /* * Get the current attributes. */ DWORD fAttr = GetFileAttributes(pszPath); if (fAttr == INVALID_FILE_ATTRIBUTES) rc = birdSetErrno(GetLastError()); else if (fMustBeDir & !(fAttr & FILE_ATTRIBUTE_DIRECTORY)) { errno = ENOTDIR; rc = -1; } else if (fAttr & FILE_ATTRIBUTE_REPARSE_POINT) { errno = ENOSYS; /** @todo resolve symbolic link / rewrite to NtSetInformationFile. */ rc = -1; } else { /* * Modify the attributes and try set them. */ if (mode & _S_IWRITE) { fAttr &= ~FILE_ATTRIBUTE_READONLY; if (fAttr == 0) fAttr = FILE_ATTRIBUTE_NORMAL; } else { fAttr &= ~FILE_ATTRIBUTE_NORMAL; fAttr |= FILE_ATTRIBUTE_READONLY; } if (!SetFileAttributes(pszPath, fAttr)) rc = birdSetErrno(GetLastError()); } if (pszPathFree) { int saved_errno = errno; free(pszPathFree); errno = saved_errno; } return rc; } typedef BOOL (WINAPI *PFNCREATEHARDLINKA)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES); int link(const char *pszDst, const char *pszLink) { static PFNCREATEHARDLINKA s_pfnCreateHardLinkA = NULL; static int s_fTried = FALSE; /* The API was introduced in Windows 2000, so resolve it dynamically. */ if (!s_pfnCreateHardLinkA) { if (!s_fTried) { HMODULE hmod = LoadLibrary("KERNEL32.DLL"); if (hmod) *(FARPROC *)&s_pfnCreateHardLinkA = GetProcAddress(hmod, "CreateHardLinkA"); s_fTried = TRUE; } if (!s_pfnCreateHardLinkA) { errno = ENOSYS; return -1; } } if (s_pfnCreateHardLinkA(pszLink, pszDst, NULL)) return 0; return birdSetErrno(GetLastError()); } int mkdir_msc(const char *path, mode_t mode) { #if 0 int rc = (mkdir)(path); if (rc) { size_t len = strlen(path); if (len > 0 && (path[len - 1] == '/' || path[len - 1] == '\\')) { char *str = strdup(path); while (len > 0 && (str[len - 1] == '/' || str[len - 1] == '\\')) str[--len] = '\0'; rc = (mkdir)(str); free(str); } } return rc; #else return birdMkDir(path, mode); #endif } int rmdir_msc(const char *path) { int rc = (rmdir)(path); if (rc) { size_t len = strlen(path); if (len > 0 && (path[len - 1] == '/' || path[len - 1] == '\\')) { char *str = strdup(path); while (len > 0 && (str[len - 1] == '/' || str[len - 1] == '\\')) str[--len] = '\0'; rc = (rmdir)(str); free(str); } } return rc; } static int doname(char *pszX, char *pszEnd) { static char s_szChars[] = "Xabcdefghijklmnopqrstuwvxyz1234567890"; int rc = 0; do { char ch; pszEnd++; ch = *(strchr(s_szChars, *pszEnd) + 1); if (ch) { *pszEnd = ch; return 0; } *pszEnd = 'a'; } while (pszEnd != pszX); return 1; } int mkstemp(char *temp) { char *pszX = strchr(temp, 'X'); char *pszEnd = strchr(pszX, '\0'); int cTries = 1000; while (--cTries > 0) { int fd; if (doname(pszX, pszEnd)) return -1; fd = open(temp, _O_EXCL | _O_CREAT | _O_BINARY | _O_RDWR | KMK_OPEN_NO_INHERIT, 0777); if (fd >= 0) return fd; } return -1; } /** Unix to DOS. */ static char *fix_slashes(char *psz) { char *pszRet = psz; for (; *psz; psz++) if (*psz == '/') *psz = '\\'; return pszRet; } /** Calcs the SYMBOLIC_LINK_FLAG_DIRECTORY flag for CreatesymbolcLink. */ static DWORD is_directory(const char *pszPath, const char *pszRelativeTo) { size_t cchPath = strlen(pszPath); struct stat st; if (cchPath > 0 && pszPath[cchPath - 1] == '\\' || pszPath[cchPath - 1] == '/') return 1; /* SYMBOLIC_LINK_FLAG_DIRECTORY */ if (stat(pszPath, &st)) { size_t cchRelativeTo = strlen(pszRelativeTo); char *psz = malloc(cchPath + cchRelativeTo + 4); memcpy(psz, pszRelativeTo, cchRelativeTo); memcpy(psz + cchRelativeTo, "\\", 1); memcpy(psz + cchRelativeTo + 1, pszPath, cchPath + 1); if (stat(pszPath, &st)) st.st_mode = _S_IFREG; free(psz); } return (st.st_mode & _S_IFMT) == _S_IFDIR ? 1 : 0; } int symlink(const char *pszDst, const char *pszLink) { static BOOLEAN (WINAPI *s_pfnCreateSymbolicLinkA)(LPCSTR, LPCSTR, DWORD) = 0; static BOOL s_fTried = FALSE; if (!s_fTried) { HMODULE hmod = LoadLibrary("KERNEL32.DLL"); if (hmod) *(FARPROC *)&s_pfnCreateSymbolicLinkA = GetProcAddress(hmod, "CreateSymbolicLinkA"); s_fTried = TRUE; } if (s_pfnCreateSymbolicLinkA) { char *pszDstCopy = fix_slashes(strdup(pszDst)); char *pszLinkCopy = fix_slashes(strdup(pszLink)); BOOLEAN fRc = s_pfnCreateSymbolicLinkA(pszLinkCopy, pszDstCopy, is_directory(pszDstCopy, pszLinkCopy)); DWORD err = GetLastError(); free(pszDstCopy); free(pszLinkCopy); if (fRc) return 0; switch (err) { case ERROR_NOT_SUPPORTED: errno = ENOSYS; break; case ERROR_ALREADY_EXISTS: case ERROR_FILE_EXISTS: errno = EEXIST; break; case ERROR_DIRECTORY: errno = ENOTDIR; break; case ERROR_ACCESS_DENIED: case ERROR_PRIVILEGE_NOT_HELD: errno = EPERM; break; default: errno = EINVAL; break; } return -1; } fprintf(stderr, "warning: symlink() is available on this version of Windows!\n"); errno = ENOSYS; return -1; } #if _MSC_VER < 1400 int snprintf(char *buf, size_t size, const char *fmt, ...) { int cch; va_list args; va_start(args, fmt); cch = vsprintf(buf, fmt, args); va_end(args); return cch; } #endif /* We override the libc write function (in our modules only, unfortunately) so we can kludge our way around a ENOSPC problem observed on build servers capturing STDOUT and STDERR via pipes. Apparently this may happen when the pipe buffer is full, even with the mscfake_init hack in place. XXX: Probably need to hook into fwrite as well. */ ssize_t msc_write(int fd, const void *pvSrc, size_t cbSrc) { #define MSC_WRITE_MAX_CHUNK (UINT_MAX / 32) ssize_t cbRet; if (cbSrc <= MSC_WRITE_MAX_CHUNK) { /* Console output optimization: */ if (cbSrc > 0 && is_console(fd)) return maybe_con_write(fd, pvSrc, cbSrc); #ifndef MSC_WRITE_TEST cbRet = _write(fd, pvSrc, (unsigned int)cbSrc); #else cbRet = -1; errno = ENOSPC; #endif if (cbRet < 0) { /* ENOSPC on pipe kludge. */ unsigned int cbLimit; int cSinceLastSuccess; if (cbSrc == 0) return 0; if (errno != ENOSPC) return -1; #ifndef MSC_WRITE_TEST if (!isPipeFd(fd)) { errno = ENOSPC; return -1; } #endif /* Likely a full pipe buffer, try write smaller amounts and do some sleeping inbetween each unsuccessful one. */ cbLimit = (unsigned)(cbSrc / 4); if (cbLimit < 4) cbLimit = 4; else if (cbLimit > 512) cbLimit = 512; cSinceLastSuccess = 0; cbRet = 0; #ifdef MSC_WRITE_TEST cbLimit = 4; #endif while ((ssize_t)cbSrc > 0) { unsigned int cbAttempt = cbSrc > cbLimit ? cbLimit : (unsigned int)cbSrc; ssize_t cbActual = _write(fd, pvSrc, cbAttempt); if (cbActual > 0) { /* For some reason, it seems like we cannot trust _write to return a number that's less or equal to the number of bytes we passed in to the call. (Also reason for signed check in loop.) */ if (cbActual > cbAttempt) cbActual = cbAttempt; pvSrc = (char *)pvSrc + cbActual; cbSrc -= cbActual; cbRet += cbActual; #ifndef MSC_WRITE_TEST if (cbLimit < 32) cbLimit = 32; #endif cSinceLastSuccess = 0; } else if (errno != ENOSPC) return -1; else { /* Delay for about 30 seconds, then just give up. */ cSinceLastSuccess++; if (cSinceLastSuccess > 1860) return -1; if (cSinceLastSuccess <= 2) Sleep(0); else if (cSinceLastSuccess <= 66) { if (cbLimit >= 8) cbLimit /= 2; /* Just in case the pipe buffer is very very small. */ Sleep(1); } else Sleep(16); } } } } else { /* * Type limit exceeded. Split the job up. */ cbRet = 0; while (cbSrc > 0) { size_t cbToWrite = cbSrc > MSC_WRITE_MAX_CHUNK ? MSC_WRITE_MAX_CHUNK : cbSrc; ssize_t cbWritten = msc_write(fd, pvSrc, cbToWrite); if (cbWritten > 0) { pvSrc = (char *)pvSrc + (size_t)cbWritten; cbSrc -= (size_t)cbWritten; cbRet += (size_t)cbWritten; } else if (cbWritten == 0 || cbRet > 0) break; else return -1; } } return cbRet; } ssize_t writev(int fd, const struct iovec *vector, int count) { ssize_t size = 0; if (count > 0) { int i; /* To get consistent console output, we must try combine the segments when outputing to the console. */ if (count > 1 && is_console(fd)) { char *pbTmp; ssize_t cbTotal; if (count == 1) return maybe_con_write(fd, vector[0].iov_base, (int)vector[0].iov_len); cbTotal = 0; for (i = 0; i < count; i++) cbTotal += vector[i].iov_len; pbTmp = malloc(cbTotal); if (pbTmp) { char *pbCur = pbTmp; for (i = 0; i < count; i++) { memcpy(pbCur, vector[i].iov_base, vector[i].iov_len); pbCur += vector[i].iov_len; } size = maybe_con_write(fd, pbTmp, cbTotal); free(pbTmp); return size; } /* fall back on segment by segment output. */ } for (i = 0; i < count; i++) { int cb = msc_write(fd, vector[i].iov_base, (int)vector[i].iov_len); if (cb < 0) return cb; size += cb; } } return size; } intmax_t strtoimax(const char *nptr, char **endptr, int base) { if (*nptr != '-') return _strtoui64(nptr, endptr, base); return -(intmax_t)_strtoui64(nptr + 1, endptr, base); } uintmax_t strtoumax(const char *nptr, char **endptr, int base) { return _strtoui64(nptr, endptr, base); } int asprintf(char **strp, const char *fmt, ...) { int rc; va_list va; va_start(va, fmt); rc = vasprintf(strp, fmt, va); va_end(va); return rc; } int vasprintf(char **strp, const char *fmt, va_list va) { int rc; char *psz; size_t cb = 1024; *strp = NULL; for (;;) { va_list va2; psz = malloc(cb); if (!psz) return -1; #ifdef va_copy va_copy(va2, va); rc = vsnprintf(psz, cb, fmt, va2); va_end(va2); #else va2 = va; rc = vsnprintf(psz, cb, fmt, va2); #endif if (rc < 0 || (size_t)rc < cb) break; cb *= 2; free(psz); } *strp = psz; return rc; } int utimes(const char *pszPath, const struct msc_timeval *paTimes) { if (paTimes) { BirdTimeVal_T aTimes[2]; aTimes[0].tv_sec = paTimes[0].tv_sec; aTimes[0].tv_usec = paTimes[0].tv_usec; aTimes[1].tv_sec = paTimes[1].tv_sec; aTimes[1].tv_usec = paTimes[1].tv_usec; return birdUtimes(pszPath, aTimes); } return birdUtimes(pszPath, NULL); } int lutimes(const char *pszPath, const struct msc_timeval *paTimes) { if (paTimes) { BirdTimeVal_T aTimes[2]; aTimes[0].tv_sec = paTimes[0].tv_sec; aTimes[0].tv_usec = paTimes[0].tv_usec; aTimes[1].tv_sec = paTimes[1].tv_sec; aTimes[1].tv_usec = paTimes[1].tv_usec; return birdUtimes(pszPath, aTimes); } return birdUtimes(pszPath, NULL); } int gettimeofday(struct msc_timeval *pNow, void *pvIgnored) { struct __timeb64 Now; int rc = _ftime64_s(&Now); if (rc == 0) { pNow->tv_sec = Now.time; pNow->tv_usec = Now.millitm * 1000; return 0; } errno = rc; return -1; } struct tm *localtime_r(const __time64_t *pNow, struct tm *pResult) { int rc = _localtime64_s(pResult, pNow); if (rc == 0) return pResult; errno = rc; return NULL; } __time64_t timegm(struct tm *pNow) { return _mkgmtime64(pNow); } /** * Checks if the given file descriptor is a pipe or not. * * @returns TRUE if pipe, FALSE if not. * @param fd The libc file descriptor number. */ static BOOL isPipeFd(int fd) { /* Is pipe? */ HANDLE hFile = (HANDLE)_get_osfhandle(fd); if (hFile != INVALID_HANDLE_VALUE) { DWORD fType = GetFileType(hFile); fType &= ~FILE_TYPE_REMOTE; if (fType == FILE_TYPE_PIPE) return TRUE; } return FALSE; } /** * This is a kludge to make pipe handles blocking. * * @returns TRUE if it's now blocking, FALSE if not a pipe or we failed to fix * the blocking mode. * @param fd The libc file descriptor number. */ static BOOL makePipeBlocking(int fd) { if (isPipeFd(fd)) { /* Try fix it. */ HANDLE hFile = (HANDLE)_get_osfhandle(fd); DWORD fState = 0; if (GetNamedPipeHandleState(hFile, &fState, NULL, NULL, NULL, NULL, 0)) { fState &= ~PIPE_NOWAIT; fState |= PIPE_WAIT; if (SetNamedPipeHandleState(hFile, &fState, NULL, NULL)) return TRUE; } } return FALSE; } /** * Initializes the msc fake stuff. * @returns 0 on success (non-zero would indicate failure, see rterr.h). */ int mscfake_init(void) { /* * Kludge against _write returning ENOSPC on non-blocking pipes. */ makePipeBlocking(STDOUT_FILENO); makePipeBlocking(STDERR_FILENO); return 0; } /* * Do this before main is called. */ #pragma section(".CRT$XIA", read) #pragma section(".CRT$XIU", read) #pragma section(".CRT$XIZ", read) typedef int (__cdecl *PFNCRTINIT)(void); static __declspec(allocate(".CRT$XIU")) PFNCRTINIT g_MscFakeInitVectorEntry = mscfake_init; kbuild-3686/src/kmk/kmkbuiltin/cmp_extern.h0000664000175000017500000000525215053010074020752 0ustar locutuslocutus/* $NetBSD: extern.h,v 1.7 2007/08/21 14:09:53 christos Exp $ */ /*- * Copyright (c) 1991, 1993, 1994 * 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. 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. * * @(#)extern.h 8.3 (Berkeley) 4/2/94 */ #define OK_EXIT 0 #define DIFF_EXIT 1 #define ERR_EXIT 2 /* error exit code */ int cmp_file_and_file(PKMKBUILTINCTX pCtx, const char *file1, const char *file2, int sflag, int lflag, int special); int cmp_file_and_file_ex(PKMKBUILTINCTX pCtx, const char *file1, off_t skip1, const char *file2, off_t skip2, int sflag, int lflag, int special); int cmp_fd_and_file(PKMKBUILTINCTX pCtx, int fd1, const char *file1, const char *file2, int sflag, int lflag, int special); int cmp_fd_and_file_ex(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, const char *file2, off_t skip2, int sflag, int lflag, int special); int cmp_fd_and_fd(PKMKBUILTINCTX pCtx, int fd1, const char *file1, int fd2, const char *file2, int sflag, int lflag, int special); int cmp_fd_and_fd_ex(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, int fd2, const char *file2, off_t skip2, int sflag, int lflag, int special); kbuild-3686/src/kmk/kmkbuiltin/chmod.c0000664000175000017500000002106215053010074017670 0ustar locutuslocutus/*- * Copyright (c) 1989, 1993, 1994 * 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. * 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 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1989, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)chmod.c 8.8 (Berkeley) 4/1/94"; #endif /* not lint */ #endif /*#include */ /*__FBSDID("$FreeBSD: src/bin/chmod/chmod.c,v 1.33 2005/01/10 08:39:20 imp Exp $");*/ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #define FAKES_NO_GETOPT_H /* bird */ #include "config.h" #include #include #include "err.h" #include #include "fts.h" #include #include #include #include #ifndef _MSC_VER # include #else # include "mscfakes.h" #endif #ifdef __sun__ # include "solfakes.h" #endif #ifdef __HAIKU__ # include "haikufakes.h" #endif #include "getopt_r.h" #include "kmkbuiltin.h" /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; /********************************************************************************************************************************* * Internal Functions * *********************************************************************************************************************************/ extern void * bsd_setmode(const char *p); extern mode_t bsd_getmode(const void *bbox, mode_t omode); extern void bsd_strmode(mode_t mode, char *p); #if (defined(__APPLE__) && !defined(_DARWIN_FEATURE_UNIX_CONFORMANCE)) || defined(__OpenBSD__) extern int lchmod(const char *, mode_t); #endif static int usage(PKMKBUILTINCTX pCtx, int is_err); int kmk_builtin_chmod(int argc, char *argv[], char **envp, PKMKBUILTINCTX pCtx) { struct getopt_state_r gos; FTS *ftsp; FTSENT *p; mode_t *set; int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval; int vflag; char *mode; mode_t newmode; int (*change_mode)(const char *, mode_t); set = NULL; Hflag = Lflag = Rflag = fflag = hflag = vflag = 0; getopt_initialize_r(&gos, argc, argv, "HLPRXfghorstuvwx", long_options, envp, pCtx); while ((ch = getopt_long_r(&gos, NULL)) != -1) switch (ch) { case 'H': Hflag = 1; Lflag = 0; break; case 'L': Lflag = 1; Hflag = 0; break; case 'P': Hflag = Lflag = 0; break; case 'R': Rflag = 1; break; case 'f': fflag = 1; break; case 'h': /* * In System V (and probably POSIX.2) the -h option * causes chmod to change the mode of the symbolic * link. 4.4BSD's symbolic links didn't have modes, * so it was an undocumented noop. In FreeBSD 3.0, * lchmod(2) is introduced and this option does real * work. */ hflag = 1; break; /* * XXX * "-[rwx]" are valid mode commands. If they are the entire * argument, getopt has moved past them, so decrement optind. * Regardless, we're done argument processing. */ case 'g': case 'o': case 'r': case 's': case 't': case 'u': case 'w': case 'X': case 'x': if (argv[gos.optind - 1][0] == '-' && argv[gos.optind - 1][1] == ch && argv[gos.optind - 1][2] == '\0') --gos.optind; goto done; case 'v': vflag++; break; case 261: usage(pCtx, 0); return 0; case 262: return kbuild_version(argv[0]); case '?': default: return usage(pCtx, 1); } done: argv += gos.optind; argc -= gos.optind; if (argc < 2) return usage(pCtx, 1); if (Rflag) { fts_options = FTS_PHYSICAL; if (hflag) return errx(pCtx, 1, "the -R and -h options may not be specified together."); if (Hflag) fts_options |= FTS_COMFOLLOW; if (Lflag) { fts_options &= ~FTS_PHYSICAL; fts_options |= FTS_LOGICAL; } } else fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL; #ifndef KMK_BUILTIN_STANDALONE fts_options |= FTS_NOCHDIR; /* Don't change the CWD while inside kmk. */ #endif if (hflag) change_mode = lchmod; else change_mode = chmod; mode = *argv; if ((set = bsd_setmode(mode)) == NULL) return errx(pCtx, 1, "invalid file mode: %s", mode); if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL) return err(pCtx, 1, "fts_open"); for (rval = 0; (p = fts_read(ftsp)) != NULL;) { switch (p->fts_info) { case FTS_D: /* Change it at FTS_DP. */ if (!Rflag) fts_set(ftsp, p, FTS_SKIP); continue; case FTS_DNR: /* Warn, chmod, continue. */ warnx(pCtx, "fts: %s: %s", p->fts_path, strerror(p->fts_errno)); rval = 1; break; case FTS_ERR: /* Warn, continue. */ case FTS_NS: warnx(pCtx, "fts: %s: %s", p->fts_path, strerror(p->fts_errno)); rval = 1; continue; case FTS_SL: /* Ignore. */ case FTS_SLNONE: /* * The only symlinks that end up here are ones that * don't point to anything and ones that we found * doing a physical walk. */ if (!hflag) continue; /* else */ /* FALLTHROUGH */ default: break; } newmode = bsd_getmode(set, p->fts_statp->st_mode); if ((newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS)) continue; if ((*change_mode)(p->fts_accpath, newmode) && !fflag) { warn(pCtx, "%schmod: %s", hflag ? "l" : "", p->fts_path); rval = 1; } else { if (vflag) { kmk_builtin_ctx_printf(pCtx, 0, "%s", p->fts_path); if (vflag > 1) { char m1[12], m2[12]; bsd_strmode(p->fts_statp->st_mode, m1); bsd_strmode((p->fts_statp->st_mode & S_IFMT) | newmode, m2); kmk_builtin_ctx_printf(pCtx, 0, ": 0%o [%s] -> 0%o [%s]", (unsigned int)p->fts_statp->st_mode, m1, (unsigned int)((p->fts_statp->st_mode & S_IFMT) | newmode), m2); } kmk_builtin_ctx_printf(pCtx, 0, "\n"); } } } if (errno) rval = err(pCtx, 1, "fts_read"); free(set); fts_close(ftsp); return rval; } int usage(PKMKBUILTINCTX pCtx, int is_err) { kmk_builtin_ctx_printf(pCtx, is_err, "usage: %s [-fhv] [-R [-H | -L | -P]] mode file ...\n" " or: %s --version\n" " or: %s --help\n", pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); return 1; } #ifdef KMK_BUILTIN_STANDALONE mode_t g_fUMask; int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_chmod", NULL }; umask(g_fUMask = umask(0077)); return kmk_builtin_chmod(argc, argv, envp, &Ctx); } #endif kbuild-3686/src/kmk/kmkbuiltin/solfakes.c0000664000175000017500000000427715053010075020417 0ustar locutuslocutus/* $Id: solfakes.c 2901 2016-09-09 15:10:24Z bird $ */ /** @file * Fake Unix stuff for Solaris. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include #include "solfakes.h" int asprintf(char **strp, const char *fmt, ...) { int rc; va_list va; va_start(va, fmt); rc = vasprintf(strp, fmt, va); va_end(va); return rc; } int vasprintf(char **strp, const char *fmt, va_list va) { int rc; char *psz; size_t cb = 1024; *strp = NULL; for (;;) { va_list va2; psz = malloc(cb); if (!psz) return -1; #ifdef va_copy va_copy(va2, va); rc = vsnprintf(psz, cb, fmt, va2); va_end(va2); #else va2 = va; rc = vsnprintf(psz, cb, fmt, va2); #endif if (rc < 0 || (size_t)rc < cb) break; cb *= 2; free(psz); } *strp = psz; return rc; } int sol_lchmod(const char *pszPath, mode_t mode) { /* * Weed out symbolic links. */ struct stat s; if ( !lstat(pszPath, &s) && S_ISLNK(s.st_mode)) { errno = -ENOSYS; return -1; } return chmod(pszPath, mode); } kbuild-3686/src/kmk/kmkbuiltin/install.c0000664000175000017500000010573215053010074020253 0ustar locutuslocutus/* * Copyright (c) 1987, 1993 * 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 0 /*ndef lint*/ static const char copyright[] = "@(#) Copyright (c) 1987, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #if 0 #ifndef lint static char sccsid[] = "@(#)xinstall.c 8.1 (Berkeley) 7/21/93"; #endif /* not lint */ #include __FBSDID("$FreeBSD: src/usr.bin/xinstall/xinstall.c,v 1.66 2005/01/25 14:34:57 ssouhlal Exp $"); #endif #define FAKES_NO_GETOPT_H #include "config.h" #ifndef _MSC_VER # include # if !defined(__HAIKU__) && !defined(__gnu_hurd__) # include # endif # include # include #endif /* !_MSC_VER */ #include #include #include "err.h" #include #include #include #include #include #include #include #include #ifndef __HAIKU__ # include #endif #ifdef __NetBSD__ # include # define strtofflags(a, b, c) string_to_flags(a, b, c) #endif #include #if defined(__EMX__) || defined(_MSC_VER) # include #endif #include "getopt_r.h" #ifdef __sun__ # include "solfakes.h" #endif #ifdef _MSC_VER # include "mscfakes.h" #endif #ifdef __HAIKU__ # include "haikufakes.h" #endif #include "kmkbuiltin.h" #include "k/kDefs.h" /* for K_OS */ #include "dos2unix.h" extern void * bsd_setmode(const char *p); extern mode_t bsd_getmode(const void *bbox, mode_t omode); #ifndef MAXBSIZE # define MAXBSIZE 0x20000 #endif #define MAX_CMP_SIZE (16 * 1024 * 1024) #define DIRECTORY 0x01 /* Tell install it's a directory. */ #define SETFLAGS 0x02 /* Tell install to set flags. */ #define NOCHANGEBITS (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND) #define BACKUP_SUFFIX ".old" #ifndef O_BINARY # define O_BINARY 0 #endif #ifndef EFTYPE # define EFTYPE EINVAL #endif #if defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__) # define IS_SLASH(ch) ((ch) == '/' || (ch) == '\\') #else # define IS_SLASH(ch) ((ch) == '/') #endif /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ typedef struct INSTALLINSTANCE { PKMKBUILTINCTX pCtx; gid_t gid; uid_t uid; int dobackup, docompare, dodir, dopreserve, dostrip, nommap, safecopy, verbose, mode_given; mode_t mode; const char *suffix; int ignore_perm_errors; int hard_link_files_when_possible; int verbose_hard_link_refusal; int verbose_hard_link_mode_mismatch; int dos2unix; } INSTALLINSTANCE; typedef INSTALLINSTANCE *PINSTALLINSTANCE; enum { kInstOpt_Help = 261, kInstOpt_Version, kInstOpt_Verbose, kInstOpt_Quiet, kInstOpt_IgnorePermErrors, kInstOpt_NoIgnorePermErrors, kInstOpt_HardLinkFilesWhenPossible, kInstOpt_NoHardLinkFilesWhenPossible, kInstOpt_Dos2Unix, kInstOpt_Unix2Dos, kInstOpt_VerboseHardLinkRefusal, kInstOpt_QuietHardLinkRefusal, kInstOpt_VerboseHardLinkModeMismatch, kInstOpt_QuietHardLinkModeMismatch }; /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ static struct option long_options[] = { { "help", no_argument, 0, kInstOpt_Help }, { "version", no_argument, 0, kInstOpt_Version }, { "quiet", no_argument, 0, kInstOpt_Quiet }, { "ignore-perm-errors", no_argument, 0, kInstOpt_IgnorePermErrors }, { "no-ignore-perm-errors", no_argument, 0, kInstOpt_NoIgnorePermErrors }, { "hard-link-files-when-possible", no_argument, 0, kInstOpt_HardLinkFilesWhenPossible }, { "no-hard-link-files-when-possible", no_argument, 0, kInstOpt_NoHardLinkFilesWhenPossible }, { "verbose-hard-link-refusal", no_argument, 0, kInstOpt_VerboseHardLinkRefusal }, { "quiet-hard-link-refusal", no_argument, 0, kInstOpt_QuietHardLinkRefusal }, { "verbose-hard-link-mode-mismatch", no_argument, 0, kInstOpt_VerboseHardLinkModeMismatch }, { "quiet-hard-link-mode-mismatch", no_argument, 0, kInstOpt_QuietHardLinkModeMismatch }, { "dos2unix", no_argument, 0, kInstOpt_Dos2Unix }, { "unix2dos", no_argument, 0, kInstOpt_Unix2Dos }, #if 1 /* GNU coreutils compatibility: */ { "compare", no_argument, 0, 'C' }, { "directory", no_argument, 0, 'd' }, { "group", required_argument, 0, 'g' }, { "mode", required_argument, 0, 'm' }, { "owner", required_argument, 0, 'o' }, { "strip", no_argument, 0, 's' }, { "suffix", required_argument, 0, 'S' }, { "verbose", no_argument, 0, 'v' }, #endif { 0, 0, 0, 0 }, }; static int copy(PINSTALLINSTANCE, int, const char *, int *, const char *); static int compare(int, size_t, int, size_t); static int create_newfile(PINSTALLINSTANCE, const char *, int, struct stat *); static int create_tempfile(const char *, char *, size_t); static int install(PINSTALLINSTANCE, const char *, const char *, u_long, u_int); static int install_dir(PINSTALLINSTANCE, char *); static u_long numeric_id(PINSTALLINSTANCE, const char *, const char *); static int strip(PINSTALLINSTANCE, const char *); static int usage(PKMKBUILTINCTX, int); static char *last_slash(const char *); static KBOOL needs_dos2unix_conversion(const char *pszFilename); static KBOOL needs_unix2dos_conversion(const char *pszFilename); int kmk_builtin_install(int argc, char *argv[], char ** envp, PKMKBUILTINCTX pCtx) { INSTALLINSTANCE This; struct getopt_state_r gos; struct stat from_sb, to_sb; mode_t *set; u_long fset = 0; int ch, no_target; u_int iflags; char *flags; const char *group, *owner, *to_name; (void)envp; /* Initialize global instance data. */ This.pCtx = pCtx; This.mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; This.suffix = BACKUP_SUFFIX; This.gid = 0; This.uid = 0; This.dobackup = 0; This.docompare = 0; This.dodir = 0; This.dopreserve = 0; This.dostrip = 0; This.nommap = 0; This.safecopy = 0; This.verbose = 0; This.mode_given = 0; This.ignore_perm_errors = geteuid() != 0; This.hard_link_files_when_possible = 0; This.verbose_hard_link_refusal = 0; This.verbose_hard_link_mode_mismatch = 0; This.dos2unix = 0; iflags = 0; group = owner = NULL; getopt_initialize_r(&gos, argc, argv, "B:bCcdf:g:Mm:o:pSsv", long_options, envp, pCtx); while ((ch = getopt_long_r(&gos, NULL)) != -1) switch(ch) { case 'B': This.suffix = gos.optarg; /* FALLTHROUGH */ case 'b': This.dobackup = 1; break; case 'C': This.docompare = 1; break; case 'c': /* For backwards compatibility. */ break; case 'd': This.dodir = 1; break; case 'f': #if defined(UF_IMMUTABLE) && K_OS != K_OS_GNU_KFBSD && K_OS != K_OS_GNU_HURD flags = optarg; if (strtofflags(&flags, &fset, NULL)) return errx(pCtx, EX_USAGE, "%s: invalid flag", flags); iflags |= SETFLAGS; #else (void)flags; #endif break; case 'g': group = gos.optarg; break; case 'M': This.nommap = 1; break; case 'm': if (!(set = bsd_setmode(gos.optarg))) return errx(pCtx, EX_USAGE, "invalid file mode: %s", gos.optarg); This.mode = bsd_getmode(set, 0); free(set); This.mode_given = 1; break; case 'o': owner = gos.optarg; break; case 'p': This.docompare = This.dopreserve = 1; break; case 'S': This.safecopy = 1; This.verbose_hard_link_refusal = 0; break; case 's': This.dostrip = 1; This.verbose_hard_link_refusal = 0; break; case 'v': case kInstOpt_Verbose: This.verbose = 1; break; case kInstOpt_Quiet: This.verbose = 0; break; case kInstOpt_Help: usage(pCtx, 0); return 0; case kInstOpt_Version: return kbuild_version(argv[0]); case kInstOpt_IgnorePermErrors: This.ignore_perm_errors = 1; break; case kInstOpt_NoIgnorePermErrors: This.ignore_perm_errors = 0; break; case kInstOpt_HardLinkFilesWhenPossible: This.hard_link_files_when_possible = 1; break; case kInstOpt_NoHardLinkFilesWhenPossible: This.hard_link_files_when_possible = 0; break; case kInstOpt_VerboseHardLinkRefusal: This.verbose_hard_link_refusal = 1; break; case kInstOpt_QuietHardLinkRefusal: This.verbose_hard_link_refusal = 0; break; case kInstOpt_VerboseHardLinkModeMismatch: This.verbose_hard_link_mode_mismatch = 1; break; case kInstOpt_QuietHardLinkModeMismatch: This.verbose_hard_link_mode_mismatch = 0; break; case kInstOpt_Dos2Unix: This.dos2unix = 1; This.verbose_hard_link_refusal = 0; break; case kInstOpt_Unix2Dos: This.dos2unix = -1; This.verbose_hard_link_refusal = 0; break; case '?': default: return usage(pCtx, 1); } argc -= gos.optind; argv += gos.optind; /* some options make no sense when creating directories */ if (This.dostrip && This.dodir) { warnx(pCtx, "-d and -s may not be specified together"); return usage(pCtx, 1); } /* must have at least two arguments, except when creating directories */ if (argc == 0 || (argc == 1 && !This.dodir)) return usage(pCtx, 1); /* and unix2dos doesn't combine well with a couple of other options. */ if (This.dos2unix != 0) { if (This.docompare) { warnx(pCtx, "-C/-p and --dos2unix/unix2dos may not be specified together"); return usage(pCtx, 1); } if (This.dostrip) { warnx(pCtx, "-s and --dos2unix/unix2dos may not be specified together"); return usage(pCtx, 1); } } /* need to make a temp copy so we can compare stripped version */ if (This.docompare && This.dostrip) This.safecopy = 1; /* get group and owner id's */ if (group != NULL) { #ifndef _MSC_VER struct group *gp; if ((gp = getgrnam(group)) != NULL) This.gid = gp->gr_gid; else #endif { This.gid = (gid_t)numeric_id(&This, group, "group"); if (This.gid == (gid_t)-1) return 1; } } else This.gid = (gid_t)-1; if (owner != NULL) { #ifndef _MSC_VER struct passwd *pp; if ((pp = getpwnam(owner)) != NULL) This.uid = pp->pw_uid; else #endif { This.uid = (uid_t)numeric_id(&This, owner, "user"); if (This.uid == (uid_t)-1) return 1; } } else This.uid = (uid_t)-1; if (This.dodir) { for (; *argv != NULL; ++argv) { int rc = install_dir(&This, *argv); if (rc) return rc; } return EX_OK; /* NOTREACHED */ } no_target = stat(to_name = argv[argc - 1], &to_sb); if (!no_target && S_ISDIR(to_sb.st_mode)) { for (; *argv != to_name; ++argv) { int rc = install(&This, *argv, to_name, fset, iflags | DIRECTORY); if (rc) return rc; } return EX_OK; } /* can't do file1 file2 directory/file */ if (argc != 2) { warnx(pCtx, "wrong number or types of arguments"); return usage(pCtx, 1); } if (!no_target) { if (stat(*argv, &from_sb)) return err(pCtx, EX_OSERR, "%s", *argv); if (!S_ISREG(to_sb.st_mode)) { errno = EFTYPE; return err(pCtx, EX_OSERR, "%s", to_name); } if (to_sb.st_dev == from_sb.st_dev && to_sb.st_dev != 0 && to_sb.st_ino == from_sb.st_ino && to_sb.st_ino != 0 && !This.hard_link_files_when_possible) return errx(pCtx, EX_USAGE, "%s and %s are the same file", *argv, to_name); } return install(&This, *argv, to_name, fset, iflags); } #ifdef KMK_BUILTIN_STANDALONE mode_t g_fUMask; int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_install", NULL }; umask(g_fUMask = umask(0077)); return kmk_builtin_install(argc, argv, envp, &Ctx); } #endif static u_long numeric_id(PINSTALLINSTANCE pThis, const char *name, const char *type) { u_long val; char *ep; /* * XXX * We know that uid_t's and gid_t's are unsigned longs. */ errno = 0; val = strtoul(name, &ep, 10); if (errno) return err(pThis->pCtx, -1, "%s", name); if (*ep != '\0') return errx(pThis->pCtx, -1, "unknown %s %s", type, name); return (val); } /* * install -- * build a path name and install the file */ static int install(PINSTALLINSTANCE pThis, const char *from_name, const char *to_name, u_long fset, u_int flags) { struct stat from_sb, temp_sb, to_sb; struct timeval tvb[2]; int devnull, files_match, from_fd, serrno, target; int tempcopy, temp_fd, to_fd; char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN]; int rc = EX_OK; files_match = 0; from_fd = -1; to_fd = -1; temp_fd = -1; /* If try to install NULL file to a directory, fails. */ if (flags & DIRECTORY #if defined(__EMX__) || defined(_MSC_VER) || ( stricmp(from_name, _PATH_DEVNULL) && stricmp(from_name, "nul") # ifdef __EMX__ && stricmp(from_name, "/dev/nul") # endif ) #else || strcmp(from_name, _PATH_DEVNULL) #endif ) { if (stat(from_name, &from_sb)) return err(pThis->pCtx, EX_OSERR, "%s", from_name); if (!S_ISREG(from_sb.st_mode)) { errno = EFTYPE; return err(pThis->pCtx, EX_OSERR, "%s", from_name); } /* Build the target path. */ if (flags & DIRECTORY) { (void)snprintf(pathbuf, sizeof(pathbuf), "%s/%s", to_name, (p = last_slash(from_name)) ? ++p : from_name); to_name = pathbuf; } devnull = 0; } else { devnull = 1; } target = stat(to_name, &to_sb) == 0; /* Only install to regular files. */ if (target && !S_ISREG(to_sb.st_mode)) { errno = EFTYPE; warn(pThis->pCtx, "%s", to_name); return EX_OK; } /* Only copy safe if the target exists. */ tempcopy = pThis->safecopy && target; /* Try hard linking if wanted and possible. */ if (pThis->hard_link_files_when_possible) { #ifdef KBUILD_OS_OS2 const char *why_not = "not supported on OS/2"; #else const char *why_not = NULL; if (devnull) { why_not = "/dev/null"; } else if (pThis->dostrip) { why_not = "strip (-s)"; } else if (pThis->docompare) { why_not = "compare (-C)"; } else if (pThis->dobackup) { why_not = "backup (-b/-B)"; } else if (pThis->safecopy) { why_not = "safe copy (-S)"; } else if (lstat(from_name, &temp_sb)) { why_not = "lstat on source failed"; } else if (S_ISLNK(temp_sb.st_mode)) { why_not = "symlink"; } else if (!S_ISREG(temp_sb.st_mode)) { why_not = "not regular file"; # if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2) } else if ((pThis->mode & S_IWUSR) != (from_sb.st_mode & S_IWUSR)) { # else } else if (pThis->mode != (from_sb.st_mode & ALLPERMS)) { # endif if ( pThis->verbose_hard_link_mode_mismatch || pThis->verbose_hard_link_refusal) kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: warning: Not hard linking, mode differs: 0%03o, desires 0%03o\n" "install: src path '%s'\n" "install: dst path '%s'\n", (from_sb.st_mode & ALLPERMS), pThis->mode, from_name, to_name); why_not = NULL; } else if (pThis->uid != (uid_t)-1 && pThis->uid != from_sb.st_uid) { why_not = "uid mismatch"; } else if (pThis->gid != (gid_t)-1 && pThis->gid != from_sb.st_gid) { why_not = "gid mismatch"; } else if (pThis->dos2unix > 0 && needs_dos2unix_conversion(from_name)) { why_not = "dos2unix"; } else if (pThis->dos2unix < 0 && needs_unix2dos_conversion(from_name)) { why_not = "unix2dos"; } else { int rcLink = link(from_name, to_name); if (rcLink != 0 && errno == EEXIST) { unlink(to_name); rcLink = link(from_name, to_name); } if (rcLink == 0) { if (pThis->verbose) kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: %s -> %s (hardlinked)\n", from_name, to_name); goto l_done; } if (pThis->verbose) kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: hard linking '%s' to '%s' failed: %s\n", to_name, from_name, strerror(errno)); why_not = NULL; } #endif if (why_not && pThis->verbose_hard_link_refusal) kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: not hard linking '%s' to '%s' because: %s\n", to_name, from_name, why_not); /* Can't hard link or we failed, continue as nothing happend. */ } if (!devnull && (from_fd = open(from_name, O_RDONLY | O_BINARY | KMK_OPEN_NO_INHERIT, 0)) < 0) return err(pThis->pCtx, EX_OSERR, "%s", from_name); /* If we don't strip, we can compare first. */ if (pThis->docompare && !pThis->dostrip && target) { if ((to_fd = open(to_name, O_RDONLY | O_BINARY | KMK_OPEN_NO_INHERIT, 0)) < 0) { rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); goto l_done; } if (devnull) files_match = to_sb.st_size == 0; else files_match = !compare(from_fd, (size_t)from_sb.st_size, to_fd, (size_t)to_sb.st_size); /* Close "to" file unless we match. */ if (!files_match) { (void)close(to_fd); to_fd = -1; } } if (!files_match) { if (tempcopy) { to_fd = create_tempfile(to_name, tempfile, sizeof(tempfile)); if (to_fd < 0) { rc = err(pThis->pCtx, EX_OSERR, "%s", tempfile); goto l_done; } } else { if ((to_fd = create_newfile(pThis, to_name, target, &to_sb)) < 0) { rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); goto l_done; } if (pThis->verbose) kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: %s -> %s\n", from_name, to_name); } if (!devnull) { rc = copy(pThis, from_fd, from_name, &to_fd, tempcopy ? tempfile : to_name); if (rc) goto l_done; } } if (pThis->dostrip) { #if defined(__EMX__) || defined(_MSC_VER) /* close before we strip. */ close(to_fd); to_fd = -1; #endif rc = strip(pThis, tempcopy ? tempfile : to_name); if (rc) goto l_done; /* * Re-open our fd on the target, in case we used a strip * that does not work in-place -- like GNU binutils strip. */ #if !defined(__EMX__) && !defined(_MSC_VER) close(to_fd); #endif to_fd = open(tempcopy ? tempfile : to_name, O_RDONLY | O_BINARY | KMK_OPEN_NO_INHERIT, 0); if (to_fd < 0) { rc = err(pThis->pCtx, EX_OSERR, "stripping %s", to_name); goto l_done; } } /* * Compare the stripped temp file with the target. */ if (pThis->docompare && pThis->dostrip && target) { temp_fd = to_fd; /* Re-open to_fd using the real target name. */ if ((to_fd = open(to_name, O_RDONLY | O_BINARY | KMK_OPEN_NO_INHERIT, 0)) < 0) { rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); goto l_done; } if (fstat(temp_fd, &temp_sb)) { serrno = errno; (void)unlink(tempfile); errno = serrno; rc = err(pThis->pCtx, EX_OSERR, "%s", tempfile); goto l_done; } if (compare(temp_fd, (size_t)temp_sb.st_size, to_fd, (size_t)to_sb.st_size) == 0) { /* * If target has more than one link we need to * replace it in order to snap the extra links. * Need to preserve target file times, though. */ #if !defined(_MSC_VER) && !defined(__EMX__) if (to_sb.st_nlink != 1) { tvb[0].tv_sec = to_sb.st_atime; tvb[0].tv_usec = 0; tvb[1].tv_sec = to_sb.st_mtime; tvb[1].tv_usec = 0; (void)utimes(tempfile, tvb); } else #endif { files_match = 1; (void)unlink(tempfile); } (void) close(temp_fd); temp_fd = -1; } } /* * Move the new file into place if doing a safe copy * and the files are different (or just not compared). */ if (tempcopy && !files_match) { #ifdef UF_IMMUTABLE /* Try to turn off the immutable bits. */ if (to_sb.st_flags & NOCHANGEBITS) (void)chflags(to_name, to_sb.st_flags & ~NOCHANGEBITS); #endif if (pThis->dobackup) { if ( (size_t)snprintf(backup, MAXPATHLEN, "%s%s", to_name, pThis->suffix) != strlen(to_name) + strlen(pThis->suffix)) { unlink(tempfile); rc = errx(pThis->pCtx, EX_OSERR, "%s: backup filename too long", to_name); goto l_done; } if (pThis->verbose) kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: %s -> %s\n", to_name, backup); if (rename(to_name, backup) < 0) { serrno = errno; unlink(tempfile); errno = serrno; rc = err(pThis->pCtx, EX_OSERR, "rename: %s to %s", to_name, backup); goto l_done; } } if (pThis->verbose) kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: %s -> %s\n", from_name, to_name); if (rename(tempfile, to_name) < 0) { serrno = errno; unlink(tempfile); errno = serrno; rc = err(pThis->pCtx, EX_OSERR, "rename: %s to %s", tempfile, to_name); goto l_done; } /* Re-open to_fd so we aren't hosed by the rename(2). */ (void) close(to_fd); if ((to_fd = open(to_name, O_RDONLY | O_BINARY | KMK_OPEN_NO_INHERIT, 0)) < 0) { rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); goto l_done; } } /* * Preserve the timestamp of the source file if necessary. */ if (pThis->dopreserve && !files_match && !devnull) { tvb[0].tv_sec = from_sb.st_atime; tvb[0].tv_usec = 0; tvb[1].tv_sec = from_sb.st_mtime; tvb[1].tv_usec = 0; (void)utimes(to_name, tvb); } if (fstat(to_fd, &to_sb) == -1) { serrno = errno; (void)unlink(to_name); errno = serrno; rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); goto l_done; } /* * Set owner, group, mode for target; do the chown first, * chown may lose the setuid bits. */ #ifdef UF_IMMUTABLE if ((pThis->gid != (gid_t)-1 && pThis->gid != to_sb.st_gid) || (pThis->uid != (uid_t)-1 && pThis->uid != to_sb.st_uid) || (pThis->mode != (to_sb.st_mode & ALLPERMS))) { /* Try to turn off the immutable bits. */ if (to_sb.st_flags & NOCHANGEBITS) (void)fchflags(to_fd, to_sb.st_flags & ~NOCHANGEBITS); } #endif if ((pThis->gid != (gid_t)-1 && pThis->gid != to_sb.st_gid) || (pThis->uid != (uid_t)-1 && pThis->uid != to_sb.st_uid)) if (fchown(to_fd, pThis->uid, pThis->gid) == -1) { if (errno == EPERM && pThis->ignore_perm_errors) { warn(pThis->pCtx, "%s: ignoring chown uid=%d gid=%d failure", to_name, (int)pThis->uid, (int)pThis->gid); } else { serrno = errno; (void)unlink(to_name); errno = serrno; rc = err(pThis->pCtx, EX_OSERR,"%s: chown/chgrp", to_name); goto l_done; } } if (pThis->mode != (to_sb.st_mode & ALLPERMS)) if (fchmod(to_fd, pThis->mode)) { serrno = errno; if (serrno == EPERM && pThis->ignore_perm_errors) { fchmod(to_fd, pThis->mode & (ALLPERMS & ~0007000)); errno = errno; warn(pThis->pCtx, "%s: ignoring chmod 0%o failure", to_name, (int)(pThis->mode & ALLPERMS)); } else { serrno = errno; (void)unlink(to_name); errno = serrno; rc = err(pThis->pCtx, EX_OSERR, "%s: chmod", to_name); goto l_done; } } /* * If provided a set of flags, set them, otherwise, preserve the * flags, except for the dump flag. * NFS does not support flags. Ignore EOPNOTSUPP flags if we're just * trying to turn off UF_NODUMP. If we're trying to set real flags, * then warn if the the fs doesn't support it, otherwise fail. */ #ifdef UF_IMMUTABLE if ( !devnull && (flags & SETFLAGS || (from_sb.st_flags & ~UF_NODUMP) != to_sb.st_flags) && fchflags(to_fd, flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) { if (flags & SETFLAGS) { if (errno == EOPNOTSUPP) warn(pThis->pCtx, "%s: chflags", to_name); else { serrno = errno; (void)unlink(to_name); errno = serrno; rc = err(pThis->pCtx, EX_OSERR, "%s: chflags", to_name); goto l_done; } } } #endif l_done: if (to_fd >= 0) (void)close(to_fd); if (temp_fd >= 0) (void)close(temp_fd); if (from_fd >= 0 && !devnull) (void)close(from_fd); return rc; } /* * compare -- * compare two files; non-zero means files differ */ static int compare(int from_fd, size_t from_len, int to_fd, size_t to_len) { char buf1[MAXBSIZE]; char buf2[MAXBSIZE]; int n1, n2; int rv; if (from_len != to_len) return 1; if (from_len <= MAX_CMP_SIZE) { rv = 0; lseek(from_fd, 0, SEEK_SET); lseek(to_fd, 0, SEEK_SET); while (rv == 0) { n1 = read(from_fd, buf1, sizeof(buf1)); if (n1 == 0) break; /* EOF */ else if (n1 > 0) { n2 = read(to_fd, buf2, n1); if (n2 == n1) rv = memcmp(buf1, buf2, n1); else rv = 1; /* out of sync */ } else rv = 1; /* read failure */ } lseek(from_fd, 0, SEEK_SET); lseek(to_fd, 0, SEEK_SET); } else rv = 1; /* don't bother in this case */ return rv; } /* * create_tempfile -- * create a temporary file based on path and open it */ int create_tempfile(const char *path, char *temp, size_t tsize) { static char s_szTemplate[] = "INS@XXXXXX"; const char *p = last_slash(path); if (p) { size_t cchDir = ++p - path; if (cchDir + sizeof(s_szTemplate) <= tsize) { memcpy(temp, path, cchDir); memcpy(&temp[cchDir], s_szTemplate, sizeof(s_szTemplate)); } else return EOVERFLOW; } else if (tsize >= sizeof(s_szTemplate)) memcpy(temp, s_szTemplate, sizeof(s_szTemplate)); else return EOVERFLOW; return (mkstemp(temp)); } /* * create_newfile -- * create a new file, overwriting an existing one if necessary */ int create_newfile(PINSTALLINSTANCE pThis, const char *path, int target, struct stat *sbp) { char backup[MAXPATHLEN]; int saved_errno = 0; int newfd; if (target) { /* * Unlink now... avoid ETXTBSY errors later. Try to turn * off the append/immutable bits -- if we fail, go ahead, * it might work. */ #ifdef UF_IMMUTABLE if (sbp->st_flags & NOCHANGEBITS) (void)chflags(path, sbp->st_flags & ~NOCHANGEBITS); #endif if (pThis->dobackup) { if ( (size_t)snprintf(backup, MAXPATHLEN, "%s%s", path, pThis->suffix) != strlen(path) + strlen(pThis->suffix)) { errx(pThis->pCtx, EX_OSERR, "%s: backup filename too long", path); errno = ENAMETOOLONG; return -1; } (void)snprintf(backup, MAXPATHLEN, "%s%s", path, pThis->suffix); if (pThis->verbose) kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: %s -> %s\n", path, backup); if (rename(path, backup) < 0) { err(pThis->pCtx, EX_OSERR, "rename: %s to %s", path, backup); return -1; } } else if (unlink(path) < 0) saved_errno = errno; } newfd = open(path, O_CREAT | O_RDWR | O_TRUNC | O_BINARY | KMK_OPEN_NO_INHERIT, S_IRUSR | S_IWUSR); if (newfd < 0 && saved_errno != 0) errno = saved_errno; return newfd; } /* * Write error handler. */ static int write_error(PINSTALLINSTANCE pThis, int *ptr_to_fd, const char *to_name, int nw) { int serrno = errno; (void)close(*ptr_to_fd); *ptr_to_fd = -1; (void)unlink(to_name); errno = nw > 0 ? EIO : serrno; return err(pThis->pCtx, EX_OSERR, "%s", to_name); } /* * Read error handler. */ static int read_error(PINSTALLINSTANCE pThis, const char *from_name, int *ptr_to_fd, const char *to_name) { int serrno = errno; (void)close(*ptr_to_fd); *ptr_to_fd = -1; (void)unlink(to_name); errno = serrno; return err(pThis->pCtx, EX_OSERR, "%s", from_name); } /* * copy -- * copy from one file to another */ static int copy(PINSTALLINSTANCE pThis, int from_fd, const char *from_name, int *ptr_to_fd, const char *to_name) { KBOOL fPendingCr = K_FALSE; KSIZE cchDst; int nr, nw; char buf[MAXBSIZE]; int to_fd = *ptr_to_fd; /* Rewind file descriptors. */ if (lseek(from_fd, (off_t)0, SEEK_SET) == (off_t)-1) return err(pThis->pCtx, EX_OSERR, "lseek: %s", from_name); if (lseek(to_fd, (off_t)0, SEEK_SET) == (off_t)-1) return err(pThis->pCtx, EX_OSERR, "lseek: %s", to_name); if (pThis->dos2unix == 0) { /* * Copy bytes, no conversion. */ while ((nr = read(from_fd, buf, sizeof(buf))) > 0) if ((nw = write(to_fd, buf, nr)) != nr) return write_error(pThis, ptr_to_fd, to_name, nw); } else if (pThis->dos2unix > 0) { /* * CRLF -> LF is a reduction, so we can work with full buffers. */ while ((nr = read(from_fd, buf, sizeof(buf))) > 0) { if ( fPendingCr && buf[0] != '\n' && (nw = write(to_fd, "\r", 1)) != 1) return write_error(pThis, ptr_to_fd, to_name, nw); fPendingCr = dos2unix_convert_to_unix(buf, nr, buf, &cchDst); nw = write(to_fd, buf, cchDst); if (nw != (int)cchDst) return write_error(pThis, ptr_to_fd, to_name, nw); } } else { /* * LF -> CRLF is an expansion, so we work with half buffers, reading * into the upper half of the buffer and expanding into the full buffer. * The conversion will never expand to more than the double size. * * Note! We do not convert valid CRLF line endings. This gives us * valid DOS text, but no round-trip conversion. */ char * const pchSrc = &buf[sizeof(buf) / 2]; while ((nr = read(from_fd, pchSrc, sizeof(buf) / 2)) > 0) { if ( fPendingCr && pchSrc[0] != '\n' && (nw = write(to_fd, "\r", 1))!= 1) return write_error(pThis, ptr_to_fd, to_name, nw); fPendingCr = dos2unix_convert_to_dos(pchSrc, nr, buf, &cchDst); nw = write(to_fd, buf, cchDst); if (nw != (int)cchDst) return write_error(pThis, ptr_to_fd, to_name, nw); } } /* Check for read error. */ if (nr != 0) return read_error(pThis, from_name, ptr_to_fd, to_name); /* When converting, we might have a pending final CR to write. */ if ( fPendingCr && (nw = write(to_fd, "\r", 1))!= 1) return write_error(pThis, ptr_to_fd, to_name, nw); return EX_OK; } /* * strip -- * use strip(1) to strip the target file */ static int strip(PINSTALLINSTANCE pThis, const char *to_name) { #if defined(__EMX__) || defined(_MSC_VER) const char *stripbin = getenv("STRIPBIN"); if (stripbin == NULL) stripbin = "strip"; (void)pThis; return spawnlp(P_WAIT, stripbin, stripbin, to_name, NULL); #else const char *stripbin; int serrno, status; pid_t pid; pid = fork(); switch (pid) { case -1: serrno = errno; (void)unlink(to_name); errno = serrno; return err(pThis->pCtx, EX_TEMPFAIL, "fork"); case 0: stripbin = getenv("STRIPBIN"); if (stripbin == NULL) stripbin = "strip"; execlp(stripbin, stripbin, to_name, (char *)NULL); err(pThis->pCtx, EX_OSERR, "exec(%s)", stripbin); exit(EX_OSERR); default: if (waitpid(pid, &status, 0) == -1 || status) { serrno = errno; (void)unlink(to_name); errno = serrno; return err(pThis->pCtx, EX_SOFTWARE, "waitpid"); /* NOTREACHED */ } } return 0; #endif } /* * install_dir -- * build directory heirarchy */ static int install_dir(PINSTALLINSTANCE pThis, char *path) { char *p; struct stat sb; int ch; for (p = path;; ++p) if ( !*p || ( p != path && IS_SLASH(*p) #if defined(_MSC_VER) /* stat("C:") fails (VC++ v10). Just skip it since it's unnecessary. */ && (p - path != 2 || p[-1] != ':') #endif )) { ch = *p; *p = '\0'; if (stat(path, &sb)) { if (errno != ENOENT || mkdir(path, 0755) < 0) { return err(pThis->pCtx, EX_OSERR, "mkdir %s", path); /* NOTREACHED */ } else if (pThis->verbose) kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: mkdir %s\n", path); } else if (!S_ISDIR(sb.st_mode)) return errx(pThis->pCtx, EX_OSERR, "%s exists but is not a directory", path); if (!(*p = ch)) break; } if ((pThis->gid != (gid_t)-1 || pThis->uid != (uid_t)-1) && chown(path, pThis->uid, pThis->gid)) warn(pThis->pCtx, "chown %u:%u %s", pThis->uid, pThis->gid, path); if (chmod(path, pThis->mode)) warn(pThis->pCtx, "chmod %o %s", pThis->mode, path); return EX_OK; } /* * usage -- * print a usage message and die */ static int usage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s [-bCcpSsv] [--[no-]hard-link-files-when-possible]\n" " [--verbose-hard-link-refusal] [--verbose-hard-link-mode-mismatch]\n" " [--[no-]ignore-perm-errors] [-B suffix] [-f flags] [-g group]\n" " [-m mode] [-o owner] [--dos2unix|--unix2dos] file1 file2\n" " or: %s [-bCcpSsv] [--[no-]ignore-perm-errors] [-B suffix] [-f flags]\n" " [-g group] [-m mode] [-o owner] file1 ... fileN directory\n" " or: %s -d [-v] [-g group] [-m mode] [-o owner] directory ...\n" " or: %s --help\n" " or: %s --version\n", pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); return EX_USAGE; } /* figures out where the last slash or colon is. */ static char * last_slash(const char *path) { #if defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__) char *p = (char *)strrchr(path, '/'); if (p) { char *p2 = strrchr(p, '\\'); if (p2) p = p2; } else { p = (char *)strrchr(path, '\\'); if (!p && isalpha(path[0]) && path[1] == ':') p = (char *)&path[1]; } return p; #else return strrchr(path, '/'); #endif } /** * Checks if @a pszFilename actually needs dos2unix conversion. * * @returns boolean. * @param pszFilename The name of the file to check. */ static KBOOL needs_dos2unix_conversion(const char *pszFilename) { KU32 fStyle = 0; int iErr = dos2unix_analyze_file(pszFilename, &fStyle, NULL, NULL); return iErr != 0 || (fStyle & (DOS2UNIX_STYLE_MASK | DOS2UNIX_F_BINARY)) != DOS2UNIX_STYLE_UNIX; } /** * Checks if @a pszFilename actually needs unix2dos conversion. * * @returns boolean. * @param pszFilename The name of the file to check. */ static KBOOL needs_unix2dos_conversion(const char *pszFilename) { KU32 fStyle = 0; int iErr = dos2unix_analyze_file(pszFilename, &fStyle, NULL, NULL); return iErr != 0 || (fStyle & (DOS2UNIX_STYLE_MASK | DOS2UNIX_F_BINARY)) != DOS2UNIX_STYLE_DOS; } kbuild-3686/src/kmk/kmkbuiltin/openbsd.c0000664000175000017500000000310415053010074020225 0ustar locutuslocutus/* $Id: openbsd.c 2421 2010-10-17 21:27:53Z bird $ */ /** @file * Missing BSD functions in OpenBSD. */ /* * Copyright (c) 2006-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include int lchmod(const char *path, mode_t mode) { struct stat st; if (lstat(path, &st)) return -1; if (S_ISLNK(st.st_mode)) return 0; /* pretend success */ return chmod(path, mode); } int lutimes(const char *path, const struct timeval *tvs) { struct stat st; if (lstat(path, &st)) return -1; if (S_ISLNK(st.st_mode)) return 0; /* pretend success */ return utimes(path, tvs); } kbuild-3686/src/kmk/kmkbuiltin/err.c0000664000175000017500000002345615053010075017400 0ustar locutuslocutus/* $Id: err.c 3636 2024-11-02 01:52:45Z bird $ */ /** @file * Override err.h so we get the program name right. */ /* * Copyright (c) 2005-2016 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #ifdef HAVE_CONFIG_H # include "config.h" # ifdef HAVE_STDLIB_H # include # endif # ifdef HAVE_STDINT_H # include # endif #else # include # if _MSC_VER < 1400 # define snprintf _snprintf # endif #endif #include #include #include #include #include "err.h" #if !defined(KMK_BUILTIN_STANDALONE) && !defined(KWORKER) # include "../output.h" #endif #ifdef KBUILD_OS_WINDOWS /* This is a trick to speed up console output on windows. */ # include "console.h" # undef fwrite # define fwrite maybe_con_fwrite #endif int err(PKMKBUILTINCTX pCtx, int eval, const char *fmt, ...) { /* * We format into a buffer and pass that onto output.c or fwrite. */ int error = errno; char *pszToFree = NULL; char szMsgStack[4096]; char *pszMsg = szMsgStack; size_t cbMsg = sizeof(szMsgStack); for (;;) { int cchMsg = snprintf(pszMsg, cbMsg, "%s: error: ", pCtx->pszProgName); if (cchMsg < (int)cbMsg - 1 && cchMsg > 0) { int cchMsg2; va_list va; va_start(va, fmt); cchMsg += cchMsg2 = vsnprintf(&pszMsg[cchMsg], cbMsg - cchMsg, fmt, va); va_end(va); if ( cchMsg < (int)cbMsg - 1 && cchMsg2 >= 0) { cchMsg += cchMsg2 = snprintf(&pszMsg[cchMsg], cbMsg - cchMsg, ": %s\n", strerror(error)); if ( cchMsg < (int)cbMsg - 1 && cchMsg2 >= 0) { #if !defined(KMK_BUILTIN_STANDALONE) && !defined(KWORKER) if (pCtx->pOut) output_write_text(pCtx->pOut, 1 /*is_err*/, pszMsg, cchMsg); else #endif { fflush(stdout); fwrite(pszMsg, cchMsg, 1, stderr); fflush(stderr); /* paranoia */ } if (pszToFree) free(pszToFree); errno = error; return eval; } } } /* double the buffer size and retry */ if (pszToFree) free(pszToFree); cbMsg *= 2; pszToFree = malloc(cbMsg); if (!pszToFree) { fprintf(stderr, "out of memory!\n"); errno = error; return eval; } } } int errx(PKMKBUILTINCTX pCtx, int eval, const char *fmt, ...) { /* * We format into a buffer and pass that onto output.c or fwrite. */ char *pszToFree = NULL; char szMsgStack[4096]; char *pszMsg = szMsgStack; size_t cbMsg = sizeof(szMsgStack); for (;;) { int cchMsg = snprintf(pszMsg, cbMsg, "%s: error: ", pCtx->pszProgName); if (cchMsg < (int)cbMsg - 1 && cchMsg > 0) { int cchMsg2; va_list va; va_start(va, fmt); cchMsg += cchMsg2 = vsnprintf(&pszMsg[cchMsg], cbMsg - cchMsg, fmt, va); va_end(va); if ( cchMsg < (int)cbMsg - 2 && cchMsg2 >= 0) { /* ensure newline */ if (pszMsg[cchMsg - 1] != '\n') { pszMsg[cchMsg++] = '\n'; pszMsg[cchMsg] = '\0'; } #if !defined(KMK_BUILTIN_STANDALONE) && !defined(KWORKER) if (pCtx->pOut) output_write_text(pCtx->pOut, 1 /*is_err*/, pszMsg, cchMsg); else #endif { fflush(stdout); fwrite(pszMsg, cchMsg, 1, stderr); fflush(stderr); /* paranoia */ } if (pszToFree) free(pszToFree); return eval; } } /* double the buffer size and retry */ if (pszToFree) free(pszToFree); cbMsg *= 2; pszToFree = malloc(cbMsg); if (!pszToFree) { fprintf(stderr, "out of memory!\n"); return eval; } } } void warn(PKMKBUILTINCTX pCtx, const char *fmt, ...) { /* * We format into a buffer and pass that onto output.c or fwrite. */ int error = errno; char *pszToFree = NULL; char szMsgStack[4096]; char *pszMsg = szMsgStack; size_t cbMsg = sizeof(szMsgStack); for (;;) { int cchMsg = snprintf(pszMsg, cbMsg, "%s: ", pCtx->pszProgName); if (cchMsg < (int)cbMsg - 1 && cchMsg > 0) { int cchMsg2; va_list va; va_start(va, fmt); cchMsg += cchMsg2 = vsnprintf(&pszMsg[cchMsg], cbMsg - cchMsg, fmt, va); va_end(va); if ( cchMsg < (int)cbMsg - 1 && cchMsg2 >= 0) { cchMsg += cchMsg2 = snprintf(&pszMsg[cchMsg], cbMsg - cchMsg, ": %s\n", strerror(error)); if ( cchMsg < (int)cbMsg - 1 && cchMsg2 >= 0) { #if !defined(KMK_BUILTIN_STANDALONE) && !defined(KWORKER) if (pCtx->pOut) output_write_text(pCtx->pOut, 1 /*is_err*/, pszMsg, cchMsg); else #endif { fflush(stdout); fwrite(pszMsg, cchMsg, 1, stderr); fflush(stderr); /* paranoia */ } if (pszToFree) free(pszToFree); errno = error; return; } } } /* double the buffer size and retry */ if (pszToFree) free(pszToFree); cbMsg *= 2; pszToFree = malloc(cbMsg); if (!pszToFree) { fprintf(stderr, "out of memory!\n"); errno = error; return; } } } void warnx(PKMKBUILTINCTX pCtx, const char *fmt, ...) { /* * We format into a buffer and pass that onto output.c or fwrite. */ char *pszToFree = NULL; char szMsgStack[4096]; char *pszMsg = szMsgStack; size_t cbMsg = sizeof(szMsgStack); for (;;) { int cchMsg = snprintf(pszMsg, cbMsg, "%s: ", pCtx->pszProgName); if (cchMsg < (int)cbMsg - 1 && cchMsg > 0) { int cchMsg2; va_list va; va_start(va, fmt); cchMsg += cchMsg2 = vsnprintf(&pszMsg[cchMsg], cbMsg - cchMsg, fmt, va); va_end(va); if ( cchMsg < (int)cbMsg - 2 && cchMsg2 >= 0) { /* ensure newline */ if (pszMsg[cchMsg - 1] != '\n') { pszMsg[cchMsg++] = '\n'; pszMsg[cchMsg] = '\0'; } #if !defined(KMK_BUILTIN_STANDALONE) && !defined(KWORKER) if (pCtx->pOut) output_write_text(pCtx->pOut, 1 /*is_err*/, pszMsg, cchMsg); else #endif { fflush(stdout); fwrite(pszMsg, cchMsg, 1, stderr); fflush(stderr); /* paranoia */ } if (pszToFree) free(pszToFree); return; } } /* double the buffer size and retry */ if (pszToFree) free(pszToFree); cbMsg *= 2; pszToFree = malloc(cbMsg); if (!pszToFree) { fprintf(stderr, "out of memory!\n"); return; } } } void kmk_builtin_ctx_printf(PKMKBUILTINCTX pCtx, int fIsErr, const char *pszFormat, ...) { /* * We format into a buffer and pass that onto output.c or fwrite. */ char *pszToFree = NULL; char szMsgStack[4096]; char *pszMsg = szMsgStack; size_t cbMsg = sizeof(szMsgStack); for (;;) { int cchMsg; va_list va; va_start(va, pszFormat); cchMsg = vsnprintf(pszMsg, cbMsg, pszFormat, va); va_end(va); if (cchMsg < (int)cbMsg - 1 && cchMsg > 0) { #if !defined(KMK_BUILTIN_STANDALONE) && !defined(KWORKER) if (pCtx->pOut) output_write_text(pCtx->pOut, fIsErr, pszMsg, cchMsg); else #endif { fwrite(pszMsg, cchMsg, 1, fIsErr ? stderr : stdout); fflush(fIsErr ? stderr : stdout); } if (pszToFree) free(pszToFree); return; } /* double the buffer size and retry */ if (pszToFree) free(pszToFree); cbMsg *= 2; pszToFree = malloc(cbMsg); if (!pszToFree) { fprintf(stderr, "out of memory!\n"); return; } } } kbuild-3686/src/kmk/kmkbuiltin/mscfakes.h0000664000175000017500000001127115053010074020400 0ustar locutuslocutus/* $Id: mscfakes.h 3682 2025-08-12 23:34:19Z bird $ */ /** @file * Unix fakes for MSC. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ #ifndef ___mscfakes_h #define ___mscfakes_h #ifdef _MSC_VER #define timeval windows_timeval /* Include the config file (kmk's) so we don't need to duplicate stuff from it here. */ #include "config.h" #include #include #include #include #include #ifndef FAKES_NO_GETOPT_H # include "getopt.h" #endif #ifndef MSCFAKES_NO_WINDOWS_H # include #endif #include #include #include #include /* unlink for UCRT */ #include "nt/ntstat.h" #include "nt/ntunlink.h" /* redefines both unlink and rmdir */ #ifdef MSC_DO_64_BIT_IO # if _MSC_VER >= 1400 /* We want 64-bit file lengths here when possible. */ # define off_t __int64 # define lseek _lseeki64 # endif #endif #undef timeval #undef PATH_MAX /*#define PATH_MAX _MAX_PATH */ #define PATH_MAX 1024 #undef MAXPATHLEN #define MAXPATHLEN PATH_MAX #define EX_OK 0 #define EX_OSERR 1 #define EX_NOUSER 1 #define EX_USAGE 1 #define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 #define F_OK 0 #define X_OK 1 #define W_OK 2 #define R_OK 4 #define EFTYPE EINVAL #define _PATH_DEVNULL "/dev/null" #ifndef MAX # define MAX(a,b) ((a) >= (b) ? (a) : (b)) #endif typedef int mode_t; typedef unsigned short nlink_t; #if 0 /* found in config.h */ typedef unsigned short uid_t; typedef unsigned short gid_t; #endif typedef intptr_t ssize_t; typedef unsigned long u_long; typedef unsigned int u_int; typedef unsigned short u_short; #if _MSC_VER >= 1600 # include #else typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; #endif struct msc_timeval { __time64_t tv_sec; long tv_usec; }; #define timeval msc_timeval struct iovec { char *iov_base; size_t iov_len; }; typedef __int64 intmax_t; #if 0 /* found in config.h */ typedef unsigned __int64 uintmax_t; #endif #define chown(path, uid, gid) 0 /** @todo implement fchmod! */ char *dirname(char *path); #define fsync(fd) 0 #define fchown(fd,uid,gid) 0 #define fchmod(fd, mode) 0 /** @todo implement fchmod! */ #define geteuid() 0 #define getegid() 0 int lchmod(const char *path, mode_t mode); int msc_chmod(const char *path, mode_t mode); #define chmod msc_chmod #define lchown(path, uid, gid) chown(path, uid, gid) int link(const char *pszDst, const char *pszLink); int mkdir_msc(const char *path, mode_t mode); #define mkdir(path, mode) mkdir_msc(path, mode) #define mkfifo(path, mode) -1 #define mknod(path, mode, devno) -1 int mkstemp(char *temp); #define readlink(link, buf, size) -1 #define reallocf(old, size) realloc(old, size) /*int rmdir_msc(const char *path); #define rmdir(path) rmdir_msc(path) */ intmax_t strtoimax(const char *nptr, char **endptr, int base); uintmax_t strtoumax(const char *nptr, char **endptr, int base); #define strtoll(a,b,c) strtoimax(a,b,c) #define strtoull(a,b,c) strtoumax(a,b,c) int asprintf(char **strp, const char *fmt, ...); int vasprintf(char **strp, const char *fmt, va_list ap); #if _MSC_VER < 1400 int snprintf(char *buf, size_t size, const char *fmt, ...); #else #define snprintf _snprintf #endif int symlink(const char *pszDst, const char *pszLink); int utimes(const char *pszPath, const struct msc_timeval *paTimes); int lutimes(const char *pszPath, const struct msc_timeval *paTimes); ssize_t writev(int fd, const struct iovec *vector, int count); int gettimeofday(struct msc_timeval *pNow, void *pvIgnored); struct tm *localtime_r(const __time64_t *pNow, struct tm *pResult); __time64_t timegm(struct tm *pNow); #undef mktime #define mktime _mktime64 /* bird write ENOSPC hacks. */ #undef write #define write msc_write ssize_t msc_write(int fd, const void *pvSrc, size_t cbSrc); /* * MSC fake internals / helpers. */ int birdSetErrno(unsigned dwErr); #endif /* _MSC_VER */ #endif kbuild-3686/src/kmk/kmkbuiltin/setmode.c0000664000175000017500000002703115053010074020240 0ustar locutuslocutus/* $NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $ */ /* * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Dave Borman at Cray Research, Inc. * * 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. 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. */ /*#include */ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94"; #else __RCSID("$NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $"); #endif #endif /* LIBC_SCCS and not lint */ /*#include "namespace.h"*/ #include "config.h" #include #include #include #include #include #include #include #ifndef _MSC_VER #include #else #include "mscfakes.h" #endif #ifdef SETMODE_DEBUG #include #endif /*#ifdef __weak_alias __weak_alias(getmode,_getmode) __weak_alias(setmode,_setmode) #endif*/ #define SET_LEN 6 /* initial # of bitcmd struct to malloc */ #define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */ typedef struct bitcmd { char cmd; char cmd2; mode_t bits; } BITCMD; #define CMD2_CLR 0x01 #define CMD2_SET 0x02 #define CMD2_GBITS 0x04 #define CMD2_OBITS 0x08 #define CMD2_UBITS 0x10 static BITCMD *addcmd(BITCMD *, int, int, int, u_int); static void compress_mode(BITCMD *); #ifdef SETMODE_DEBUG static void dumpmode(BITCMD *); #endif #ifndef _DIAGASSERT # define _DIAGASSERT assert #endif #ifndef S_ISTXT # ifdef S_ISVTX # define S_ISTXT S_ISVTX # else # define S_ISTXT 0 # endif #endif /* !S_ISTXT */ extern mode_t g_fUMask; /* Initialize in main() and keep up to date. */ /* * Given the old mode and an array of bitcmd structures, apply the operations * described in the bitcmd structures to the old mode, and return the new mode. * Note that there is no '=' command; a strict assignment is just a '-' (clear * bits) followed by a '+' (set bits). */ mode_t bsd_getmode(bbox, omode) const void *bbox; mode_t omode; { const BITCMD *set; mode_t clrval, newmode, value; _DIAGASSERT(bbox != NULL); set = (const BITCMD *)bbox; newmode = omode; for (value = 0;; set++) switch(set->cmd) { /* * When copying the user, group or other bits around, we "know" * where the bits are in the mode so that we can do shifts to * copy them around. If we don't use shifts, it gets real * grundgy with lots of single bit checks and bit sets. */ case 'u': value = (newmode & S_IRWXU) >> 6; goto common; case 'g': value = (newmode & S_IRWXG) >> 3; goto common; case 'o': value = newmode & S_IRWXO; common: if (set->cmd2 & CMD2_CLR) { clrval = (set->cmd2 & CMD2_SET) ? S_IRWXO : value; if (set->cmd2 & CMD2_UBITS) newmode &= ~((clrval<<6) & set->bits); if (set->cmd2 & CMD2_GBITS) newmode &= ~((clrval<<3) & set->bits); if (set->cmd2 & CMD2_OBITS) newmode &= ~(clrval & set->bits); } if (set->cmd2 & CMD2_SET) { if (set->cmd2 & CMD2_UBITS) newmode |= (value<<6) & set->bits; if (set->cmd2 & CMD2_GBITS) newmode |= (value<<3) & set->bits; if (set->cmd2 & CMD2_OBITS) newmode |= value & set->bits; } break; case '+': newmode |= set->bits; break; case '-': newmode &= ~set->bits; break; case 'X': if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH)) newmode |= set->bits; break; case '\0': default: #ifdef SETMODE_DEBUG (void)printf("getmode:%04o -> %04o\n", omode, newmode); #endif return (newmode); } } #define ADDCMD(a, b, c, d) do { \ if (set >= endset) { \ BITCMD *newset; \ setlen += SET_LEN_INCR; \ newset = realloc(saveset, sizeof(BITCMD) * setlen); \ if (newset == NULL) { \ free(saveset); \ return (NULL); \ } \ set = newset + (set - saveset); \ saveset = newset; \ endset = newset + (setlen - 2); \ } \ set = addcmd(set, (a), (b), (c), (d)); \ } while (/*CONSTCOND*/0) #define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) void * bsd_setmode(p) const char *p; { int perm, who; char op, *ep; BITCMD *set, *saveset, *endset; #ifndef _MSC_VER sigset_t signset, sigoset; #endif mode_t mask; int equalopdone = 0; /* pacify gcc */ int permXbits, setlen; if (!*p) return (NULL); /* * Get a copy of the mask for the permissions that are mask relative. * Flip the bits, we want what's not set. Since it's possible that * the caller is opening files inside a signal handler, protect them * as best we can. */ #ifndef _MSC_VER sigfillset(&signset); (void)sigprocmask(SIG_BLOCK, &signset, &sigoset); #endif mask = g_fUMask; assert(mask == umask(g_fUMask)); mask = ~mask; #ifndef _MSC_VER (void)sigprocmask(SIG_SETMASK, &sigoset, NULL); #endif setlen = SET_LEN + 2; if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL) return (NULL); saveset = set; endset = set + (setlen - 2); /* * If an absolute number, get it and return; disallow non-octal digits * or illegal bits. */ if (isdigit((unsigned char)*p)) { perm = (mode_t)strtol(p, &ep, 8); if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) { free(saveset); return (NULL); } ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask); set->cmd = 0; return (saveset); } /* * Build list of structures to set/clear/copy bits as described by * each clause of the symbolic mode. */ for (;;) { /* First, find out which bits might be modified. */ for (who = 0;; ++p) { switch (*p) { case 'a': who |= STANDARD_BITS; break; case 'u': who |= S_ISUID|S_IRWXU; break; case 'g': who |= S_ISGID|S_IRWXG; break; case 'o': who |= S_IRWXO; break; default: goto getop; } } getop: if ((op = *p++) != '+' && op != '-' && op != '=') { free(saveset); return (NULL); } if (op == '=') equalopdone = 0; who &= ~S_ISTXT; for (perm = 0, permXbits = 0;; ++p) { switch (*p) { case 'r': perm |= S_IRUSR|S_IRGRP|S_IROTH; break; case 's': /* * If specific bits where requested and * only "other" bits ignore set-id. */ if (who == 0 || (who & ~S_IRWXO)) perm |= S_ISUID|S_ISGID; break; case 't': /* * If specific bits where requested and * only "other" bits ignore set-id. */ if (who == 0 || (who & ~S_IRWXO)) { who |= S_ISTXT; perm |= S_ISTXT; } break; case 'w': perm |= S_IWUSR|S_IWGRP|S_IWOTH; break; case 'X': permXbits = S_IXUSR|S_IXGRP|S_IXOTH; break; case 'x': perm |= S_IXUSR|S_IXGRP|S_IXOTH; break; case 'u': case 'g': case 'o': /* * When ever we hit 'u', 'g', or 'o', we have * to flush out any partial mode that we have, * and then do the copying of the mode bits. */ if (perm) { ADDCMD(op, who, perm, mask); perm = 0; } if (op == '=') equalopdone = 1; if (op == '+' && permXbits) { ADDCMD('X', who, permXbits, mask); permXbits = 0; } ADDCMD(*p, who, op, mask); break; default: /* * Add any permissions that we haven't already * done. */ if (perm || (op == '=' && !equalopdone)) { if (op == '=') equalopdone = 1; ADDCMD(op, who, perm, mask); perm = 0; } if (permXbits) { ADDCMD('X', who, permXbits, mask); permXbits = 0; } goto apply; } } apply: if (!*p) break; if (*p != ',') goto getop; ++p; } set->cmd = 0; #ifdef SETMODE_DEBUG (void)printf("Before compress_mode()\n"); dumpmode(saveset); #endif compress_mode(saveset); #ifdef SETMODE_DEBUG (void)printf("After compress_mode()\n"); dumpmode(saveset); #endif return (saveset); } static BITCMD * addcmd(set, op, who, oparg, mask) BITCMD *set; int oparg, who; int op; u_int mask; { _DIAGASSERT(set != NULL); switch (op) { case '=': set->cmd = '-'; set->bits = who ? who : STANDARD_BITS; set++; op = '+'; /* FALLTHROUGH */ case '+': case '-': case 'X': set->cmd = op; set->bits = (who ? (mode_t)who : mask) & oparg; break; case 'u': case 'g': case 'o': set->cmd = op; if (who) { set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) | ((who & S_IRGRP) ? CMD2_GBITS : 0) | ((who & S_IROTH) ? CMD2_OBITS : 0); set->bits = (mode_t)~0; } else { set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS; set->bits = mask; } if (oparg == '+') set->cmd2 |= CMD2_SET; else if (oparg == '-') set->cmd2 |= CMD2_CLR; else if (oparg == '=') set->cmd2 |= CMD2_SET|CMD2_CLR; break; } return (set + 1); } #ifdef SETMODE_DEBUG static void dumpmode(set) BITCMD *set; { _DIAGASSERT(set != NULL); for (; set->cmd; ++set) (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n", set->cmd, set->bits, set->cmd2 ? " cmd2:" : "", set->cmd2 & CMD2_CLR ? " CLR" : "", set->cmd2 & CMD2_SET ? " SET" : "", set->cmd2 & CMD2_UBITS ? " UBITS" : "", set->cmd2 & CMD2_GBITS ? " GBITS" : "", set->cmd2 & CMD2_OBITS ? " OBITS" : ""); } #endif /* * Given an array of bitcmd structures, compress by compacting consecutive * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u', * 'g' and 'o' commands continue to be separate. They could probably be * compacted, but it's not worth the effort. */ static void compress_mode(set) BITCMD *set; { BITCMD *nset; int setbits, clrbits, Xbits, op; _DIAGASSERT(set != NULL); for (nset = set;;) { /* Copy over any 'u', 'g' and 'o' commands. */ while ((op = nset->cmd) != '+' && op != '-' && op != 'X') { *set++ = *nset++; if (!op) return; } for (setbits = clrbits = Xbits = 0;; nset++) { if ((op = nset->cmd) == '-') { clrbits |= nset->bits; setbits &= ~nset->bits; Xbits &= ~nset->bits; } else if (op == '+') { setbits |= nset->bits; clrbits &= ~nset->bits; Xbits &= ~nset->bits; } else if (op == 'X') Xbits |= nset->bits & ~setbits; else break; } if (clrbits) { set->cmd = '-'; set->cmd2 = 0; set->bits = clrbits; set++; } if (setbits) { set->cmd = '+'; set->cmd2 = 0; set->bits = setbits; set++; } if (Xbits) { set->cmd = 'X'; set->cmd2 = 0; set->bits = Xbits; set++; } } } kbuild-3686/src/kmk/kmkbuiltin/kSubmit.c0000664000175000017500000022671615053010074020231 0ustar locutuslocutus/* $Id: kSubmit.c 3642 2024-11-02 23:40:35Z bird $ */ /** @file * kMk Builtin command - submit job to a kWorker. */ /* * Copyright (c) 2007-2016 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #ifdef __APPLE__ # define _POSIX_C_SOURCE 1 /* 10.4 sdk and unsetenv */ #endif #include "makeint.h" #include "job.h" #include "variable.h" #include "pathstuff.h" #include #include #include #include #include #ifdef HAVE_ALLOCA_H # include #endif #if defined(_MSC_VER) # include # include # include # include #else # include #endif #ifdef KBUILD_OS_WINDOWS # ifndef CONFIG_NEW_WIN_CHILDREN # include "sub_proc.h" # else # include "../w32/winchildren.h" # endif # include "nt/nt_child_inject_standard_handles.h" #endif #include "kbuild.h" #include "kmkbuiltin.h" #include "err.h" /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ /** Hashes a pid. */ #define KWORKER_PID_HASH(a_pid) ((size_t)(a_pid) % 61) #define TUPLE(a_sz) a_sz, sizeof(a_sz) - 1 /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ typedef struct WORKERINSTANCE *PWORKERINSTANCE; typedef struct WORKERINSTANCE { /** Pointer to the next worker instance. */ PWORKERINSTANCE pNext; /** Pointer to the previous worker instance. */ PWORKERINSTANCE pPrev; /** Pointer to the next worker with the same pid hash slot. */ PWORKERINSTANCE pNextPidHash; /** 32 or 64. */ unsigned cBits; /** The process ID of the kWorker process. */ pid_t pid; union { struct { /** The exit code. */ int32_t rcExit; /** Set to 1 if the worker is exiting. */ uint8_t bWorkerExiting; uint8_t abUnused[3]; } s; uint8_t ab[8]; } Result; /** Number of result bytes read alread. */ size_t cbResultRead; #ifdef KBUILD_OS_WINDOWS /** The process handle. */ HANDLE hProcess; /** The bi-directional pipe we use to talk to the kWorker process. */ HANDLE hPipe; /** For overlapped read (have valid event semaphore). */ OVERLAPPED OverlappedRead; # ifdef CONFIG_NEW_WIN_CHILDREN /** Standard output catcher (reused). */ PWINCCWPIPE pStdOut; /** Standard error catcher (reused). */ PWINCCWPIPE pStdErr; # endif #else /** The socket descriptor we use to talk to the kWorker process. */ int fdSocket; #endif /** --debug-dump-history-on-failure. */ int fDebugDumpHistoryOnFailure; /** Current history index (must mod with aHistory element count). */ unsigned iHistory; /** History. */ struct { /** Pointer to the message, NULL if none. */ void *pvMsg; /** The message size, zero if not present. */ size_t cbMsg; } aHistory[4]; /** What it's busy with. NULL if idle. */ struct child *pBusyWith; } WORKERINSTANCE; typedef struct WORKERLIST { /** The head of the list. NULL if empty. */ PWORKERINSTANCE pHead; /** The tail of the list. NULL if empty. */ PWORKERINSTANCE pTail; /** Number of list entries. */ size_t cEntries; } WORKERLIST; typedef WORKERLIST *PWORKERLIST; /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ /** List of idle worker.*/ static WORKERLIST g_IdleList; /** List of busy workers. */ static WORKERLIST g_BusyList; /** PID hash table for the workers. * @sa KWORKER_PID_HASH() */ static PWORKERINSTANCE g_apPidHash[61]; #ifdef KBUILD_OS_WINDOWS /** For naming the pipes. * Also indicates how many worker instances we've spawned. */ static unsigned g_uWorkerSeqNo = 0; #endif /** Set if we've registred the atexit handler already. */ static int g_fAtExitRegistered = 0; /** @var g_cArchBits * The bit count of the architecture this binary is compiled for. */ /** @var g_szArch * The name of the architecture this binary is compiled for. */ /** @var g_cArchBits * The bit count of the alternative architecture. */ /** @var g_szAltArch * The name of the alternative architecture. */ #if defined(KBUILD_ARCH_AMD64) static unsigned g_cArchBits = 64; static char const g_szArch[] = "amd64"; static unsigned g_cAltArchBits = 32; static char const g_szAltArch[] = "x86"; #elif defined(KBUILD_ARCH_X86) static unsigned g_cArchBits = 32; static char const g_szArch[] = "x86"; static unsigned g_cAltArchBits = 64; static char const g_szAltArch[] = "amd64"; #elif defined(KBUILD_ARCH_ARM64) static unsigned g_cArchBits = 64; static char const g_szArch[] = "arm64"; static unsigned g_cAltArchBits = 64; static char const g_szAltArch[] = "arm64"; /* not used */ #else # error "Port me!" #endif #ifdef KBUILD_OS_WINDOWS /** The processor group allocator state. */ static MKWINCHILDCPUGROUPALLOCSTATE g_SubmitProcessorGroupAllocator; # if K_ARCH_BITS == 64 /** The processor group allocator state for 32-bit processes. */ static MKWINCHILDCPUGROUPALLOCSTATE g_SubmitProcessorGroupAllocator32; # endif #endif #ifdef KBUILD_OS_WINDOWS /** Pointer to kernel32!SetThreadGroupAffinity. */ static BOOL (WINAPI *g_pfnSetThreadGroupAffinity)(HANDLE, const GROUP_AFFINITY*, GROUP_AFFINITY *); #endif /** * Unlinks a worker instance from a list. * * @param pList The list. * @param pWorker The worker. */ static void kSubmitListUnlink(PWORKERLIST pList, PWORKERINSTANCE pWorker) { PWORKERINSTANCE pNext = pWorker->pNext; PWORKERINSTANCE pPrev = pWorker->pPrev; if (pNext) { assert(pNext->pPrev == pWorker); pNext->pPrev = pPrev; } else { assert(pList->pTail == pWorker); pList->pTail = pPrev; } if (pPrev) { assert(pPrev->pNext == pWorker); pPrev->pNext = pNext; } else { assert(pList->pHead == pWorker); pList->pHead = pNext; } assert(!pList->pHead || pList->pHead->pPrev == NULL); assert(!pList->pTail || pList->pTail->pNext == NULL); assert(pList->cEntries > 0); pList->cEntries--; pWorker->pNext = NULL; pWorker->pPrev = NULL; } /** * Appends a worker instance to the tail of a list. * * @param pList The list. * @param pWorker The worker. */ static void kSubmitListAppend(PWORKERLIST pList, PWORKERINSTANCE pWorker) { PWORKERINSTANCE pTail = pList->pTail; assert(pTail != pWorker); assert(pList->pHead != pWorker); pWorker->pNext = NULL; pWorker->pPrev = pTail; if (pTail != NULL) { assert(pTail->pNext == NULL); pTail->pNext = pWorker; } else { assert(pList->pHead == NULL); pList->pHead = pWorker; } pList->pTail = pWorker; assert(pList->pHead->pPrev == NULL); assert(pList->pTail->pNext == NULL); pList->cEntries++; } /** * Remove worker from the process ID hash table. * * @param pWorker The worker. */ static void kSubmitPidHashRemove(PWORKERINSTANCE pWorker) { size_t idxHash = KWORKER_PID_HASH(pWorker->pid); if (g_apPidHash[idxHash] == pWorker) g_apPidHash[idxHash] = pWorker->pNext; else { PWORKERINSTANCE pPrev = g_apPidHash[idxHash]; while (pPrev && pPrev->pNext != pWorker) pPrev = pPrev->pNext; assert(pPrev != NULL); if (pPrev) pPrev->pNext = pWorker->pNext; } pWorker->pid = -1; } /** * Looks up a worker by its process ID. * * @returns Pointer to the worker instance if found. NULL if not. * @param pid The process ID of the worker. */ static PWORKERINSTANCE kSubmitFindWorkerByPid(pid_t pid) { PWORKERINSTANCE pWorker = g_apPidHash[KWORKER_PID_HASH(pid)]; while (pWorker && pWorker->pid != pid) pWorker = pWorker->pNextPidHash; return pWorker; } /** * Calcs the path to the kWorker binary for the worker. * * @returns * @param pCtx The command execution context. * @param pWorker The worker (for its bitcount). * @param pszExecutable The output buffer. * @param cbExecutable The output buffer size. */ static int kSubmitCalcExecutablePath(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, char *pszExecutable, size_t cbExecutable) { #if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2) static const char s_szWorkerName[] = "kWorker.exe"; #else static const char s_szWorkerName[] = "kWorker"; #endif const char *pszBinPath = get_kbuild_bin_path(); size_t const cchBinPath = strlen(pszBinPath); size_t cchExecutable; if ( pWorker->cBits == g_cArchBits ? cchBinPath + 1 + sizeof(s_szWorkerName) <= cbExecutable : cchBinPath + 1 - sizeof(g_szArch) + sizeof(g_szAltArch) + sizeof(s_szWorkerName) <= cbExecutable ) { memcpy(pszExecutable, pszBinPath, cchBinPath); cchExecutable = cchBinPath; /* Replace the arch bin directory extension with the alternative one if requested. */ if (pWorker->cBits != g_cArchBits) { if ( cchBinPath < sizeof(g_szArch) || memcmp(&pszExecutable[cchBinPath - sizeof(g_szArch) + 1], g_szArch, sizeof(g_szArch) - 1) != 0) return errx(pCtx, 1, "KBUILD_BIN_PATH does not end with main architecture (%s) as expected: %s", pszBinPath, g_szArch); cchExecutable -= sizeof(g_szArch) - 1; memcpy(&pszExecutable[cchExecutable], g_szAltArch, sizeof(g_szAltArch) - 1); cchExecutable += sizeof(g_szAltArch) - 1; } /* Append a slash and the worker name. */ pszExecutable[cchExecutable++] = '/'; memcpy(&pszExecutable[cchExecutable], s_szWorkerName, sizeof(s_szWorkerName)); return 0; } return errx(pCtx, 1, "KBUILD_BIN_PATH is too long"); } #ifdef KBUILD_OS_WINDOWS /** * Calcs the UTF-16 path to the kWorker binary for the worker. * * @returns * @param pCtx The command execution context. * @param pWorker The worker (for its bitcount). * @param pwszExecutable The output buffer. * @param cwcExecutable The output buffer size. */ static int kSubmitCalcExecutablePathW(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, wchar_t *pwszExecutable, size_t cwcExecutable) { char szExecutable[MAX_PATH]; int rc = kSubmitCalcExecutablePath(pCtx, pWorker, szExecutable, sizeof(szExecutable)); if (rc == 0) { int cwc = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, szExecutable, strlen(szExecutable) + 1, pwszExecutable, cwcExecutable); if (cwc > 0) return 0; return errx(pCtx, 1, "MultiByteToWideChar failed on '%s': %u", szExecutable, GetLastError()); } return rc; } #endif /** * Creates a new worker process. * * @returns 0 on success, non-zero value on failure. * @param pCtx The command execution context. * @param pWorker The worker structure. Caller does the linking * (as we might be reusing an existing worker * instance because a worker shut itself down due * to high resource leak level). * @param cVerbosity The verbosity level. */ static int kSubmitSpawnWorker(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, int cVerbosity) { int rc; #ifdef KBUILD_OS_WINDOWS wchar_t wszExecutable[MAX_PATH]; #else PATH_VAR(szExecutable); #endif /* * Get the output path so it can be passed on as a volatile. */ const char *pszVarVolatile; struct variable *pVarVolatile = lookup_variable(TUPLE("PATH_OUT")); if (pVarVolatile) pszVarVolatile = "PATH_OUT"; else { pVarVolatile = lookup_variable(TUPLE("PATH_OUT_BASE")); if (pVarVolatile) pszVarVolatile = "PATH_OUT_BASE"; else warn(pCtx, "Neither PATH_OUT_BASE nor PATH_OUT was found."); } if (pVarVolatile && strchr(pVarVolatile->value, '"')) return errx(pCtx, -1, "%s contains double quotes.", pszVarVolatile); if (pVarVolatile && strlen(pVarVolatile->value) >= GET_PATH_MAX) return errx(pCtx, -1, "%s is too long (max %u)", pszVarVolatile, GET_PATH_MAX); /* * Construct the executable path. */ #ifdef KBUILD_OS_WINDOWS rc = kSubmitCalcExecutablePathW(pCtx, pWorker, wszExecutable, K_ELEMENTS(wszExecutable)); #else rc = kSubmitCalcExecutablePath(pCtx, pWorker, szExecutable, GET_PATH_MAX); #endif if (rc == 0) { #ifdef KBUILD_OS_WINDOWS static DWORD s_fDenyRemoteClients = ~(DWORD)0; wchar_t wszPipeName[128]; HANDLE hWorkerPipe; int iProcessorGroup; # if K_ARCH_BITS == 64 /** @todo make it return -1 if not applicable (e.g only one group). */ if (pWorker->cBits != 32) iProcessorGroup = MkWinChildAllocateCpuGroup(&g_SubmitProcessorGroupAllocator); else iProcessorGroup = MkWinChildAllocateCpuGroup(&g_SubmitProcessorGroupAllocator32); # else iProcessorGroup = MkWinChildAllocateCpuGroup(&g_SubmitProcessorGroupAllocator); # endif /* * Create the bi-directional pipe with overlapping I/O enabled. */ if (s_fDenyRemoteClients == ~(DWORD)0) s_fDenyRemoteClients = GetVersion() >= 0x60000 ? PIPE_REJECT_REMOTE_CLIENTS : 0; _snwprintf(wszPipeName, sizeof(wszPipeName), L"\\\\.\\pipe\\kmk-%u-kWorker-%u-%u", GetCurrentProcessId(), g_uWorkerSeqNo++, GetTickCount()); hWorkerPipe = CreateNamedPipeW(wszPipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE /* win2k sp2+ */, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | s_fDenyRemoteClients, 1 /* cMaxInstances */, 64 /*cbOutBuffer*/, 65536 /*cbInBuffer*/, 0 /*cMsDefaultTimeout -> 50ms*/, NULL /* pSecAttr - no inherit */); if (hWorkerPipe != INVALID_HANDLE_VALUE) { pWorker->hPipe = CreateFileW(wszPipeName, GENERIC_READ | GENERIC_WRITE, 0 /* dwShareMode - no sharing */, NULL /*pSecAttr - no inherit */, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL /*hTemplate*/); if (pWorker->hPipe != INVALID_HANDLE_VALUE) { pWorker->OverlappedRead.hEvent = CreateEventW(NULL /*pSecAttrs - no inherit*/, TRUE /*bManualReset*/, TRUE /*bInitialState*/, NULL /*pwszName*/); if (pWorker->OverlappedRead.hEvent != NULL) { extern int process_priority; /* main.c */ wchar_t wszCommandLine[MAX_PATH * 3 + 32]; wchar_t *pwszDst = wszCommandLine; size_t cwcDst = K_ELEMENTS(wszCommandLine); int cwc; DWORD fFlags; STARTUPINFOW StartupInfo; PROCESS_INFORMATION ProcInfo = { NULL, NULL, 0, 0 }; /* * Compose the command line. */ cwc = _snwprintf(pwszDst, cwcDst, L"\"%s\" ", wszExecutable); assert(cwc > 0 && cwc < cwcDst); pwszDst += cwc; cwcDst -= cwc; if (pVarVolatile && *pVarVolatile->value) { char chEnd = strchr(pVarVolatile->value, '\0')[-1]; if (chEnd == '\\') cwc = _snwprintf(pwszDst, cwcDst, L" --volatile \"%S.\"", pVarVolatile->value); else cwc = _snwprintf(pwszDst, cwcDst, L" --volatile \"%S\"", pVarVolatile->value); assert(cwc > 0 && cwc < cwcDst); pwszDst += cwc; cwcDst -= cwc; } if (iProcessorGroup >= 0) { cwc = _snwprintf(pwszDst, cwcDst, L" --group %d", iProcessorGroup); assert(cwc > 0 && cwc < cwcDst); pwszDst += cwc; cwcDst -= cwc; } *pwszDst = '\0'; /* * Fill in the startup information. */ memset(&StartupInfo, 0, sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); GetStartupInfoW(&StartupInfo); StartupInfo.dwFlags &= ~STARTF_USESTDHANDLES; StartupInfo.lpReserved2 = NULL; StartupInfo.cbReserved2 = 0; /* * Flags and such. */ fFlags = CREATE_SUSPENDED; switch (process_priority) { case 1: fFlags |= CREATE_SUSPENDED | IDLE_PRIORITY_CLASS; break; case 2: fFlags |= CREATE_SUSPENDED | BELOW_NORMAL_PRIORITY_CLASS; break; case 3: fFlags |= CREATE_SUSPENDED | NORMAL_PRIORITY_CLASS; break; case 4: fFlags |= CREATE_SUSPENDED | HIGH_PRIORITY_CLASS; break; case 5: fFlags |= CREATE_SUSPENDED | REALTIME_PRIORITY_CLASS; break; } /* * Create the worker process. */ if (CreateProcessW(wszExecutable, wszCommandLine, NULL /*pProcSecAttr*/, NULL /*pThreadSecAttr*/, FALSE /*fInheritHandles*/, fFlags, NULL /*pwszzEnvironment*/, NULL /*pwszCwd*/, &StartupInfo, &ProcInfo)) { char szErrMsg[256]; BOOL afReplace[3] = { TRUE, FALSE, FALSE }; HANDLE ahReplace[3] = { hWorkerPipe, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; if (pWorker->pStdOut) { afReplace[1] = TRUE; afReplace[2] = TRUE; ahReplace[1] = pWorker->pStdOut->hPipeChild; ahReplace[2] = pWorker->pStdErr->hPipeChild; } rc = nt_child_inject_standard_handles(ProcInfo.hProcess, afReplace, ahReplace, szErrMsg, sizeof(szErrMsg)); if (rc == 0) { BOOL fRet; switch (process_priority) { case 1: fRet = SetThreadPriority(ProcInfo.hThread, THREAD_PRIORITY_IDLE); break; case 2: fRet = SetThreadPriority(ProcInfo.hThread, THREAD_PRIORITY_BELOW_NORMAL); break; case 3: fRet = SetThreadPriority(ProcInfo.hThread, THREAD_PRIORITY_NORMAL); break; case 4: fRet = SetThreadPriority(ProcInfo.hThread, THREAD_PRIORITY_HIGHEST); break; case 5: fRet = SetThreadPriority(ProcInfo.hThread, THREAD_PRIORITY_TIME_CRITICAL); break; default: fRet = TRUE; } if (!fRet) warnx(pCtx, "warning: failed to set kWorker thread priority: %u\n", GetLastError()); if (iProcessorGroup >= 0 && g_pfnSetThreadGroupAffinity) { GROUP_AFFINITY OldAff = { 0, 0, 0, 0, 0 }; GROUP_AFFINITY NewAff = { 0 /* == all active apparently */, (WORD)iProcessorGroup, 0, 0, 0 }; if (!g_pfnSetThreadGroupAffinity(ProcInfo.hThread, &NewAff, &OldAff)) warnx(pCtx, "warning: Failed to set processor group to %d: %u\n", iProcessorGroup, GetLastError()); } /* * Now, we just need to resume the thread. */ if (ResumeThread(ProcInfo.hThread)) { CloseHandle(hWorkerPipe); CloseHandle(ProcInfo.hThread); pWorker->pid = ProcInfo.dwProcessId; pWorker->hProcess = ProcInfo.hProcess; if (cVerbosity > 0) warnx(pCtx, "created %d bit worker %d\n", pWorker->cBits, pWorker->pid); return 0; } /* * Failed, bail out. */ rc = errx(pCtx, -3, "ResumeThread failed: %u", GetLastError()); } else rc = errx(pCtx, -3, "%s", szErrMsg); TerminateProcess(ProcInfo.hProcess, 1234); CloseHandle(ProcInfo.hThread); CloseHandle(ProcInfo.hProcess); } else rc = errx(pCtx, -2, "CreateProcessW failed: %u (exe=%S cmdline=%S)", GetLastError(), wszExecutable, wszCommandLine); CloseHandle(pWorker->OverlappedRead.hEvent); pWorker->OverlappedRead.hEvent = INVALID_HANDLE_VALUE; } else rc = errx(pCtx, -1, "CreateEventW failed: %u", GetLastError()); CloseHandle(pWorker->hPipe); pWorker->hPipe = INVALID_HANDLE_VALUE; } else rc = errx(pCtx, -1, "Opening named pipe failed: %u", GetLastError()); CloseHandle(hWorkerPipe); } else rc = errx(pCtx, -1, "CreateNamedPipeW failed: %u", GetLastError()); #else /* * Create a socket pair. */ int aiPair[2] = { -1, -1 }; if (socketpair(AF_LOCAL, SOCK_STREAM, 0, aiPair) == 0) { pWorker->fdSocket = aiPair[1]; rc = -1; } else rc = err(pCtx, -1, "socketpair"); #endif } else rc = errx(pCtx, -1, "KBUILD_BIN_PATH is too long"); return rc; } /** * Selects an idle worker or spawns a new one. * * @returns Pointer to the selected worker instance. NULL on error. * @param pCtx The command execution context. * @param pWorker The idle worker instance to respawn. * On failure this will be freed! * @param cBitsWorker The worker bitness - 64 or 32. */ static int kSubmitRespawnWorker(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, int cVerbosity) { /* * Clean up after the old worker. */ #ifdef KBUILD_OS_WINDOWS DWORD rcWait; /* Close the pipe handle first, breaking the pipe in case it's not already busted up. Close the event semaphore too before waiting for the process. */ if (pWorker->hPipe != INVALID_HANDLE_VALUE) { if (!CloseHandle(pWorker->hPipe)) warnx(pCtx, "CloseHandle(pWorker->hPipe): %u", GetLastError()); pWorker->hPipe = INVALID_HANDLE_VALUE; } if (!CloseHandle(pWorker->OverlappedRead.hEvent)) warnx(pCtx, "CloseHandle(pWorker->OverlappedRead.hEvent): %u", GetLastError()); pWorker->OverlappedRead.hEvent = INVALID_HANDLE_VALUE; if (pWorker->pStdOut) MkWinChildcareWorkerDrainPipes(NULL, pWorker->pStdOut, pWorker->pStdErr); /* It's probably shutdown already, if not give it 10 milliseconds before we terminate it forcefully. */ rcWait = WaitForSingleObject(pWorker->hProcess, 10); if (rcWait != WAIT_OBJECT_0) { BOOL fRc = TerminateProcess(pWorker->hProcess, 127); if (pWorker->pStdOut) MkWinChildcareWorkerDrainPipes(NULL, pWorker->pStdOut, pWorker->pStdErr); rcWait = WaitForSingleObject(pWorker->hProcess, 100); if (rcWait != WAIT_OBJECT_0) warnx(pCtx, "WaitForSingleObject returns %u (and TerminateProcess %d)", rcWait, fRc); } if (pWorker->pStdOut) MkWinChildcareWorkerDrainPipes(NULL, pWorker->pStdOut, pWorker->pStdErr); if (!CloseHandle(pWorker->hProcess)) warnx(pCtx, "CloseHandle(pWorker->hProcess): %u", GetLastError()); pWorker->hProcess = INVALID_HANDLE_VALUE; #else pid_t pidWait; int rc; if (pWorker->fdSocket != -1) { if (close(pWorker->fdSocket) != 0) warn(pCtx, "close(pWorker->fdSocket)"); pWorker->fdSocket = -1; } kill(pWorker->pid, SIGTERM); pidWait = waitpid(pWorker->pid, &rc, 0); if (pidWait != pWorker->pid) warn(pCtx, "waitpid(pWorker->pid,,0)"); #endif /* * Unlink it from the hash table. */ kSubmitPidHashRemove(pWorker); /* * Respawn it. */ if (kSubmitSpawnWorker(pCtx, pWorker, cVerbosity) == 0) { /* * Insert it into the process ID hash table and idle list. */ size_t idxHash = KWORKER_PID_HASH(pWorker->pid); pWorker->pNextPidHash = g_apPidHash[idxHash]; g_apPidHash[idxHash] = pWorker; return 0; } kSubmitListUnlink(&g_IdleList, pWorker); free(pWorker); return -1; } /** * Selects an idle worker or spawns a new one. * * @returns Pointer to the selected worker instance. NULL on error. * @param cBitsWorker The worker bitness - 64 or 32. */ static PWORKERINSTANCE kSubmitSelectWorkSpawnNewIfNecessary(PKMKBUILTINCTX pCtx, unsigned cBitsWorker, int cVerbosity) { /* * Lookup up an idle worker. */ PWORKERINSTANCE pWorker = g_IdleList.pHead; while (pWorker) { if (pWorker->cBits == cBitsWorker) return pWorker; pWorker = pWorker->pNext; } /* * Create a new worker instance. */ pWorker = (PWORKERINSTANCE)xcalloc(sizeof(*pWorker)); pWorker->cBits = cBitsWorker; #if defined(CONFIG_NEW_WIN_CHILDREN) && defined(KBUILD_OS_WINDOWS) if (output_sync != OUTPUT_SYNC_NONE) { pWorker->pStdOut = MkWinChildcareCreateWorkerPipe(1, g_uWorkerSeqNo << 1); pWorker->pStdErr = MkWinChildcareCreateWorkerPipe(2, g_uWorkerSeqNo << 1); } if ( output_sync == OUTPUT_SYNC_NONE || ( pWorker->pStdOut != NULL && pWorker->pStdErr != NULL)) #endif { if (kSubmitSpawnWorker(pCtx, pWorker, cVerbosity) == 0) { /* * Insert it into the process ID hash table and idle list. */ size_t idxHash = KWORKER_PID_HASH(pWorker->pid); pWorker->pNextPidHash = g_apPidHash[idxHash]; g_apPidHash[idxHash] = pWorker; kSubmitListAppend(&g_IdleList, pWorker); return pWorker; } } #if defined(CONFIG_NEW_WIN_CHILDREN) && defined(KBUILD_OS_WINDOWS) if (pWorker->pStdErr) MkWinChildcareDeleteWorkerPipe(pWorker->pStdErr); if (pWorker->pStdOut) MkWinChildcareDeleteWorkerPipe(pWorker->pStdOut); #endif free(pWorker); return NULL; } /** * Composes a JOB mesage for a worker. * * @returns Pointer to the message. * @param pszExecutable The executable to run. * @param papszArgs The argument vector. * @param papszEnvVars The environment vector. * @param pszCwd The current directory. * @param fWatcomBrainDamage The wcc/wcc386 workaround. * @param fNoPchCaching Whether to disable precompiled header caching. * @param pszSpecialEnv Environment variable (name=value) subject to * special expansion in kWorker. NULL if none. * @param papszPostCmdArgs The post command and it's arguments. * @param cPostCmdArgs Number of post command argument, including the * command. Zero if no post command scheduled. * @param pcbMsg Where to return the message length. */ static void *kSubmitComposeJobMessage(const char *pszExecutable, char **papszArgs, char **papszEnvVars, const char *pszCwd, int fWatcomBrainDamage, int fNoPchCaching, const char *pszSpecialEnv, char **papszPostCmdArgs, uint32_t cPostCmdArgs, uint32_t *pcbMsg) { size_t cbTmp; size_t cbSpecialEnv; uint32_t i; uint32_t cbMsg; uint32_t cArgs; uint32_t cEnvVars; uint8_t *pbMsg; uint8_t *pbCursor; /* * Adjust input. */ if (!pszExecutable) pszExecutable = papszArgs[0]; /* * Calculate the message length first. */ cbMsg = sizeof(cbMsg); cbMsg += sizeof("JOB"); cbMsg += strlen(pszExecutable) + 1; cbMsg += strlen(pszCwd) + 1; cbMsg += sizeof(cArgs); for (i = 0; papszArgs[i] != NULL; i++) cbMsg += 1 + strlen(papszArgs[i]) + 1; cArgs = i; cbMsg += sizeof(cArgs); for (i = 0; papszEnvVars[i] != NULL; i++) cbMsg += strlen(papszEnvVars[i]) + 1; cEnvVars = i; cbMsg += 1; /* fWatcomBrainDamage */ cbMsg += 1; /* fNoPchCaching */ cbSpecialEnv = pszSpecialEnv ? strchr(pszSpecialEnv, '=') - pszSpecialEnv : 0; cbMsg += cbSpecialEnv + 1; cbMsg += sizeof(cPostCmdArgs); for (i = 0; i < cPostCmdArgs; i++) cbMsg += strlen(papszPostCmdArgs[i]) + 1; /* * Compose the message. */ pbMsg = pbCursor = xmalloc(cbMsg); /* header */ memcpy(pbCursor, &cbMsg, sizeof(cbMsg)); pbCursor += sizeof(cbMsg); memcpy(pbCursor, "JOB", sizeof("JOB")); pbCursor += sizeof("JOB"); /* executable. */ cbTmp = strlen(pszExecutable) + 1; memcpy(pbCursor, pszExecutable, cbTmp); pbCursor += cbTmp; /* cwd */ cbTmp = strlen(pszCwd) + 1; memcpy(pbCursor, pszCwd, cbTmp); pbCursor += cbTmp; /* arguments */ memcpy(pbCursor, &cArgs, sizeof(cArgs)); pbCursor += sizeof(cArgs); for (i = 0; papszArgs[i] != NULL; i++) { *pbCursor++ = 0; /* Argument expansion flags (MSC, EMX). */ cbTmp = strlen(papszArgs[i]) + 1; memcpy(pbCursor, papszArgs[i], cbTmp); pbCursor += cbTmp; } assert(i == cArgs); /* environment */ memcpy(pbCursor, &cEnvVars, sizeof(cEnvVars)); pbCursor += sizeof(cEnvVars); for (i = 0; papszEnvVars[i] != NULL; i++) { cbTmp = strlen(papszEnvVars[i]) + 1; memcpy(pbCursor, papszEnvVars[i], cbTmp); pbCursor += cbTmp; } assert(i == cEnvVars); /* flags */ *pbCursor++ = fWatcomBrainDamage != 0; *pbCursor++ = fNoPchCaching != 0; /* Special environment variable name. */ memcpy(pbCursor, pszSpecialEnv, cbSpecialEnv); pbCursor += cbSpecialEnv; *pbCursor++ = '\0'; /* post command */ memcpy(pbCursor, &cPostCmdArgs, sizeof(cPostCmdArgs)); pbCursor += sizeof(cPostCmdArgs); for (i = 0; i < cPostCmdArgs; i++) { cbTmp = strlen(papszPostCmdArgs[i]) + 1; memcpy(pbCursor, papszPostCmdArgs[i], cbTmp); pbCursor += cbTmp; } assert(i == cPostCmdArgs); assert(pbCursor - pbMsg == (size_t)cbMsg); /* * Done. */ *pcbMsg = cbMsg; return pbMsg; } /** * Sends the job message to the given worker, respawning the worker if * necessary. * * @returns 0 on success, non-zero on failure. * * @param pCtx The command execution context. * @param pWorker The work to send the request to. The worker is * on the idle list. * @param pvMsg The message to send. * @param cbMsg The size of the message. * @param fNoRespawning Set if * @param cVerbosity The verbosity level. */ static int kSubmitSendJobMessage(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, void const *pvMsg, uint32_t cbMsg, int fNoRespawning, int cVerbosity) { int cRetries; /* * Respawn the worker if it stopped by itself and we closed the pipe already. */ #ifdef KBUILD_OS_WINDOWS if (pWorker->hPipe == INVALID_HANDLE_VALUE) #else if (pWorker->fdSocket == -1) #endif { if (!fNoRespawning) { if (cVerbosity > 0) warnx(pCtx, "Respawning worker (#1)...\n"); if (kSubmitRespawnWorker(pCtx, pWorker, cVerbosity) != 0) return 2; } } /* * Restart-on-broken-pipe loop. Necessary? */ for (cRetries = !fNoRespawning ? 1 : 0; ; cRetries--) { /* * Try write the message. */ uint32_t cbLeft = cbMsg; uint8_t const *pbLeft = (uint8_t const *)pvMsg; #ifdef KBUILD_OS_WINDOWS DWORD dwErr; DWORD cbWritten; while (WriteFile(pWorker->hPipe, pbLeft, cbLeft, &cbWritten, NULL /*pOverlapped*/)) { assert(cbWritten <= cbLeft); cbLeft -= cbWritten; if (!cbLeft) return 0; /* This scenario shouldn't really ever happen. But just in case... */ pbLeft += cbWritten; } dwErr = GetLastError(); if ( ( dwErr != ERROR_BROKEN_PIPE && dwErr != ERROR_NO_DATA) || cRetries <= 0) return errx(pCtx, 1, "Error writing to worker: %u", dwErr); #else ssize_t cbWritten while ((cbWritten = write(pWorker->fdSocket, pbLeft, cbLeft)) >= 0) { assert(cbWritten <= cbLeft); cbLeft -= cbWritten; if (!cbLeft) return 0; pbLeft += cbWritten; } if ( ( errno != EPIPE && errno != ENOTCONN && errno != ECONNRESET)) || cRetries <= 0) return err(pCtx, 1, "Error writing to worker"); # error "later" #endif /* * Broken connection. Try respawn the worker. */ if (cVerbosity > 0) warnx(pCtx, "Respawning worker (#2)...\n"); if (kSubmitRespawnWorker(pCtx, pWorker, cVerbosity) != 0) return 2; } } /** * Closes the connection on a worker that said it is going to exit now. * * This is a way of dealing with imperfect resource management in the worker, it * will monitor it a little and trigger a respawn when it looks bad. * * This function just closes the pipe / socket connection to the worker. The * kSubmitSendJobMessage function will see this a trigger a respawn the next * time the worker is engaged. This will usually mean there's a little delay in * which the process can terminate without us having to actively wait for it. * * @param pCtx The command execution context. * @param pWorker The worker instance. */ static void kSubmitCloseConnectOnExitingWorker(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker) { #ifdef KBUILD_OS_WINDOWS if (!CloseHandle(pWorker->hPipe)) warnx(pCtx, "CloseHandle(pWorker->hPipe): %u", GetLastError()); pWorker->hPipe = INVALID_HANDLE_VALUE; #else if (close(pWorker->fdSocket) != 0) warn(pCtx, "close(pWorker->fdSocket)"); pWorker->fdSocket = -1; #endif } #ifdef KBUILD_OS_WINDOWS /** * Handles read failure. * * @returns Exit code. * @param pCtx The command execution context. * @param pWorker The worker instance. * @param dwErr The error code. * @param pszWhere Where it failed. */ static int kSubmitWinReadFailed(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, DWORD dwErr, const char *pszWhere) { DWORD dwExitCode; if (pWorker->cbResultRead == 0) errx(pCtx, 1, "%s/ReadFile failed: %u", pszWhere, dwErr); else errx(pCtx, 1, "%s/ReadFile failed: %u (read %u bytes)", pszWhere, dwErr, pWorker->cbResultRead); assert(dwErr != 0); /* Complete the result. */ pWorker->Result.s.rcExit = 127; pWorker->Result.s.bWorkerExiting = 1; pWorker->cbResultRead = sizeof(pWorker->Result); if (GetExitCodeProcess(pWorker->hProcess, &dwExitCode)) { if (dwExitCode != 0) pWorker->Result.s.rcExit = dwExitCode; } return dwErr != 0 ? (int)(dwErr & 0x7fffffff) : 0x7fffffff; } /** * Used by * @returns 0 if we got the whole result, -1 if I/O is pending, and windows last * error on ReadFile failure. * @param pCtx The command execution context. * @param pWorker The worker instance. */ static int kSubmitReadMoreResultWin(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, const char *pszWhere) { /* * Set up the result read, telling the sub_proc.c unit about it. */ while (pWorker->cbResultRead < sizeof(pWorker->Result)) { DWORD cbRead = 0; BOOL fRc = ResetEvent(pWorker->OverlappedRead.hEvent); assert(fRc); (void)fRc; pWorker->OverlappedRead.Offset = 0; pWorker->OverlappedRead.OffsetHigh = 0; if (!ReadFile(pWorker->hPipe, &pWorker->Result.ab[pWorker->cbResultRead], sizeof(pWorker->Result) - pWorker->cbResultRead, &cbRead, &pWorker->OverlappedRead)) { DWORD dwErr = GetLastError(); if (dwErr == ERROR_IO_PENDING) return -1; return kSubmitWinReadFailed(pCtx, pWorker, dwErr, pszWhere); } pWorker->cbResultRead += cbRead; assert(pWorker->cbResultRead <= sizeof(pWorker->Result)); } return 0; } #endif /* KBUILD_OS_WINDOWS */ /** * Adds the given message to the history. * * @returns Pointer to old message, or NULL if no old msg to free. * @param pWorker The worker instance. * @param pvMsg The message. * @param cbMsg The message size. */ static void *kSubmitUpdateHistory(PWORKERINSTANCE pWorker, void *pvMsg, size_t cbMsg) { unsigned iHistory = pWorker->iHistory % K_ELEMENTS(pWorker->aHistory); void *pvRet; pWorker->iHistory++; pvRet = pWorker->aHistory[iHistory].pvMsg; pWorker->aHistory[iHistory].pvMsg = pvMsg; pWorker->aHistory[iHistory].cbMsg = cbMsg; return pvRet; } typedef struct HISTORYDUMPBUF { char *pszBuf; size_t cbBuf; size_t off; PKMKBUILTINCTX pCtx; } HISTORYDUMPBUF; static void kSubmitDumpHistoryWrite(HISTORYDUMPBUF *pBuf, const char *pch, size_t cch) { if (pBuf->off + cch >= pBuf->cbBuf) { size_t cbNew = pBuf->cbBuf ? pBuf->cbBuf * 2 : 65536; while (pBuf->off + cch >= cbNew) cbNew *= 2; pBuf->pszBuf = (char *)xrealloc(pBuf->pszBuf, cbNew); pBuf->cbBuf = cbNew; } memcpy(&pBuf->pszBuf[pBuf->off], pch, cch); pBuf->off += cch; pBuf->pszBuf[pBuf->off] = '\0'; } static void kSubmitDumpHistoryPrintf(HISTORYDUMPBUF *pBuf, const char *pszFormat, ...) { char szTmp[32]; va_list va; va_start(va, pszFormat); for (;;) { const char *pszPct = strchr(pszFormat, '%'); if (!pszPct) { kSubmitDumpHistoryWrite(pBuf, pszFormat, strlen(pszFormat)); return; } if (pszPct != pszFormat) { kSubmitDumpHistoryWrite(pBuf, pszFormat, pszPct - pszFormat); pszFormat = pszPct; } pszFormat++; switch (*pszFormat++) { case 's': { const char * const psz = va_arg(va, const char *); size_t const cch = strlen(psz); if (cch == 0 || memchr(psz, '\'', cch)) { kSubmitDumpHistoryWrite(pBuf, TUPLE("\"")); /** @todo what if there are '"' in the string? */ kSubmitDumpHistoryWrite(pBuf, psz, cch); kSubmitDumpHistoryWrite(pBuf, TUPLE("\"")); } else if ( !memchr(psz, ' ', cch) && !memchr(psz, '\\', cch) && !memchr(psz, '\t', cch) && !memchr(psz, '\n', cch) && !memchr(psz, '\r', cch) && !memchr(psz, '&', cch) && !memchr(psz, ';', cch) && !memchr(psz, '|', cch)) kSubmitDumpHistoryWrite(pBuf, psz, cch); else { kSubmitDumpHistoryWrite(pBuf, TUPLE("'")); kSubmitDumpHistoryWrite(pBuf, psz, strlen(psz)); kSubmitDumpHistoryWrite(pBuf, TUPLE("'")); } break; } case 'd': { int iValue = va_arg(va, int); kSubmitDumpHistoryWrite(pBuf, szTmp, snprintf(szTmp, sizeof(szTmp), "%d", iValue)); break; } case 'u': { unsigned uValue = va_arg(va, unsigned); kSubmitDumpHistoryWrite(pBuf, szTmp, snprintf(szTmp, sizeof(szTmp), "%u", uValue)); break; } case '%': kSubmitDumpHistoryWrite(pBuf, "%s", 1); break; default: assert(0); } } va_end(va); } static void kSubmitDumpHistoryFlush(HISTORYDUMPBUF *pBuf) { if (pBuf->off > 0) output_write_text(pBuf->pCtx->pOut, 1, pBuf->pszBuf, pBuf->off); pBuf->off = 0; } /** * Dumps the history for this worker to stderr in the given context. * * @param pCtx The command execution context. (Typically not a * real context.) * @param pWorker The worker instance. */ static void kSubmitDumpHistory(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker) { HISTORYDUMPBUF Buf = { NULL, 0, 0, pCtx }; int iHistory = pWorker->iHistory; unsigned cDumped = 0; while (cDumped < K_ELEMENTS(pWorker->aHistory) && iHistory > 0) { unsigned const idx = (unsigned)--iHistory % K_ELEMENTS(pWorker->aHistory); const char *pszMsg = (const char *)pWorker->aHistory[idx].pvMsg; ssize_t cbMsg = pWorker->aHistory[idx].cbMsg; const char *pszExe; const char *pszCwd; uint32_t i; uint32_t cArgs; const char *pszArgs; size_t cbArgs; uint32_t cEnvVars; const char *pszEnvVars; size_t cbEnvVars; const char *pszSpecialEnv; char fNoPchCaching; char fWatcomBrainDamage; uint32_t cPostArgs; const char *pszPostArgs; size_t cbPostArgs; cDumped++; if (!pszMsg || !cbMsg) break; #define SKIP_BYTES(a_cbSkip) do { pszMsg += (a_cbSkip); cbMsg -= (a_cbSkip); } while (0) #define SKIP_STR() do { size_t const cbToSkip = strlen(pszMsg) + 1; SKIP_BYTES(cbToSkip); } while (0) #define SKIP_STRING_ARRAY(a_cStrings, a_cbPreable) do { \ for (i = 0; i < (a_cStrings) && cbMsg > 0; i++) { \ size_t const cbToSkip = (a_cbPreable) + strlen(pszMsg + (a_cbPreable)) + 1; \ SKIP_BYTES(cbToSkip); \ } } while (0) /* Decode it: */ SKIP_BYTES(sizeof(uint32_t) + sizeof("JOB")); pszExe = pszMsg; SKIP_STR(); pszCwd = pszMsg; SKIP_STR(); cArgs = *(uint32_t *)pszMsg; SKIP_BYTES(sizeof(uint32_t)); pszArgs = pszMsg; SKIP_STRING_ARRAY(cArgs, 1 /*fbFlags*/); cbArgs = pszMsg - pszArgs; cEnvVars = *(uint32_t *)pszMsg; SKIP_BYTES(sizeof(uint32_t)); pszEnvVars = pszMsg; SKIP_STRING_ARRAY(cEnvVars, 0); cbEnvVars = pszMsg - pszEnvVars; fWatcomBrainDamage = pszMsg[0] != '\0'; fNoPchCaching = pszMsg[1] != '\0'; SKIP_BYTES(2); pszSpecialEnv = pszMsg; SKIP_STR(); cPostArgs = *(uint32_t *)pszMsg; SKIP_BYTES(sizeof(uint32_t)); pszPostArgs = pszMsg; SKIP_STRING_ARRAY(cPostArgs, 0); cbPostArgs = pszMsg - pszPostArgs; /* Produce parseable output: */ kSubmitDumpHistoryPrintf(&Buf, "kWorker %u/%u:\n\tkSubmit", (long)pWorker->pid, iHistory, pszExe); if (fNoPchCaching) kSubmitDumpHistoryWrite(&Buf, TUPLE(" --no-pch-caching")); if (fWatcomBrainDamage) kSubmitDumpHistoryWrite(&Buf, TUPLE(" --watcom-brain-damage")); if (pszSpecialEnv) kSubmitDumpHistoryPrintf(&Buf, " --special-env %s", pszSpecialEnv); kSubmitDumpHistoryPrintf(&Buf, " --chdir %s \\\n", pszCwd); pszMsg = pszEnvVars; cbMsg = cbEnvVars; for (i = 0; i < cEnvVars && cbMsg > 0; i++) { kSubmitDumpHistoryPrintf(&Buf, "\t--putenv %s \\\n", pszMsg); SKIP_STR(); } if (cPostArgs > 0) { kSubmitDumpHistoryWrite(&Buf, TUPLE("\t--post-cmd ")); pszMsg = pszPostArgs; cbMsg = cbPostArgs; for (i = 0; i < cPostArgs && cbMsg > 0; i++) { kSubmitDumpHistoryPrintf(&Buf, " %s", pszMsg); SKIP_STR(); } kSubmitDumpHistoryWrite(&Buf, TUPLE(" \\\n")); } kSubmitDumpHistoryWrite(&Buf, TUPLE("\t-- \\\n")); pszMsg = pszArgs; cbMsg = cbArgs; for (i = 0; i < cArgs && cbMsg > 0; i++) { SKIP_BYTES(1); kSubmitDumpHistoryPrintf(&Buf, i + 1 < cArgs ? "\t%s \\\n" : "\t%s\n", pszMsg); SKIP_STR(); } #undef SKIP_BYTES #undef SKIP_STR #undef SKIP_STRING_ARRAY } kSubmitDumpHistoryFlush(&Buf); free(Buf.pszBuf); } /** * Marks the worker active. * * On windows this involves setting up the async result read and telling * sub_proc.c about the process. * * @returns Exit code. * @param pCtx The command execution context. * @param pWorker The worker instance to mark as active. * @param cVerbosity The verbosity level. * @param pChild The kmk child to associate the job with. * @param pPidSpawned If @a *pPidSpawned is non-zero if the child is * running, otherwise the worker is already done * and we've returned the exit code of the job. */ static int kSubmitMarkActive(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, int cVerbosity, struct child *pChild, pid_t *pPidSpawned) { #ifdef KBUILD_OS_WINDOWS int rc; #endif pWorker->cbResultRead = 0; #ifdef KBUILD_OS_WINDOWS /* * Setup the async result read on windows. If we're slow and the worker * very fast, this may actually get the result immediately. */ l_again: rc = kSubmitReadMoreResultWin(pCtx, pWorker, "kSubmitMarkActive"); if (rc == -1) { # ifndef CONFIG_NEW_WIN_CHILDREN if (process_kmk_register_submit(pWorker->OverlappedRead.hEvent, (intptr_t)pWorker, pPidSpawned) == 0) { /* likely */ } else { /* We need to do the waiting here because sub_proc.c has too much to do. */ warnx(pCtx, "Too many processes for sub_proc.c to handle!"); WaitForSingleObject(pWorker->OverlappedRead.hEvent, INFINITE); goto l_again; } # else if (MkWinChildCreateSubmit((intptr_t)pWorker->OverlappedRead.hEvent, pWorker, pWorker->pStdOut, pWorker->pStdErr, pChild, pPidSpawned) == 0) { /* likely */ } else { /* We need to do the waiting here because sub_proc.c has too much to do. */ warnx(pCtx, "MkWinChildCreateSubmit failed!"); WaitForSingleObject(pWorker->OverlappedRead.hEvent, INFINITE); goto l_again; } # endif } else { assert(rc == 0 || pWorker->Result.s.rcExit != 0); if (pWorker->Result.s.bWorkerExiting) kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); if (pWorker->Result.s.rcExit && 1) kSubmitDumpHistory(pCtx, pWorker); *pPidSpawned = 0; return pWorker->Result.s.rcExit; } #endif /* * Mark it busy and move it to the active instance. */ pWorker->pBusyWith = pChild; #ifndef KBUILD_OS_WINDOWS *pPidSpawned = pWorker->pid; #endif kSubmitListUnlink(&g_IdleList, pWorker); kSubmitListAppend(&g_BusyList, pWorker); return 0; } #ifdef KBUILD_OS_WINDOWS /** * Retrieve the worker child result. * * If incomplete, we restart the ReadFile operation like kSubmitMarkActive does. * * @returns 0 on success, -1 if ReadFile was restarted. * @param pvUser The worker instance. * @param fBlock if we're to block waiting for the result or not. * @param prcExit Where to return the exit code. * @param piSigNo Where to return the signal number. */ int kSubmitSubProcGetResult(intptr_t pvUser, int fBlock, int *prcExit, int *piSigNo) { PWORKERINSTANCE pWorker = (PWORKERINSTANCE)pvUser; KMKBUILTINCTX FakeCtx = { "kSubmit/GetResult", NULL }; PKMKBUILTINCTX pCtx = &FakeCtx; /* * Get the overlapped result. There should be one since we're here * because of a satisfied WaitForMultipleObject. */ DWORD cbRead = 0; if (GetOverlappedResult(pWorker->hPipe, &pWorker->OverlappedRead, &cbRead, fBlock ? TRUE : FALSE)) { pWorker->cbResultRead += cbRead; assert(pWorker->cbResultRead <= sizeof(pWorker->Result)); /* More to be read? */ while (pWorker->cbResultRead < sizeof(pWorker->Result)) { int rc = kSubmitReadMoreResultWin(pCtx, pWorker, "kSubmitSubProcGetResult/more"); if (rc == -1) return -1; assert(rc == 0 || pWorker->Result.s.rcExit != 0); } assert(pWorker->cbResultRead == sizeof(pWorker->Result)); } else { DWORD dwErr = GetLastError(); if (dwErr == ERROR_IO_INCOMPLETE && !fBlock) return -1; kSubmitWinReadFailed(pCtx, pWorker, dwErr, "kSubmitSubProcGetResult/result"); } /* * Okay, we've got a result. */ *prcExit = pWorker->Result.s.rcExit; switch (pWorker->Result.s.rcExit) { default: *piSigNo = 0; break; case CONTROL_C_EXIT: *piSigNo = SIGINT; break; case STATUS_INTEGER_DIVIDE_BY_ZERO: *piSigNo = SIGFPE; break; case STATUS_ACCESS_VIOLATION: *piSigNo = SIGSEGV; break; case STATUS_PRIVILEGED_INSTRUCTION: case STATUS_ILLEGAL_INSTRUCTION: *piSigNo = SIGILL; break; } if (pWorker->Result.s.rcExit && pWorker->fDebugDumpHistoryOnFailure) kSubmitDumpHistory(pCtx, pWorker); if (pWorker->Result.s.bWorkerExiting) kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); return 0; } int kSubmitSubProcKill(intptr_t pvUser, int iSignal) { return -1; } /** * Called by process_cleanup when it's done with the worker. * * @param pvUser The worker instance. */ void kSubmitSubProcCleanup(intptr_t pvUser) { PWORKERINSTANCE pWorker = (PWORKERINSTANCE)pvUser; kSubmitListUnlink(&g_BusyList, pWorker); kSubmitListAppend(&g_IdleList, pWorker); } #endif /* KBUILD_OS_WINDOWS */ /** * atexit callback that trigger worker termination. */ static void kSubmitAtExitCallback(void) { PWORKERINSTANCE pWorker; DWORD msStartTick; DWORD cKillRaids = 0; KMKBUILTINCTX FakeCtx = { "kSubmit/atexit", NULL }; PKMKBUILTINCTX pCtx = &FakeCtx; /* * Tell all the workers to exit by breaking the connection. */ for (pWorker = g_IdleList.pHead; pWorker != NULL; pWorker = pWorker->pNext) kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); for (pWorker = g_BusyList.pHead; pWorker != NULL; pWorker = pWorker->pNext) kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); /* * Wait a little while for them to stop. */ Sleep(0); msStartTick = GetTickCount(); for (;;) { /* * Collect handles of running processes. */ PWORKERINSTANCE apWorkers[MAXIMUM_WAIT_OBJECTS]; HANDLE ahHandles[MAXIMUM_WAIT_OBJECTS]; DWORD cHandles = 0; for (pWorker = g_IdleList.pHead; pWorker != NULL; pWorker = pWorker->pNext) if (pWorker->hProcess != INVALID_HANDLE_VALUE) { if (cHandles < MAXIMUM_WAIT_OBJECTS) { apWorkers[cHandles] = pWorker; ahHandles[cHandles] = pWorker->hProcess; } cHandles++; } for (pWorker = g_BusyList.pHead; pWorker != NULL; pWorker = pWorker->pNext) if (pWorker->hProcess != INVALID_HANDLE_VALUE) { if (cHandles < MAXIMUM_WAIT_OBJECTS) { apWorkers[cHandles] = pWorker; ahHandles[cHandles] = pWorker->hProcess; } cHandles++; } if (cHandles == 0) return; /* * Wait for the processes. */ for (;;) { DWORD cMsElapsed = GetTickCount() - msStartTick; DWORD dwWait = WaitForMultipleObjects(cHandles <= MAXIMUM_WAIT_OBJECTS ? cHandles : MAXIMUM_WAIT_OBJECTS, ahHandles, FALSE /*bWaitAll*/, cMsElapsed < 5000 ? 5000 - cMsElapsed + 16 : 16); if ( dwWait >= WAIT_OBJECT_0 && dwWait <= WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS) { size_t idx = dwWait - WAIT_OBJECT_0; CloseHandle(apWorkers[idx]->hProcess); apWorkers[idx]->hProcess = INVALID_HANDLE_VALUE; if (cHandles <= MAXIMUM_WAIT_OBJECTS) { /* Restart the wait with the worker removed, or quit if it was the last worker. */ cHandles--; if (!cHandles) return; if (idx != cHandles) { apWorkers[idx] = apWorkers[cHandles]; ahHandles[idx] = ahHandles[cHandles]; } continue; } /* else: Reconstruct the wait array so we get maximum coverage. */ } else if (dwWait == WAIT_TIMEOUT) { /* Terminate the whole bunch. */ cKillRaids++; if (cKillRaids == 1 && getenv("KMK_KSUBMIT_NO_KILL") == NULL) { warnx(pCtx, "Killing %u lingering worker processe(s)!\n", cHandles); for (pWorker = g_IdleList.pHead; pWorker != NULL; pWorker = pWorker->pNext) if (pWorker->hProcess != INVALID_HANDLE_VALUE) TerminateProcess(pWorker->hProcess, WAIT_TIMEOUT); for (pWorker = g_BusyList.pHead; pWorker != NULL; pWorker = pWorker->pNext) if (pWorker->hProcess != INVALID_HANDLE_VALUE) TerminateProcess(pWorker->hProcess, WAIT_TIMEOUT); } else { warnx(pCtx, "Giving up on the last %u worker processe(s). :-(\n", cHandles); return; } } else { /* Some kind of wait error. Could be a bad handle, check each and remove bad ones as well as completed ones. */ size_t idx; warnx(pCtx, "WaitForMultipleObjects unexpectedly returned %#u (err=%u)\n", dwWait, GetLastError()); for (idx = 0; idx < cHandles; idx++) { dwWait = WaitForSingleObject(ahHandles[idx], 0 /*ms*/); if (dwWait != WAIT_TIMEOUT) { CloseHandle(apWorkers[idx]->hProcess); apWorkers[idx]->hProcess = INVALID_HANDLE_VALUE; } } } break; } /* wait loop */ } /* outer wait loop */ } static int kmk_builtin_kSubmit_usage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s [-Z|--zap-env] [-E|--set ] [-U|--unset ]\n" " [-A|--append ] [-D|--prepend ]\n" " [-s|--special-env ] [-C|--chdir ]\n" " [--wcc-brain-damage] [--no-pch-caching]\n" " [-3|--32-bit] [-6|--64-bit] [-v] [--debug-dump-history]\n" " [-P|--post-cmd [args]] -- [args]\n" " or: %s --help\n" " or: %s --version\n" "\n" "Options:\n" " -Z, --zap-env, -i, --ignore-environment\n" " Zaps the environment. Position dependent.\n" " -E, --set =[value]\n" " Sets an environment variable putenv fashion. Position dependent.\n" " -U, --unset \n" " Removes an environment variable. Position dependent.\n" " -A, --append =\n" " Appends the given value to the environment variable.\n" " -D,--prepend =\n" " Prepends the given value to the environment variable.\n" " -s,--special-env =\n" " Same as --set, but flags the variable for further expansion\n" " within kWorker. Replacements:\n" " @@PROCESSOR_GROUP@@ - The processor group number.\n" " @@AUTHENTICATION_ID@@ - The authentication ID from the process token.\n" " @@PID@@ - The kWorker process ID.\n" " @@@@ - Escaped \"@@\".\n" " @@DEBUG_COUNTER@@ - An ever increasing counter (starts at zero).\n" " -C, --chdir \n" " Specifies the current directory for the program. Relative paths\n" " are relative to the previous -C option. Default is getcwd value.\n" " -3, --32-bit\n" " Selects a 32-bit kWorker process. Default: kmk bit count\n" " -6, --64-bit\n" " Selects a 64-bit kWorker process. Default: kmk bit count\n" " --wcc-brain-damage\n" " Works around wcc and wcc386 (Open Watcom) not following normal\n" " quoting conventions on Windows, OS/2, and DOS.\n" " --no-pch-caching\n" " Do not cache precompiled header files because they're being created.\n" " -v,--verbose\n" " More verbose execution.\n" " --debug-dump-history\n" " Dump the history as of the submitted command. Handy for debugging\n" " trouble caused by a previous job.\n" " --debug-dump-history-on-failure, --no-debug-dump-history-on-failure\n" " Dump the history on failure. Can also be enabled by a non-empty\n" " KMK_KSUBMIT_DUMP_HISTORY_ON_FAILURE variable (first invocation only).\n" " -P|--post-cmd ...\n" " For running a built-in command on the output, specifying the command\n" " and all it's parameters. Currently supported commands:\n" " kDepObj\n" " -V,--version\n" " Show the version number.\n" " -h,--help\n" " Show this usage information.\n" "\n" , pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); return 2; } int kmk_builtin_kSubmit(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned) { #ifdef KBUILD_OS_WINDOWS static int s_fInitialized = 0; #endif int rcExit = 0; int iArg; unsigned cAllocatedEnvVars; unsigned cEnvVars; char **papszEnvVars; const char *pszExecutable = NULL; const char *pszSpecialEnv = NULL; int iPostCmd = argc; int cPostCmdArgs = 0; unsigned cBitsWorker = g_cArchBits; int fWatcomBrainDamage = 0; int fNoPchCaching = 0; int fDebugDumpHistory = 0; static int s_fDebugDumpHistoryOnFailure = -1; int fDebugDumpHistoryOnFailure = s_fDebugDumpHistoryOnFailure; int cVerbosity = 0; size_t const cbCwdBuf = GET_PATH_MAX; PATH_VAR(szCwd); #ifdef KBUILD_OS_WINDOWS /* * First time thru we must perform some initializations. */ if (s_fInitialized) { } else { MkWinChildInitCpuGroupAllocator(&g_SubmitProcessorGroupAllocator); # if K_ARCH_BITS == 64 MkWinChildInitCpuGroupAllocator(&g_SubmitProcessorGroupAllocator32); # endif *(FARPROC *)&g_pfnSetThreadGroupAffinity = GetProcAddress(GetModuleHandleW(L"KERNEL32.DLL"), "SetThreadGroupAffinity"); s_fInitialized = 1; } #endif if (fDebugDumpHistoryOnFailure != -1) { /* likely */ } else { struct variable *pVar = lookup_variable(TUPLE("KMK_KSUBMIT_DUMP_HISTORY_ON_FAILURE")); fDebugDumpHistoryOnFailure = pVar && *pVar->value != '\0'; s_fDebugDumpHistoryOnFailure = fDebugDumpHistoryOnFailure; } /* * Create default program environment. * * Note! We only clean up the environment on successful return, assuming * make will stop after that. */ if (getcwd_fs(szCwd, cbCwdBuf) != NULL) { /* likely */ } else return err(pCtx, 1, "getcwd_fs failed\n"); /* The environment starts out in read-only mode and will be duplicated if modified. */ cAllocatedEnvVars = 0; papszEnvVars = envp; cEnvVars = 0; while (papszEnvVars[cEnvVars] != NULL) cEnvVars++; /* * Parse the command line. */ for (iArg = 1; iArg < argc; iArg++) { const char *pszArg = argv[iArg]; if (*pszArg == '-') { char chOpt = *++pszArg; pszArg++; if (chOpt != '-') { if (chOpt != '\0') { /* likely */ } else { errx(pCtx, 1, "Incomplete option: '-'"); return kmk_builtin_kSubmit_usage(pCtx, 1); } } else { /* '--' indicates where the bits to execute start. */ if (*pszArg == '\0') { iArg++; break; } if ( strcmp(pszArg, "wcc-brain-damage") == 0 || strcmp(pszArg, "watcom-brain-damage") == 0) { fWatcomBrainDamage = 1; continue; } if (strcmp(pszArg, "no-pch-caching") == 0) { fNoPchCaching = 1; continue; } if (strcmp(pszArg, "debug-dump-history") == 0) { fDebugDumpHistory = 1; continue; } if (strcmp(pszArg, "debug-dump-history-on-failure") == 0) { fDebugDumpHistoryOnFailure = 1; continue; } if (strcmp(pszArg, "no-debug-dump-history-on-failure") == 0) { fDebugDumpHistoryOnFailure = 0; continue; } /* convert to short. */ if (strcmp(pszArg, "help") == 0) chOpt = 'h'; else if (strcmp(pszArg, "version") == 0) chOpt = 'V'; else if (strcmp(pszArg, "set") == 0) chOpt = 'E'; else if (strcmp(pszArg, "append") == 0) chOpt = 'A'; else if (strcmp(pszArg, "prepend") == 0) chOpt = 'D'; else if (strcmp(pszArg, "unset") == 0) chOpt = 'U'; else if ( strcmp(pszArg, "zap-env") == 0 || strcmp(pszArg, "ignore-environment") == 0 /* GNU env compatibility. */ ) chOpt = 'Z'; else if (strcmp(pszArg, "chdir") == 0) chOpt = 'C'; else if (strcmp(pszArg, "set-special") == 0) chOpt = 's'; else if (strcmp(pszArg, "post-cmd") == 0) chOpt = 'P'; else if (strcmp(pszArg, "32-bit") == 0) chOpt = '3'; else if (strcmp(pszArg, "64-bit") == 0) chOpt = '6'; else if (strcmp(pszArg, "verbose") == 0) chOpt = 'v'; else if (strcmp(pszArg, "executable") == 0) chOpt = 'e'; else { errx(pCtx, 2, "Unknown option: '%s'", pszArg - 2); return kmk_builtin_kSubmit_usage(pCtx, 1); } pszArg = ""; } do { /* Get option value first, if the option takes one. */ const char *pszValue = NULL; switch (chOpt) { case 'A': case 'C': case 'E': case 'U': case 'D': case 'e': case 's': if (*pszArg != '\0') pszValue = pszArg + (*pszArg == ':' || *pszArg == '='); else if (++iArg < argc) pszValue = argv[iArg]; else { errx(pCtx, 1, "Option -%c requires a value!", chOpt); return kmk_builtin_kSubmit_usage(pCtx, 1); } break; } switch (chOpt) { case 'Z': case 'i': /* GNU env compatibility. */ rcExit = kBuiltinOptEnvZap(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity); if (rcExit == 0) break; return rcExit; case 'E': rcExit = kBuiltinOptEnvSet(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); if (rcExit == 0) break; return rcExit; case 'A': rcExit = kBuiltinOptEnvAppend(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); if (rcExit == 0) break; return rcExit; case 'D': rcExit = kBuiltinOptEnvPrepend(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); if (rcExit == 0) break; return rcExit; case 'U': rcExit = kBuiltinOptEnvUnset(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); if (rcExit == 0) break; return rcExit; case 'C': rcExit = kBuiltinOptChDir(pCtx, szCwd, cbCwdBuf, pszValue); if (rcExit == 0) break; return rcExit; case 's': if (pszSpecialEnv) return errx(pCtx, 1, "The -s option can only be used once!"); pszSpecialEnv = pszValue; rcExit = kBuiltinOptEnvSet(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); if (rcExit == 0) break; return rcExit; case 'P': if (cPostCmdArgs > 0) return errx(pCtx, 1, "The -P option can only be used once!"); if (*pszArg != '\0') return errx(pCtx, 1, "The cmd part of the -P needs to be a separate argument!"); iPostCmd = ++iArg; if (iArg >= argc) return errx(pCtx, 1, "The -P option requires a command following it!"); while (iArg < argc && strcmp(argv[iArg], "--") != 0) iArg++; cPostCmdArgs = iArg - iPostCmd; iArg--; break; #if !defined(KBUILD_ARCH_ARM64) case '3': cBitsWorker = 32; break; #endif case '6': cBitsWorker = 64; break; case 'e': pszExecutable = pszValue; break; case 'v': cVerbosity++; break; case 'h': kmk_builtin_kSubmit_usage(pCtx, 0); kBuiltinOptEnvCleanup(&papszEnvVars, cEnvVars, &cAllocatedEnvVars); return 0; case 'V': kBuiltinOptEnvCleanup(&papszEnvVars, cEnvVars, &cAllocatedEnvVars); return kbuild_version(argv[0]); } } while ((chOpt = *pszArg++) != '\0'); } else { errx(pCtx, 1, "Unknown argument: '%s'", pszArg); return kmk_builtin_kSubmit_usage(pCtx, 1); } } /* * Check that we've got something to execute. */ if (iArg < argc) { uint32_t cbMsg; void *pvMsg = kSubmitComposeJobMessage(pszExecutable, &argv[iArg], papszEnvVars, szCwd, fWatcomBrainDamage, fNoPchCaching, pszSpecialEnv, &argv[iPostCmd], cPostCmdArgs, &cbMsg); PWORKERINSTANCE pWorker = kSubmitSelectWorkSpawnNewIfNecessary(pCtx, cBitsWorker, cVerbosity); if (pWorker) { /* Before we send off the job, we should dump pending output, since the kWorker process currently does not coordinate its output with the output.c mechanics. */ #ifdef CONFIG_NEW_WIN_CHILDREN if (pCtx->pOut && !pWorker->pStdOut) #else if (pCtx->pOut) #endif output_dump(pCtx->pOut); pWorker->fDebugDumpHistoryOnFailure = fDebugDumpHistoryOnFailure; rcExit = kSubmitSendJobMessage(pCtx, pWorker, pvMsg, cbMsg, 0 /*fNoRespawning*/, cVerbosity); if (rcExit == 0) { pvMsg = kSubmitUpdateHistory(pWorker, pvMsg, cbMsg); if (fDebugDumpHistory) kSubmitDumpHistory(pCtx, pWorker); rcExit = kSubmitMarkActive(pCtx, pWorker, cVerbosity, pChild, pPidSpawned); } if (!g_fAtExitRegistered) if (atexit(kSubmitAtExitCallback) == 0) g_fAtExitRegistered = 1; } else rcExit = 1; free(pvMsg); } else { errx(pCtx, 1, "Nothing to executed!"); rcExit = kmk_builtin_kSubmit_usage(pCtx, 1); } kBuiltinOptEnvCleanup(&papszEnvVars, cEnvVars, &cAllocatedEnvVars); return rcExit; } kbuild-3686/src/kmk/kmkbuiltin/Makefile.kup0000664000175000017500000000000015053010075020656 0ustar locutuslocutuskbuild-3686/src/kmk/kmkbuiltin/darwin.c0000664000175000017500000000314315053010074020062 0ustar locutuslocutus/* $Id: darwin.c 2591 2012-06-17 20:45:31Z bird $ */ /** @file * Missing BSD functions on Darwin / Mac OS X. */ /* * Copyright (c) 2006-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include int lchmod(const char *path, mode_t mode) { struct stat st; if (lstat(path, &st)) return -1; if (S_ISLNK(st.st_mode)) return 0; /* pretend success */ return chmod(path, mode); } int lutimes(const char *path, const struct timeval *tvs) { struct stat st; if (lstat(path, &st)) return -1; if (S_ISLNK(st.st_mode)) return 0; /* pretend success */ return utimes(path, tvs); } kbuild-3686/src/kmk/kmkbuiltin/redirect.c0000664000175000017500000023460715053010074020412 0ustar locutuslocutus/* $Id: redirect.c 3685 2025-08-15 00:51:28Z bird $ */ /** @file * kmk_redirect - Do simple program <-> file redirection (++). */ /* * Copyright (c) 2007-2016 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #if defined(__APPLE__) /*# define _POSIX_C_SOURCE 1 / * 10.4 sdk and unsetenv * / - breaks O_CLOEXEC on 10.8 */ #endif #include "makeint.h" #include #include #include #include #include #include #include #if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2) # include #endif #ifdef KBUILD_OS_WINDOWS # include #endif #if defined(_MSC_VER) # include # include # include "quote_argv.h" #else # ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ # if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 # define USE_POSIX_SPAWN # endif # elif !defined(KBUILD_OS_WINDOWS) && !defined(KBUILD_OS_OS2) # define USE_POSIX_SPAWN # endif # include # ifdef USE_POSIX_SPAWN # include # endif # include #endif #include #include #include "err.h" #include "kbuild_version.h" #ifdef KBUILD_OS_WINDOWS # include "nt/nt_child_inject_standard_handles.h" #endif #if defined(__gnu_hurd__) && !defined(KMK_BUILTIN_STANDALONE) /* need constant */ # undef GET_PATH_MAX # undef PATH_MAX # define GET_PATH_MAX PATH_MAX #endif #include "kmkbuiltin.h" #ifdef KMK # ifdef KBUILD_OS_WINDOWS # ifndef CONFIG_NEW_WIN_CHILDREN # include "sub_proc.h" # else # include "../w32/winchildren.h" # endif # include "pathstuff.h" # endif #endif #ifdef __OS2__ # define INCL_BASE # include # ifndef LIBPATHSTRICT # define LIBPATHSTRICT 3 # endif #endif #ifndef KMK_BUILTIN_STANDALONE extern void kmk_cache_exec_image_a(const char *); /* imagecache.c */ #endif /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ /* String + strlen tuple. */ #define TUPLE(a_sz) a_sz, sizeof(a_sz) - 1 /** Only standard handles on windows. */ #ifdef KBUILD_OS_WINDOWS # define ONLY_TARGET_STANDARD_HANDLES #endif static int kmk_redirect_usage(PKMKBUILTINCTX pCtx, int fIsErr) { /* 0 1 2 3 4 5 6 7 8 */ /* 012345678901234567890123456789012345678901234567890123456789012345678901234567890 */ kmk_builtin_ctx_printf(pCtx, fIsErr, "Usage: %s [-[rwa+tb] ] [-d=] [-c] [--stdin-pipe]\n" " [-Z] [-E ] [-A ] [-P ] [-D ]\n" " [-X [=]\n" " [-C ] [--wcc-brain-damage] [-v] -- [args]\n" " or: %s --help\n" " or: %s --version\n" "\n" "Options:\n" "-[rwa+tb] \n" " The rwa+tb is like for fopen, if not specified it defaults to w+.\n" " The is either a number or an alias for the standard handles:\n" " i = stdin\n" " o = stdout\n" " e = stderr\n" "-d\n" " The -d switch duplicate the right hand file descriptor (src-fd) to the left\n" " hand side one (fd). The latter is limited to standard handles on windows.\n" "-c , --close \n" " The -c switch will close the specified file descriptor. Limited to standard\n" " handles on windows.\n" "--stdin-pipe\n" " The --stdin-pipe switch will replace stdin with the read end of an\n" " anonymous pipe. This is for tricking things like rsh.exe that blocks\n" " reading on stdin.\n" "-Z, --zap-env, --ignore-environment\n" " The -Z switch zaps the environment.\n" "-E , --set , --env \n" " The -E (--set, --env) switch is for making changes to the environment\n" " in an putenv fashion.\n" "-A , --append \n" " The -A switch appends to an environment variable in a putenv fashion.\n" "-D , --prepend \n" " The -D switch prepends to an environment variable in a putenv fashion.\n" "-U , --unset \n" " The -U switch deletes an environment variable.\n" /* 0 1 2 3 4 5 6 7 8 */ /* 012345678901234567890123456789012345678901234567890123456789012345678901234567890 */ "-X [=], --translate-exitcode [=]\n" " Translates exit codes. The '' value defaults to zero.\n" "-C , --chdir \n" " The -C switch is for changing the current directory. Please specify an\n" " absolute program path as it's platform dependent whether this takes\n" " effect before or after the executable is located.\n" "--wcc-brain-damage, --watcom-brain-damage\n" " The --wcc-brain-damage switch is to work around wcc and wcc386\n" " (Open Watcom) not following normal quoting conventions on Windows and OS/2.\n" "-v, --verbose\n" " The -v switch is for making the thing more verbose.\n" "\n" "On OS/2 the kernel variables BEGINLIBPATH, ENDLIBPATH and LIBPATHSTRICT can be\n" "accessed as-if they were regular environment variables.\n" "\n" "This command was originally just a quick hack to avoid invoking the shell\n" "on Windows (cygwin) where forking is very expensive and has exhibited\n" "stability issues on SMP machines. It has since grown into something like\n" "/usr/bin/env on steroids.\n" /* 0 1 2 3 4 5 6 7 8 */ /* 012345678901234567890123456789012345678901234567890123456789012345678901234567890 */ , pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); return 2; } /** * Decoded file descriptor operations. */ typedef struct REDIRECTORDERS { enum { kRedirectOrder_Invalid = 0, kRedirectOrder_Close, kRedirectOrder_Open, kRedirectOrder_Dup } enmOrder; /** The target file handle. */ int fdTarget; /** The source file name, -1 on close only. * This is an opened file if pszFilename is set. */ int fdSource; /** Whether to remove the file on failure cleanup. */ int fRemoveOnFailure; /** The open flags (for O_TEXT/O_BINARY) on windows. */ int fOpen; /** The filename - NULL if close only. */ const char *pszFilename; /** The other pipe end, needs closing in cleanup. */ int fdOtherPipeEnd; #ifndef USE_POSIX_SPAWN /** Saved file descriptor. */ int fdSaved; /** Saved flags. */ int fSaved; #endif } REDIRECTORDERS; static KBOOL kRedirectHasConflict(int fd, unsigned cOrders, REDIRECTORDERS *paOrders) { #ifdef ONLY_TARGET_STANDARD_HANDLES return fd < 3; #else while (cOrders-- > 0) if (paOrders[cOrders].fdTarget == fd) return K_TRUE; return K_FALSE; #endif } /** * Creates a pair of pipe descriptors that does not conflict with any previous * orders. * * The pipe is open with both descriptors being inherited by the child as it's * supposed to be a dummy pipe for stdin that won't break. * * @returns 0 on success, exit code on failure (error message displayed). * @param pCtx The command execution context. * @param paFds Where to return the pipe descriptors * @param cOrders The number of orders. * @param paOrders The order array. * @param fdTarget The target descriptor (0). */ static int kRedirectCreateStdInPipeWithoutConflict(PKMKBUILTINCTX pCtx, int paFds[2], unsigned cOrders, REDIRECTORDERS *paOrders, int fdTarget) { struct { int aFds[2]; } aTries[32]; unsigned cTries = 0; while (cTries < K_ELEMENTS(aTries)) { #ifdef _MSC_VER int rc = _pipe(aTries[cTries].aFds, 0, _O_BINARY); #else int rc = pipe(aTries[cTries].aFds); #endif if (rc >= 0) { if ( !kRedirectHasConflict(aTries[cTries].aFds[0], cOrders, paOrders) && !kRedirectHasConflict(aTries[cTries].aFds[1], cOrders, paOrders) #ifndef _MSC_VER && aTries[cTries].aFds[0] != fdTarget && aTries[cTries].aFds[1] != fdTarget #endif ) { paFds[0] = aTries[cTries].aFds[0]; paFds[1] = aTries[cTries].aFds[1]; while (cTries-- > 0) { close(aTries[cTries].aFds[0]); close(aTries[cTries].aFds[1]); } return 0; } } else { err(pCtx, -1, "failed to create stdin pipe (try #%u)", cTries + 1); break; } cTries++; } if (cTries >= K_ELEMENTS(aTries)) errx(pCtx, -1, "failed to find a conflict free pair of pipe descriptor for stdin!"); /* cleanup */ while (cTries-- > 0) { close(aTries[cTries].aFds[0]); close(aTries[cTries].aFds[1]); } return 1; } /** * Creates a file descriptor for @a pszFilename that does not conflict with any * previous orders. * * We need to be careful that there isn't a close or dup targetting the * temporary file descriptor we return. Also, we need to take care with the * descriptor's inheritability. It should only be inheritable if the returned * descriptor matches the target descriptor (@a fdTarget). * * @returns File descriptor on success, -1 & err/errx on failure. * * The returned file descriptor is not inherited (i.e. close-on-exec), * unless it matches @a fdTarget * * @param pCtx The command execution context. * @param pszFilename The filename to open. * @param fOpen The open flags. * @param fMode The file creation mode (if applicable). * @param cOrders The number of orders. * @param paOrders The order array. * @param fRemoveOnFailure Whether to remove the file on failure. * @param fdTarget The target descriptor. */ static int kRedirectOpenWithoutConflict(PKMKBUILTINCTX pCtx, const char *pszFilename, int fOpen, mode_t fMode, unsigned cOrders, REDIRECTORDERS *paOrders, int fRemoveOnFailure, int fdTarget) { #ifdef _O_NOINHERIT int const fNoInherit = _O_NOINHERIT; #elif defined(O_NOINHERIT) int const fNoInherit = O_NOINHERIT; #elif defined(O_CLOEXEC) int const fNoInherit = O_CLOEXEC; #else int const fNoInherit = 0; # define USE_FD_CLOEXEC #endif int aFdTries[32]; unsigned cTries; int fdOpened; #ifdef KBUILD_OS_WINDOWS if (strcmp(pszFilename, "/dev/null") == 0) pszFilename = "nul"; #endif /* Open it first. */ fdOpened = open(pszFilename, fOpen | fNoInherit, fMode); if (fdOpened < 0) return err(pCtx, -1, "open(%s,%#x,) failed", pszFilename, fOpen); /* Check for conflicts. */ if (!kRedirectHasConflict(fdOpened, cOrders, paOrders)) { #ifndef KBUILD_OS_WINDOWS if (fdOpened != fdTarget) return fdOpened; # ifndef USE_FD_CLOEXEC if (fcntl(fdOpened, F_SETFD, 0) != -1) # endif #endif return fdOpened; } /* * Do conflict resolving. */ cTries = 1; aFdTries[cTries++] = fdOpened; while (cTries < K_ELEMENTS(aFdTries)) { fdOpened = open(pszFilename, fOpen | fNoInherit, fMode); if (fdOpened >= 0) { if (!kRedirectHasConflict(fdOpened, cOrders, paOrders)) { #ifndef KBUILD_OS_WINDOWS # ifdef USE_FD_CLOEXEC if ( fdOpened == fdTarget || fcntl(fdOpened, F_SETFD, FD_CLOEXEC) != -1) # else if ( fdOpened != fdTarget || fcntl(fdOpened, F_SETFD, 0) != -1) # endif #endif { while (cTries-- > 0) close(aFdTries[cTries]); return fdOpened; } } } else { err(pCtx, -1, "open(%s,%#x,) #%u failed", pszFilename, cTries + 1, fOpen); break; } aFdTries[cTries++] = fdOpened; } /* * Give up. */ if (fdOpened >= 0) errx(pCtx, -1, "failed to find a conflict free file descriptor for '%s'!", pszFilename); while (cTries-- > 0) close(aFdTries[cTries]); return -1; } /** * Cleans up the file operation orders. * * This does not restore stuff, just closes handles we've opened for the child. * * @param cOrders Number of file operation orders. * @param paOrders The file operation orders. * @param fFailed Set if it's a failure. */ static void kRedirectCleanupFdOrders(unsigned cOrders, REDIRECTORDERS *paOrders, KBOOL fFailure) { unsigned i = cOrders; while (i-- > 0) { if ( paOrders[i].enmOrder == kRedirectOrder_Open && paOrders[i].fdSource != -1) { close(paOrders[i].fdSource); paOrders[i].fdSource = -1; if (paOrders[i].fdOtherPipeEnd >= 0) { close(paOrders[i].fdOtherPipeEnd); paOrders[i].fdOtherPipeEnd = -1; } if ( fFailure && paOrders[i].fRemoveOnFailure && paOrders[i].pszFilename) remove(paOrders[i].pszFilename); } } } #if !defined(USE_POSIX_SPAWN) && !defined(KBUILD_OS_WINDOWS) /** * Wrapper that chooses between fprintf and kmk_builtin_ctx_printf to get * an error message to the user. * * @param pCtx The command execution context. * @param pWorkingStdErr Work stderr. * @param pszFormat The message format string. * @param ... Format arguments. */ static void safe_err_printf(PKMKBUILTINCTX pCtx, FILE *pWorkingStdErr, const char *pszFormat, ...) { char szMsg[4096]; size_t cchMsg; va_list va; va_start(va, pszFormat); vsnprintf(szMsg, sizeof(szMsg) - 1, pszFormat, va); va_end(va); szMsg[sizeof(szMsg) - 1] = '\0'; cchMsg = strlen(szMsg); #ifdef KMK_BUILTIN_STANDALONE (void)pCtx; #else if (pCtx->pOut && pCtx->pOut->syncout) output_write_text(pCtx->pOut, 1, szMsg, cchMsg); else #endif fwrite(szMsg, cchMsg, 1, pWorkingStdErr); } /** * Saves a file handle to one which isn't inherited and isn't affected by the * file orders. * * @returns 0 on success, non-zero exit code on failure. * @param pCtx The command execution context. * @param pToSave Pointer to the file order to save the target * descriptor of. * @param cOrders Number of file orders. * @param paOrders The array of file orders. * @param ppWorkingStdErr Pointer to a pointer to a working stderr. This will * get replaced if we're saving stderr, so that we'll * keep having a working one to report failures to. */ static int kRedirectSaveHandle(PKMKBUILTINCTX pCtx, REDIRECTORDERS *pToSave, unsigned cOrders, REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr) { int fdToSave = pToSave->fdTarget; int rcRet = 10; /* * First, check if there's actually handle here that needs saving. */ pToSave->fSaved = fcntl(pToSave->fdTarget, F_GETFD, 0); if (pToSave->fSaved != -1) { /* * Try up to 32 times to get a duplicate descriptor that doesn't conflict. */ int aFdTries[32]; int cTries = 0; do { /* Duplicate the handle (windows makes this complicated). */ int fdDup; fdDup = dup(fdToSave); if (fdDup == -1) { safe_err_printf(pCtx, *ppWorkingStdErr, "%s: dup(%#x) failed: %u\n", pCtx->pszProgName, fdToSave, strerror(errno)); break; } /* Is the duplicate usable? */ if (!kRedirectHasConflict(fdDup, cOrders, paOrders)) { pToSave->fdSaved = fdDup; if ( *ppWorkingStdErr == stderr && fdToSave == fileno(*ppWorkingStdErr)) { *ppWorkingStdErr = fdopen(fdDup, "wt"); if (*ppWorkingStdErr == NULL) { safe_err_printf(pCtx, stderr, "%s: fdopen(%d,\"wt\") failed: %s\n", pCtx->pszProgName, fdDup, strerror(errno)); *ppWorkingStdErr = stderr; close(fdDup); break; } } rcRet = 0; break; } /* Not usuable, stash it and try again. */ aFdTries[cTries++] = fdDup; } while (cTries < K_ELEMENTS(aFdTries)); /* * Clean up unused duplicates. */ while (cTries-- > 0) close(aFdTries[cTries]); } else { /* * Nothing to save. */ pToSave->fdSaved = -1; rcRet = 0; } return rcRet; } /** * Restores the target file descriptors affected by the file operation orders. * * @param pCtx The command execution context. * @param cOrders Number of file operation orders. * @param paOrders The file operation orders. * @param ppWorkingStdErr Pointer to a pointer to the working stderr. If this * is one of the saved file descriptors, we'll restore * it to stderr. */ static void kRedirectRestoreFdOrders(PKMKBUILTINCTX pCtx, unsigned cOrders, REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr) { int iSavedErrno = errno; unsigned i = cOrders; while (i-- > 0) { if (paOrders[i].fdSaved != -1) { KBOOL fRestoreStdErr = *ppWorkingStdErr != stderr && paOrders[i].fdSaved == fileno(*ppWorkingStdErr); if (dup2(paOrders[i].fdSaved, paOrders[i].fdTarget) != -1) { close(paOrders[i].fdSaved); paOrders[i].fdSaved = -1; if (fRestoreStdErr) { *ppWorkingStdErr = stderr; assert(fileno(stderr) == paOrders[i].fdTarget); } } else safe_err_printf(pCtx, *ppWorkingStdErr, "%s: dup2(%d,%d) failed: %s\n", pCtx->pszProgName, paOrders[i].fdSaved, paOrders[i].fdTarget, strerror(errno)); } if (paOrders[i].fSaved != -1) { if (fcntl(paOrders[i].fdTarget, F_SETFD, paOrders[i].fSaved & FD_CLOEXEC) != -1) paOrders[i].fSaved = -1; else safe_err_printf(pCtx, *ppWorkingStdErr, "%s: fcntl(%d,F_SETFD,%s) failed: %s\n", pCtx->pszProgName, paOrders[i].fdTarget, paOrders[i].fSaved & FD_CLOEXEC ? "FD_CLOEXEC" : "0", strerror(errno)); } } errno = iSavedErrno; } /** * Executes the file operation orders. * * @returns 0 on success, exit code on failure. * @param pCtx The command execution context. * @param cOrders Number of file operation orders. * @param paOrders File operation orders to execute. * @param ppWorkingStdErr Where to return a working stderr (mainly for * kRedirectRestoreFdOrders). */ static int kRedirectExecFdOrders(PKMKBUILTINCTX pCtx, unsigned cOrders, REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr) { unsigned i; *ppWorkingStdErr = stderr; for (i = 0; i < cOrders; i++) { int rcExit = 10; switch (paOrders[i].enmOrder) { case kRedirectOrder_Close: { /* If the handle isn't used by any of the following operation, just mark it as non-inheritable if necessary. */ int const fdTarget = paOrders[i].fdTarget; unsigned j; for (j = i + 1; j < cOrders; j++) if (paOrders[j].fdTarget == fdTarget) break; if (j >= cOrders) { paOrders[j].fSaved = fcntl(fdTarget, F_GETFD, 0); if (paOrders[j].fSaved != -1) { if (paOrders[j].fSaved & FD_CLOEXEC) rcExit = 0; else if ( fcntl(fdTarget, F_SETFD, FD_CLOEXEC) != -1 || errno == EBADF) rcExit = 0; else safe_err_printf(pCtx, *ppWorkingStdErr, "%s: fcntl(%d,F_SETFD,FD_CLOEXEC) failed: %s\n", pCtx->pszProgName, fdTarget, strerror(errno)); } else if (errno == EBADF) rcExit = 0; else safe_err_printf(pCtx, *ppWorkingStdErr, "%s: fcntl(%d,F_GETFD,0) failed: %s\n", pCtx->pszProgName, fdTarget, strerror(errno)); } else rcExit = kRedirectSaveHandle(pCtx, &paOrders[i], cOrders, paOrders, ppWorkingStdErr); break; } case kRedirectOrder_Dup: case kRedirectOrder_Open: rcExit = kRedirectSaveHandle(pCtx, &paOrders[i], cOrders, paOrders, ppWorkingStdErr); if (rcExit == 0) { if (dup2(paOrders[i].fdSource, paOrders[i].fdTarget) != -1) rcExit = 0; else { if (paOrders[i].enmOrder == kRedirectOrder_Open) safe_err_printf(pCtx, *ppWorkingStdErr, "%s: dup2(%d [%s],%d) failed: %s\n", pCtx->pszProgName, paOrders[i].fdSource, paOrders[i].pszFilename, paOrders[i].fdTarget, strerror(errno)); else safe_err_printf(pCtx, *ppWorkingStdErr, "%s: dup2(%d,%d) failed: %s\n", pCtx->pszProgName, paOrders[i].fdSource, paOrders[i].fdTarget, strerror(errno)); rcExit = 10; } } break; default: safe_err_printf(pCtx, *ppWorkingStdErr, "%s: error! invalid enmOrder=%d\n", pCtx->pszProgName, paOrders[i].enmOrder); rcExit = 99; break; } if (rcExit != 0) { kRedirectRestoreFdOrders(pCtx, i, paOrders, ppWorkingStdErr); return rcExit; } } return 0; } #endif /* !USE_POSIX_SPAWN */ #ifdef KBUILD_OS_WINDOWS /** * Registers the child process with a care provider or waits on it to complete. * * @returns 0 or non-zero success indicator or child exit code, depending on * the value pfIsChildExitCode points to. * @param pCtx The command execution context. * @param hProcess The child process handle. * @param cVerbosity The verbosity level. * @param pPidSpawned Where to return the PID of the spawned child * when we're inside KMK and we're return without * waiting. * @param pfIsChildExitCode Where to indicate whether the return exit code * is from the child or from our setup efforts. */ static int kRedirectPostnatalCareOnWindows(PKMKBUILTINCTX pCtx, HANDLE hProcess, unsigned cVerbosity, pid_t *pPidSpawned, KBOOL *pfIsChildExitCode) { int rcExit; DWORD dwTmp; # ifndef KMK_BUILTIN_STANDALONE /* * Try register the child with a childcare provider, i.e. winchildren.c * or sub_proc.c. */ # ifndef CONFIG_NEW_WIN_CHILDREN if (process_kmk_register_redirect(hProcess, pPidSpawned) == 0) # else if ( pPidSpawned && MkWinChildCreateRedirect((intptr_t)hProcess, pPidSpawned) == 0) # endif { if (cVerbosity > 0) warnx(pCtx, "debug: spawned %d", *pPidSpawned); *pfIsChildExitCode = K_FALSE; return 0; } # ifndef CONFIG_NEW_WIN_CHILDREN warn(pCtx, "sub_proc is out of slots, waiting for child..."); # else if (pPidSpawned) warn(pCtx, "MkWinChildCreateRedirect failed..."); # endif # endif /* * Either the provider is outbooked or we're not in a context (like * standalone) where we get help with waiting and must to it ourselves */ dwTmp = WaitForSingleObject(hProcess, INFINITE); if (dwTmp != WAIT_OBJECT_0) warnx(pCtx, "WaitForSingleObject failed: %#x\n", dwTmp); if (GetExitCodeProcess(hProcess, &dwTmp)) rcExit = (int)dwTmp; else { warnx(pCtx, "GetExitCodeProcess failed: %u\n", GetLastError()); TerminateProcess(hProcess, 127); rcExit = 127; } CloseHandle(hProcess); *pfIsChildExitCode = K_TRUE; return rcExit; } /** * Tries to locate the executable image. * * This isn't quite perfect yet... * * @returns pszExecutable or pszBuf with valid string. * @param pszExecutable The specified executable. * @param pszBuf Buffer to return a modified path in. * @param cbBuf Size of return buffer. * @param pszPath The search path. */ static const char *kRedirectCreateProcessWindowsFindImage(const char *pszExecutable, char *pszBuf, size_t cbBuf, const char *pszPath) { /* * Analyze the name. */ size_t const cchExecutable = strlen(pszExecutable); BOOL fHavePath = FALSE; BOOL fHaveSuffix = FALSE; size_t off = cchExecutable; while (off > 0) { char ch = pszExecutable[--off]; if (ch == '.') { fHaveSuffix = TRUE; break; } if (ch == '\\' || ch == '/' || ch == ':') { fHavePath = TRUE; break; } } if (!fHavePath) while (off > 0) { char ch = pszExecutable[--off]; if (ch == '\\' || ch == '/' || ch == ':') { fHavePath = TRUE; break; } } /* * If no path, search the path value. */ if (!fHavePath) { char *pszFilename; DWORD cchFound = SearchPathA(pszPath, pszExecutable, fHaveSuffix ? NULL : ".exe", cbBuf, pszBuf, &pszFilename); if (cchFound) return pszBuf; } /* * If no suffix, try add .exe. */ if ( !fHaveSuffix && GetFileAttributesA(pszExecutable) == INVALID_FILE_ATTRIBUTES && cchExecutable + 4 < cbBuf) { memcpy(pszBuf, pszExecutable, cchExecutable); memcpy(&pszBuf[cchExecutable], ".exe", 5); if (GetFileAttributesA(pszBuf) != INVALID_FILE_ATTRIBUTES) return pszBuf; } return pszExecutable; } /** * Turns the orders into input for nt_child_inject_standard_handles and * winchildren.c * * @returns 0 on success, non-zero on failure. * @param pCtx The command execution context. * @param cOrders Number of file operation orders. * @param paOrders The file operation orders. * @param pafReplace Replace (TRUE) or leave alone (FALSE) indicator * for each of the starndard handles. * @param pahChild Array of standard handles for injecting into the * child. Parallel to pafReplace. */ static int kRedirectOrderToWindowsHandles(PKMKBUILTINCTX pCtx, unsigned cOrders, REDIRECTORDERS *paOrders, BOOL pafReplace[3], HANDLE pahChild[3]) { int i; for (i = 0; i < (int)cOrders; i++) { int fdTarget = paOrders[i].fdTarget; assert(fdTarget >= 0 && fdTarget < 3); switch (paOrders[i].enmOrder) { case kRedirectOrder_Open: if ( (paOrders[i].fOpen & O_APPEND) && lseek(paOrders[i].fdSource, 0, SEEK_END) < 0) return err(pCtx, 10, "lseek-to-end failed on %d (for %d)", paOrders[i].fdSource, fdTarget); /* fall thru */ case kRedirectOrder_Dup: pahChild[fdTarget] = (HANDLE)_get_osfhandle(paOrders[i].fdSource); if (pahChild[fdTarget] == NULL || pahChild[fdTarget] == INVALID_HANDLE_VALUE) return err(pCtx, 10, "_get_osfhandle failed on %d (for %d)", paOrders[i].fdSource, fdTarget); break; case kRedirectOrder_Close: pahChild[fdTarget] = NULL; break; default: assert(0); } pafReplace[fdTarget] = TRUE; } return 0; } /** * Alternative approach on windows that use CreateProcess and doesn't require * any serialization wrt handles and CWD. * * @returns 0 on success, non-zero on failure to create. * @param pCtx The command execution context. * @param pszExecutable The child process executable. * @param cArgs Number of arguments. * @param papszArgs The child argument vector. * @param papszEnvVars The child environment vector. * @param pszCwd The current working directory of the child. * @param cOrders Number of file operation orders. * @param paOrders The file operation orders. * @param phProcess Where to return process handle. */ static int kRedirectCreateProcessWindows(PKMKBUILTINCTX pCtx, const char *pszExecutable, int cArgs, char **papszArgs, char **papszEnvVars, const char *pszCwd, unsigned cOrders, REDIRECTORDERS *paOrders, HANDLE *phProcess) { size_t cbArgs; char *pszCmdLine; size_t cbEnv; char *pszzEnv; char *pch; int i; int rc; /* * Start by making the the command line. We just need to put spaces * between the arguments since quote_argv don't the quoting already. */ cbArgs = 0; for (i = 0; i < cArgs; i++) cbArgs += strlen(papszArgs[i]) + 1; pszCmdLine = pch = (char *)malloc(cbArgs); if (!pszCmdLine) return errx(pCtx, 9, "out of memory!"); for (i = 0; i < cArgs; i++) { size_t cch; if (i != 0) *pch++ = ' '; cch = strlen(papszArgs[i]); memcpy(pch, papszArgs[i], cch); pch += cch; } *pch++ = '\0'; assert(pch - pszCmdLine == cbArgs); /* * The environment vector is also simple. */ cbEnv = 0; for (i = 0; papszEnvVars[i]; i++) cbEnv += strlen(papszEnvVars[i]) + 1; cbEnv++; pszzEnv = pch = (char *)malloc(cbEnv); if (pszzEnv) { char szAbsExe[1024]; const char *pszPathVal = NULL; STARTUPINFOA StartupInfo; PROCESS_INFORMATION ProcInfo = { NULL, NULL, 0, 0 }; for (i = 0; papszEnvVars[i]; i++) { size_t cbSrc = strlen(papszEnvVars[i]) + 1; memcpy(pch, papszEnvVars[i], cbSrc); if ( !pszPathVal && cbSrc >= 5 && pch[4] == '=' && (pch[0] == 'P' || pch[0] == 'p') && (pch[1] == 'A' || pch[1] == 'a') && (pch[2] == 'T' || pch[2] == 't') && (pch[3] == 'H' || pch[3] == 'h')) pszPathVal = &pch[5]; pch += cbSrc; } *pch++ = '\0'; assert(pch - pszzEnv == cbEnv); /* * Locate the executable. */ pszExecutable = kRedirectCreateProcessWindowsFindImage(pszExecutable, szAbsExe, sizeof(szAbsExe), pszPathVal); /* * Do basic startup info preparation. */ memset(&StartupInfo, 0, sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); GetStartupInfoA(&StartupInfo); StartupInfo.lpReserved2 = 0; /* No CRT file handle + descriptor info possible, sorry. */ StartupInfo.cbReserved2 = 0; StartupInfo.dwFlags &= ~STARTF_USESTDHANDLES; /* * If there are no redirection orders, we're good. */ if (!cOrders) { if (CreateProcessA(pszExecutable, pszCmdLine, NULL /*pProcAttrs*/, NULL /*pThreadAttrs*/, FALSE /*fInheritHandles*/, 0 /*fFlags*/, pszzEnv, pszCwd, &StartupInfo, &ProcInfo)) { CloseHandle(ProcInfo.hThread); *phProcess = ProcInfo.hProcess; # ifndef KMK_BUILTIN_STANDALONE kmk_cache_exec_image_a(pszExecutable); # endif rc = 0; } else rc = errx(pCtx, 10, "CreateProcessA(%s) failed: %u", pszExecutable, GetLastError()); } else { /* * Execute the orders, ending up with three handles we need to * implant into the guest process. * * This isn't 100% perfect wrt O_APPEND, but it'll have to do for now. */ BOOL afReplace[3] = { FALSE, FALSE, FALSE }; HANDLE ahChild[3] = { NULL, NULL, NULL }; rc = kRedirectOrderToWindowsHandles(pCtx, cOrders, paOrders, afReplace, ahChild); if (rc == 0) { /* * Start the process in suspended animation so we can inject handles. */ if (CreateProcessA(pszExecutable, pszCmdLine, NULL /*pProcAttrs*/, NULL /*pThreadAttrs*/, FALSE /*fInheritHandles*/, CREATE_SUSPENDED, pszzEnv, pszCwd, &StartupInfo, &ProcInfo)) { unsigned i; /* Inject the handles and try make it start executing. */ char szErrMsg[128]; rc = nt_child_inject_standard_handles(ProcInfo.hProcess, afReplace, ahChild, szErrMsg, sizeof(szErrMsg)); if (rc) rc = errx(pCtx, 10, "%s", szErrMsg); else if (!ResumeThread(ProcInfo.hThread)) rc = errx(pCtx, 10, "ResumeThread failed: %u", GetLastError()); /* Duplicate the write end of any stdin pipe handles into the child. */ for (i = 0; i < cOrders; i++) if (paOrders[i].fdOtherPipeEnd >= 0) { HANDLE hIgnored = INVALID_HANDLE_VALUE; HANDLE hPipeW = (HANDLE)_get_osfhandle(paOrders[i].fdOtherPipeEnd); if (!DuplicateHandle(GetCurrentProcess(), hPipeW, ProcInfo.hProcess, &hIgnored, 0 /*fDesiredAccess*/, TRUE /*fInheritable*/, DUPLICATE_SAME_ACCESS)) rc = errx(pCtx, 10, "DuplicateHandle failed on other stdin pipe end %d/%p: %u", paOrders[i].fdOtherPipeEnd, hPipeW, GetLastError()); } /* Kill it if any of that fails. */ if (rc != 0) TerminateProcess(ProcInfo.hProcess, rc); CloseHandle(ProcInfo.hThread); *phProcess = ProcInfo.hProcess; # ifndef KMK_BUILTIN_STANDALONE kmk_cache_exec_image_a(pszExecutable); # endif rc = 0; } else rc = errx(pCtx, 10, "CreateProcessA(%s) failed: %u", pszExecutable, GetLastError()); } } free(pszzEnv); } else rc = errx(pCtx, 9, "out of memory!"); free(pszCmdLine); return rc; } # if !defined(KMK_BUILTIN_STANDALONE) && defined(CONFIG_NEW_WIN_CHILDREN) /** * Pass the problem on to winchildren.c when we're on one of its workers. * * @returns 0 on success, non-zero on failure to create. * @param pCtx The command execution context. * @param pszExecutable The child process executable. * @param cArgs Number of arguments. * @param papszArgs The child argument vector. * @param papszEnvVars The child environment vector. * @param pszCwd The current working directory of the child. * @param cOrders Number of file operation orders. * @param paOrders The file operation orders. * @param phProcess Where to return process handle. * @param pfIsChildExitCode Where to indicate whether the return exit code * is from the child or from our setup efforts. */ static int kRedirectExecProcessWithinOnWorker(PKMKBUILTINCTX pCtx, const char *pszExecutable, int cArgs, char **papszArgs, char **papszEnvVars, const char *pszCwd, unsigned cOrders, REDIRECTORDERS *paOrders, KBOOL *pfIsChildExitCode) { BOOL afReplace[3] = { FALSE, FALSE, FALSE }; HANDLE ahChild[3] = { NULL, NULL, NULL }; int rc = kRedirectOrderToWindowsHandles(pCtx, cOrders, paOrders, afReplace, ahChild); if (rc == 0) { rc = MkWinChildBuiltInExecChild(pCtx->pvWorker, pszExecutable, papszArgs, TRUE /*fQuotedArgv*/, papszEnvVars, pszCwd, afReplace, ahChild); *pfIsChildExitCode = K_TRUE; } return rc; } # endif /* !KMK_BUILTIN_STANDALONE */ #endif /* KBUILD_OS_WINDOWS */ /** * Does the child spawning . * * @returns Exit code. * @param pCtx The command execution context. * @param pszExecutable The child process executable. * @param cArgs Number of arguments. * @param papszArgs The child argument vector. * @param fWatcomBrainDamage Whether MSC need to do quoting according to * weird Watcom WCC rules. * @param papszEnvVars The child environment vector. * @param pszCwd The current working directory of the child. * @param pszSavedCwd The saved current working directory. This is * NULL if the CWD doesn't need changing. * @param cOrders Number of file operation orders. * @param paOrders The file operation orders. * @param pFileActions The posix_spawn file actions. * @param cVerbosity The verbosity level. * @param pPidSpawned Where to return the PID of the spawned child * when we're inside KMK and we're return without * waiting. * @param pfIsChildExitCode Where to indicate whether the return exit code * is from the child or from our setup efforts. */ static int kRedirectDoSpawn(PKMKBUILTINCTX pCtx, const char *pszExecutable, int cArgs, char **papszArgs, int fWatcomBrainDamage, char **papszEnvVars, const char *pszCwd, const char *pszSavedCwd, unsigned cOrders, REDIRECTORDERS *paOrders, #ifdef USE_POSIX_SPAWN posix_spawn_file_actions_t *pFileActions, #endif unsigned cVerbosity, #ifdef KMK pid_t *pPidSpawned, #endif KBOOL *pfIsChildExitCode) { int rcExit = 0; int i; #ifdef _MSC_VER char **papszArgsOriginal = papszArgs; #endif *pfIsChildExitCode = K_FALSE; #ifdef _MSC_VER /* * Do MSC parameter quoting. */ papszArgs = malloc((cArgs + 1) * sizeof(papszArgs[0])); if (papszArgs) memcpy(papszArgs, papszArgsOriginal, (cArgs + 1) * sizeof(papszArgs[0])); else return errx(pCtx, 9, "out of memory!"); rcExit = quote_argv(cArgs, papszArgs, fWatcomBrainDamage, 0 /*fFreeOrLeak*/); if (rcExit == 0) #endif { /* * Display what we're about to execute if we're in verbose mode. */ if (cVerbosity > 0) { for (i = 0; i < cArgs; i++) warnx(pCtx, "debug: argv[%i]=%s", i, papszArgs[i]); for (i = 0; i < (int)cOrders; i++) switch (paOrders[i].enmOrder) { case kRedirectOrder_Close: warnx(pCtx, "debug: close %d\n", paOrders[i].fdTarget); break; case kRedirectOrder_Dup: warnx(pCtx, "debug: dup %d to %d\n", paOrders[i].fdSource, paOrders[i].fdTarget); break; case kRedirectOrder_Open: warnx(pCtx, "debug: open '%s' (%#x) as [%d ->] %d\n", paOrders[i].pszFilename, paOrders[i].fOpen, paOrders[i].fdSource, paOrders[i].fdTarget); break; default: warnx(pCtx, "error! invalid enmOrder=%d", paOrders[i].enmOrder); assert(0); break; } if (pszSavedCwd) warnx(pCtx, "debug: chdir %s\n", pszCwd); } #ifndef KBUILD_OS_WINDOWS /* * Change working directory if so requested. */ if (pszSavedCwd) { if (chdir(pszCwd) < 0) rcExit = errx(pCtx, 10, "Failed to change directory to '%s'", pszCwd); } #endif /* KBUILD_OS_WINDOWS */ if (rcExit == 0) { # if !defined(USE_POSIX_SPAWN) && !defined(KBUILD_OS_WINDOWS) /* * Execute the file orders. */ FILE *pWorkingStdErr = NULL; rcExit = kRedirectExecFdOrders(pCtx, cOrders, paOrders, &pWorkingStdErr); if (rcExit == 0) # endif { # ifdef KMK /* * We're spawning from within kmk. */ # ifdef KBUILD_OS_WINDOWS /* Windows is slightly complicated due to handles and winchildren.c. */ if (pPidSpawned) *pPidSpawned = 0; # ifdef CONFIG_NEW_WIN_CHILDREN if (pCtx->pvWorker && !pPidSpawned) rcExit = kRedirectExecProcessWithinOnWorker(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars, pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, pfIsChildExitCode); else # endif { HANDLE hProcess = INVALID_HANDLE_VALUE; rcExit = kRedirectCreateProcessWindows(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars, pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, &hProcess); if (rcExit == 0) rcExit = kRedirectPostnatalCareOnWindows(pCtx, hProcess, cVerbosity, pPidSpawned, pfIsChildExitCode); } # elif defined(KBUILD_OS_OS2) *pPidSpawned = _spawnvpe(P_NOWAIT, pszExecutable, papszArgs, papszEnvVars); kRedirectRestoreFdOrders(pCtx, cOrders, paOrders, &pWorkingStdErr); if (*pPidSpawned != -1) { if (cVerbosity > 0) warnx(pCtx, "debug: spawned %d", *pPidSpawned); } else { rcExit = err(pCtx, 10, "_spawnvpe(%s) failed", pszExecutable); *pPidSpawned = 0; } # else rcExit = posix_spawnp(pPidSpawned, pszExecutable, pFileActions, NULL /*pAttr*/, papszArgs, papszEnvVars); if (rcExit == 0) { if (cVerbosity > 0) warnx(pCtx, "debug: spawned %d", *pPidSpawned); } else { rcExit = errx(pCtx, 10, "posix_spawnp(%s) failed: %s", pszExecutable, strerror(rcExit)); *pPidSpawned = 0; } # endif #else /* !KMK */ /* * Spawning from inside the kmk_redirect executable. */ # ifdef KBUILD_OS_WINDOWS HANDLE hProcess = INVALID_HANDLE_VALUE; rcExit = kRedirectCreateProcessWindows(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars, pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, &hProcess); if (rcExit == 0) { DWORD dwWait; do dwWait = WaitForSingleObject(hProcess, INFINITE); while (dwWait == WAIT_IO_COMPLETION || dwWait == WAIT_TIMEOUT); dwWait = 11; if (GetExitCodeProcess(hProcess, &dwWait)) { *pfIsChildExitCode = K_TRUE; rcExit = dwWait; } else rcExit = errx(pCtx, 11, "GetExitCodeProcess(%s) failed: %u", pszExecutable, GetLastError()); } #elif defined(KBUILD_OS_OS2) errno = 0; rcExit = (int)_spawnvpe(P_WAIT, pszExecutable, papszArgs, papszEnvVars); kRedirectRestoreFdOrders(pCtx, cOrders, paOrders, &pWorkingStdErr); if (rcExit != -1 || errno == 0) { *pfIsChildExitCode = K_TRUE; if (cVerbosity > 0) warnx(pCtx, "debug: exit code: %d", rcExit); } else rcExit = err(pCtx, 10, "_spawnvpe(%s) failed", pszExecutable); # else pid_t pidChild = 0; rcExit = posix_spawnp(&pidChild, pszExecutable, pFileActions, NULL /*pAttr*/, papszArgs, papszEnvVars); if (rcExit == 0) { *pfIsChildExitCode = K_TRUE; if (cVerbosity > 0) warnx(pCtx, "debug: spawned %d", pidChild); /* Wait for the child. */ for (;;) { int rcExitRaw = 1; pid_t pid = waitpid(pidChild, &rcExitRaw, 0 /*block*/); if (pid == pidChild) { rcExit = WIFEXITED(rcExitRaw) ? WEXITSTATUS(rcExitRaw) : 63; if (cVerbosity > 0) warnx(pCtx, "debug: %d exit code: %d (%d)", pidChild, rcExit, rcExitRaw); break; } if ( errno != EINTR # ifdef ERESTART && errno != ERESTART # endif ) { rcExit = err(pCtx, 11, "waitpid failed"); kill(pidChild, SIGKILL); break; } } } else rcExit = errx(pCtx, 10, "posix_spawnp(%s) failed: %s", pszExecutable, strerror(rcExit)); # endif #endif /* !KMK */ } } #ifndef KBUILD_OS_WINDOWS /* * Restore the current directory. */ if (pszSavedCwd) { if (chdir(pszSavedCwd) < 0) warn(pCtx, "Failed to restore directory to '%s'", pszSavedCwd); } #endif } #ifdef _MSC_VER else rcExit = errx(pCtx, 9, "quite_argv failed: %u", rcExit); /* Restore the original argv strings, freeing the quote_argv replacements. */ i = cArgs; while (i-- > 0) if (papszArgs[i] != papszArgsOriginal[i]) free(papszArgs[i]); free(papszArgs); #endif return rcExit; } /** * The function that does almost everything here... ugly. */ int kmk_builtin_redirect(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned) { int rcExit = 0; KBOOL fChildExitCode = K_FALSE; #ifdef USE_POSIX_SPAWN posix_spawn_file_actions_t FileActions; #endif unsigned cOrders = 0; REDIRECTORDERS aOrders[32]; unsigned cExitCodeTranslations = 0; struct { int rcExitFrom, rcExitTo; } aExitCodeTranslations[8]; int iArg; const char *pszExecutable = NULL; char **papszEnvVars = NULL; unsigned cAllocatedEnvVars; unsigned cEnvVars; int fWatcomBrainDamage = 0; int cVerbosity = 0; char *pszSavedCwd = NULL; size_t const cbCwdBuf = GET_PATH_MAX; PATH_VAR(szCwd); #ifdef KBUILD_OS_OS2 ULONG ulLibPath; char *apszSavedLibPaths[LIBPATHSTRICT + 1] = { NULL, NULL, NULL, NULL }; #endif if (argc <= 1) return kmk_redirect_usage(pCtx, 1); /* * Create default program environment. */ #if defined(KMK) && defined(KBUILD_OS_WINDOWS) if (getcwd_fs(szCwd, cbCwdBuf) != NULL) #else if (getcwd(szCwd, cbCwdBuf) != NULL) #endif { /* likely */ } else return err(pCtx, 9, "getcwd failed"); /* We start out with a read-only environment from kmk or the crt, and will duplicate it if we make changes to it. */ cAllocatedEnvVars = 0; papszEnvVars = envp; cEnvVars = 0; while (papszEnvVars[cEnvVars] != NULL) cEnvVars++; #ifdef USE_POSIX_SPAWN /* * Init posix attributes with stdout/err redirections according to pCtx. */ rcExit = posix_spawn_file_actions_init(&FileActions); if (rcExit != 0) rcExit = errx(pCtx, 9, "posix_spawn_file_actions_init failed: %s", strerror(rcExit)); # if !defined(KMK_BUILTIN_STANDALONE) && !defined(CONFIG_WITH_OUTPUT_IN_MEMORY) if (pCtx->pOut && rcExit == 0) { if (pCtx->pOut->out >= 0) { rcExit = posix_spawn_file_actions_adddup2(&FileActions, pCtx->pOut->out, 1); if (rcExit != 0) rcExit = errx(pCtx, 2, "posix_spawn_file_actions_addclose(%d, 1) failed: %s", pCtx->pOut->out, strerror(rcExit)); } if (pCtx->pOut->err >= 0 && rcExit == 0) { rcExit = posix_spawn_file_actions_adddup2(&FileActions, pCtx->pOut->err, 2); if (rcExit != 0) rcExit = errx(pCtx, 2, "posix_spawn_file_actions_addclose(%d, 1) failed: %s", pCtx->pOut->err, strerror(rcExit)); } } # endif #endif /* * Parse arguments. */ for (iArg = 1; rcExit == 0 && iArg < argc; iArg++) { char *pszArg = argv[iArg]; if (*pszArg == '-') { int fd; char chOpt; const char *pszValue; chOpt = *++pszArg; pszArg++; if (chOpt == '-') { /* '--' indicates where the bits to execute start. Check if we're relaunching ourselves here and just continue parsing if we are. */ if (*pszArg == '\0') { iArg++; if ( iArg >= argc || ( strcmp(argv[iArg], "kmk_builtin_redirect") != 0 && strcmp(argv[iArg], argv[0]) != 0)) break; continue; } if ( strcmp(pszArg, "wcc-brain-damage") == 0 || strcmp(pszArg, "watcom-brain-damage") == 0) { fWatcomBrainDamage = 1; continue; } /* convert to short. */ if (strcmp(pszArg, "help") == 0) chOpt = 'h'; else if (strcmp(pszArg, "version") == 0) chOpt = 'V'; else if ( strcmp(pszArg, "set") == 0 || strcmp(pszArg, "env") == 0) chOpt = 'E'; else if (strcmp(pszArg, "append") == 0) chOpt = 'A'; else if (strcmp(pszArg, "prepend") == 0) chOpt = 'D'; else if (strcmp(pszArg, "unset") == 0) chOpt = 'U'; else if ( strcmp(pszArg, "zap-env") == 0 || strcmp(pszArg, "ignore-environment") == 0 /* GNU env compatibility. */ ) chOpt = 'Z'; else if (strcmp(pszArg, "chdir") == 0) chOpt = 'C'; else if (strcmp(pszArg, "close") == 0) chOpt = 'c'; else if (strcmp(pszArg, "verbose") == 0) chOpt = 'v'; else if (strcmp(pszArg, "stdin-pipe") == 0) chOpt = 'I'; else if (strcmp(pszArg, "translate-exitcode") == 0) chOpt = 'X'; else { errx(pCtx, 2, "Unknown option: '%s'", pszArg - 2); rcExit = kmk_redirect_usage(pCtx, 1); break; } pszArg = ""; } /* * Deal with the obligatory help and version switches first to get them out of the way. */ if (chOpt == 'h') { kmk_redirect_usage(pCtx, 0); rcExit = -1; break; } if (chOpt == 'V') { kbuild_version(argv[0]); rcExit = -1; break; } /* * Get option value first, if the option takes one. */ if ( chOpt == 'E' || chOpt == 'A' || chOpt == 'D' || chOpt == 'U' || chOpt == 'C' || chOpt == 'c' || chOpt == 'd' || chOpt == 'e' || chOpt == 'X') { if (*pszArg != '\0') pszValue = pszArg + (*pszArg == ':' || *pszArg == '='); else if (++iArg < argc) pszValue = argv[iArg]; else { errx(pCtx, 2, "syntax error: Option -%c requires a value!", chOpt); rcExit = kmk_redirect_usage(pCtx, 1); break; } } else pszValue = NULL; /* * Environment switch? */ if (chOpt == 'E') { const char *pchEqual = strchr(pszValue, '='); #ifdef KBUILD_OS_OS2 if ( strncmp(pszValue, TUPLE("BEGINLIBPATH=")) == 0 || strncmp(pszValue, TUPLE("ENDLIBPATH=")) == 0 || strncmp(pszValue, TUPLE("LIBPATHSTRICT=")) == 0) { ULONG ulVar = *pszValue == 'B' ? BEGIN_LIBPATH : *pszValue == 'E' ? END_LIBPATH : LIBPATHSTRICT; APIRET rc; if (apszSavedLibPaths[ulVar] == NULL) { /* The max length is supposed to be 1024 bytes. */ apszSavedLibPaths[ulVar] = calloc(1024, 2); if (apszSavedLibPaths[ulVar]) { rc = DosQueryExtLIBPATH(apszSavedLibPaths[ulVar], ulVar); if (rc) { rcExit = errx(pCtx, 9, "DosQueryExtLIBPATH(,%u) failed: %lu", ulVar, rc); free(apszSavedLibPaths[ulVar]); apszSavedLibPaths[ulVar] = NULL; } } else rcExit = errx(pCtx, 9, "out of memory!"); } if (rcExit == 0) { rc = DosSetExtLIBPATH(pchEqual + 1, ulVar); if (rc) rcExit = errx(pCtx, 9, "error: DosSetExtLibPath(\"%s\", %.*s (%lu)): %lu", pchEqual, pchEqual - pszValue, pchEqual + 1, ulVar, rc); } continue; } #endif /* KBUILD_OS_OS2 */ /* We differ from kSubmit here and use putenv sematics. */ if (pchEqual) { if (pchEqual[1] != '\0') rcExit = kBuiltinOptEnvSet(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); else { char *pszCopy = strdup(pszValue); if (pszCopy) { pszCopy[pchEqual - pszValue] = '\0'; rcExit = kBuiltinOptEnvUnset(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszCopy); free(pszCopy); } else rcExit = errx(pCtx, 1, "out of memory!"); } continue; } /* Simple unset. */ chOpt = 'U'; } /* * Append or prepend value to and environment variable. */ if (chOpt == 'A' || chOpt == 'D') { #ifdef KBUILD_OS_OS2 if ( strcmp(pszValue, "BEGINLIBPATH") == 0 || strcmp(pszValue, "ENDLIBPATH") == 0 || strcmp(pszValue, "LIBPATHSTRICT") == 0) rcExit = errx(pCtx, 2, "error: '%s' cannot currently be appended or prepended to. Please use -E/--set for now.", pszValue); else #endif if (chOpt == 'A') rcExit = kBuiltinOptEnvAppend(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); else rcExit = kBuiltinOptEnvPrepend(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); continue; } /* * Unset environment variable. */ if (chOpt == 'U') { #ifdef KBUILD_OS_OS2 if ( strcmp(pszValue, "BEGINLIBPATH") == 0 || strcmp(pszValue, "ENDLIBPATH") == 0 || strcmp(pszValue, "LIBPATHSTRICT") == 0) rcExit = errx(pCtx, 2, "error: '%s' cannot be unset, only set to an empty value using -E/--set.", pszValue); else #endif rcExit = kBuiltinOptEnvUnset(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); continue; } /* * Zap environment switch? */ if (chOpt == 'Z') /* (no -i option here, as it's reserved for stdin) */ { rcExit = kBuiltinOptEnvZap(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity); continue; } /* * Change directory switch? */ if (chOpt == 'C') { if (pszSavedCwd == NULL) pszSavedCwd = strdup(szCwd); if (pszSavedCwd) rcExit = kBuiltinOptChDir(pCtx, szCwd, cbCwdBuf, pszValue); else rcExit = err(pCtx, 9, "out of memory!"); continue; } /* * Verbose operation switch? */ if (chOpt == 'v') { cVerbosity++; continue; } /* * Executable image other than the first argument following '--'. */ if (chOpt == 'e') { pszExecutable = pszValue; continue; } /* * Exit code translation: from[=to] */ if (chOpt == 'X') { int rcExitTo = 0; char *pszEqual; int rcExitFrom = (int)strtol(pszValue, &pszEqual, 0); if (pszEqual == pszValue) rcExit = errx(pCtx, 2, "error: failed to convert 1st part of '--translate-exitcode %s' to a number", pszValue); else if (!pszEqual || !*pszEqual) rcExitTo = 0; else if (*pszEqual != '=') rcExit = errx(pCtx, 2, "syntax error: expected '=' to separate the two values in: '--translate-exitcode %s'", pszValue); else { char *pszEnd = 0; rcExitTo = (int)strtol(++pszEqual, &pszEnd, 0); if (pszEnd == pszEqual) rcExit = errx(pCtx, 2, "error: failed to convert 2nd half of '--translate-exitcode %s' to a number", pszValue); else if (pszEnd && *pszEnd != '\0') rcExit = errx(pCtx, 2, "error: unexpected trailing chars in: '--translate-exitcode %s'", pszValue); } if (cExitCodeTranslations >= K_ELEMENTS(aExitCodeTranslations)) rcExit = errx(pCtx, 2, "error: too many exit code translations"); else if (rcExit == 0) { aExitCodeTranslations[cExitCodeTranslations].rcExitFrom = rcExitFrom; aExitCodeTranslations[cExitCodeTranslations].rcExitTo = rcExitTo; cExitCodeTranslations++; } continue; } /* * Okay, it is some file descriptor operation. Make sure we've got room for it. */ if (cOrders + 1 < K_ELEMENTS(aOrders)) { aOrders[cOrders].fdTarget = -1; aOrders[cOrders].fdSource = -1; aOrders[cOrders].fOpen = 0; aOrders[cOrders].fRemoveOnFailure = 0; aOrders[cOrders].pszFilename = NULL; aOrders[cOrders].fdOtherPipeEnd = -1; #ifndef USE_POSIX_SPAWN aOrders[cOrders].fdSaved = -1; #endif } else { rcExit = errx(pCtx, 2, "error: too many file actions (max: %d)", K_ELEMENTS(aOrders)); break; } if (chOpt == 'c') { /* * Close the specified file descriptor (no stderr/out/in aliases). */ char *pszTmp; fd = (int)strtol(pszValue, &pszTmp, 0); if (pszTmp == pszValue || *pszTmp != '\0') rcExit = errx(pCtx, 2, "error: failed to convert '%s' to a number", pszValue); else if (fd < 0) rcExit = errx(pCtx, 2, "error: negative fd %d (%s)", fd, pszValue); #ifdef ONLY_TARGET_STANDARD_HANDLES else if (fd > 2) rcExit = errx(pCtx, 2, "error: %d is not a standard descriptor number", fd); #endif else { aOrders[cOrders].enmOrder = kRedirectOrder_Close; aOrders[cOrders].fdTarget = fd; cOrders++; #ifdef USE_POSIX_SPAWN rcExit = posix_spawn_file_actions_addclose(&FileActions, fd); if (rcExit != 0) rcExit = errx(pCtx, 2, "posix_spawn_file_actions_addclose(%d) failed: %s", fd, strerror(rcExit)); #endif } } else if (chOpt == 'd') { /* * Duplicate file handle. Value is fdTarget=fdSource */ char *pszEqual; fd = (int)strtol(pszValue, &pszEqual, 0); if (pszEqual == pszValue) rcExit = errx(pCtx, 2, "error: failed to convert target descriptor of '-d %s' to a number", pszValue); else if (fd < 0) rcExit = errx(pCtx, 2, "error: negative target descriptor %d ('-d %s')", fd, pszValue); #ifdef ONLY_TARGET_STANDARD_HANDLES else if (fd > 2) rcExit = errx(pCtx, 2, "error: target %d is not a standard descriptor number", fd); #endif else if (*pszEqual != '=') rcExit = errx(pCtx, 2, "syntax error: expected '=' to follow target descriptor: '-d %s'", pszValue); else { char *pszEnd; int fdSource = (int)strtol(++pszEqual, &pszEnd, 0); if (pszEnd == pszEqual || *pszEnd != '\0') rcExit = errx(pCtx, 2, "error: failed to convert source descriptor of '-d %s' to a number", pszValue); else if (fdSource < 0) rcExit = errx(pCtx, 2, "error: negative source descriptor %d ('-d %s')", fdSource, pszValue); else { aOrders[cOrders].enmOrder = kRedirectOrder_Dup; aOrders[cOrders].fdTarget = fd; aOrders[cOrders].fdSource = fdSource; cOrders++; #ifdef USE_POSIX_SPAWN rcExit = posix_spawn_file_actions_adddup2(&FileActions, fdSource, fd); if (rcExit != 0) rcExit = errx(pCtx, 2, "posix_spawn_file_actions_adddup2(%d) failed: %s", fdSource, fd, strerror(rcExit)); #endif } } } else if (chOpt == 'I') { /* * Replace stdin with the read end of an anonymous pipe. */ int aFds[2] = { -1, -1 }; rcExit = kRedirectCreateStdInPipeWithoutConflict(pCtx, aFds, cOrders, aOrders, 0 /*fdTarget*/); if (rcExit == 0) { aOrders[cOrders].enmOrder = kRedirectOrder_Dup; aOrders[cOrders].fdTarget = 0; aOrders[cOrders].fdSource = aFds[0]; aOrders[cOrders].fdOtherPipeEnd = aFds[1]; cOrders++; #ifdef USE_POSIX_SPAWN rcExit = posix_spawn_file_actions_adddup2(&FileActions, aFds[0], 0); if (rcExit != 0) rcExit = errx(pCtx, 2, "posix_spawn_file_actions_adddup2(0) failed: %s", strerror(rcExit)); #endif } } else { /* * Open file as a given file descriptor. */ int fdOpened; int fOpen; /* mode */ switch (chOpt) { case 'r': chOpt = *pszArg++; if (chOpt == '+') { fOpen = O_RDWR; chOpt = *pszArg++; } else fOpen = O_RDONLY; break; case 'w': chOpt = *pszArg++; if (chOpt == '+') { fOpen = O_RDWR | O_CREAT | O_TRUNC; chOpt = *pszArg++; } else fOpen = O_WRONLY | O_CREAT | O_TRUNC; aOrders[cOrders].fRemoveOnFailure = 1; break; case 'a': chOpt = *pszArg++; if (chOpt == '+') { fOpen = O_RDWR | O_CREAT | O_APPEND; chOpt = *pszArg++; } else fOpen = O_WRONLY | O_CREAT | O_APPEND; break; case 'i': /* make sure stdin is read-only. */ fOpen = O_RDONLY; break; case '+': rcExit = errx(pCtx, 2, "syntax error: Unexpected '+' in '%s'", argv[iArg]); continue; default: fOpen = O_RDWR | O_CREAT | O_TRUNC; aOrders[cOrders].fRemoveOnFailure = 1; break; } /* binary / text modifiers */ switch (chOpt) { case 'b': chOpt = *pszArg++; default: #ifdef O_BINARY fOpen |= O_BINARY; #elif defined(_O_BINARY) fOpen |= _O_BINARY; #endif break; case 't': #ifdef O_TEXT fOpen |= O_TEXT; #elif defined(_O_TEXT) fOpen |= _O_TEXT; #endif chOpt = *pszArg++; break; } /* convert to file descriptor number */ switch (chOpt) { case 'i': fd = 0; break; case 'o': fd = 1; break; case 'e': fd = 2; break; case '0': if (*pszArg == '\0') { fd = 0; break; } /* fall thru */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': pszValue = pszArg - 1; fd = (int)strtol(pszValue, &pszArg, 0); if (pszArg == pszValue) rcExit = errx(pCtx, 2, "error: failed to convert '%s' to a number", argv[iArg]); else if (fd < 0) rcExit = errx(pCtx, 2, "error: negative fd %d (%s)", fd, argv[iArg]); #ifdef ONLY_TARGET_STANDARD_HANDLES else if (fd > 2) rcExit = errx(pCtx, 2, "error: %d is not a standard descriptor number", fd); #endif else break; continue; /* * Invalid argument. */ default: rcExit = errx(pCtx, 2, "error: failed to convert '%s' ('%s') to a file descriptor", pszArg, argv[iArg]); continue; } /* * Check for the filename. */ if (*pszArg != '\0') { if (*pszArg != ':' && *pszArg != '=') { rcExit = errx(pCtx, 2, "syntax error: characters following the file descriptor: '%s' ('%s')", pszArg, argv[iArg]); break; } pszArg++; } else if (++iArg < argc) pszArg = argv[iArg]; else { rcExit = errx(pCtx, 2, "syntax error: missing filename argument."); break; } /* * Open the file. We could've used posix_spawn_file_actions_addopen here, * but that means complicated error reporting. So, since we need to do * this for windows anyway, just do it the same way everywhere. */ fdOpened = kRedirectOpenWithoutConflict(pCtx, pszArg, fOpen, 0666, cOrders, aOrders, aOrders[cOrders].fRemoveOnFailure, fd); if (fdOpened >= 0) { aOrders[cOrders].enmOrder = kRedirectOrder_Open; aOrders[cOrders].fdTarget = fd; aOrders[cOrders].fdSource = fdOpened; aOrders[cOrders].fOpen = fOpen; aOrders[cOrders].pszFilename = pszArg; cOrders++; #ifdef USE_POSIX_SPAWN if (fdOpened != fd) { rcExit = posix_spawn_file_actions_adddup2(&FileActions, fdOpened, fd); if (rcExit != 0) rcExit = err(pCtx, 9, "posix_spawn_file_actions_adddup2(,%d [%s], %d) failed: %s", fdOpened, fd, pszArg, strerror(rcExit)); } #endif } else rcExit = 9; } } else { errx(pCtx, 2, "syntax error: Invalid argument '%s'.", argv[iArg]); rcExit = kmk_redirect_usage(pCtx, 1); } } if (!pszExecutable) pszExecutable = argv[iArg]; /* * Make sure there's something to execute. */ if (rcExit == 0 && iArg < argc) { /* * Do the spawning in a separate function (main is far to large as it is by now). */ rcExit = kRedirectDoSpawn(pCtx, pszExecutable, argc - iArg, &argv[iArg], fWatcomBrainDamage, papszEnvVars, szCwd, pszSavedCwd, #ifdef USE_POSIX_SPAWN cOrders, aOrders, &FileActions, cVerbosity, #else cOrders, aOrders, cVerbosity, #endif #ifdef KMK pPidSpawned, #endif &fChildExitCode); /* Do exit code translations if rcExit is a child exit code. */ if (fChildExitCode) while (cExitCodeTranslations-- > 0) if (aExitCodeTranslations[cExitCodeTranslations].rcExitFrom == rcExit) { if (cVerbosity > 0) warnx(pCtx, "info: translating exit code %d to %d", rcExit, aExitCodeTranslations[cExitCodeTranslations].rcExitTo); rcExit = aExitCodeTranslations[cExitCodeTranslations].rcExitTo; break; } } else if (rcExit == 0) { errx(pCtx, 2, "syntax error: nothing to execute!"); rcExit = kmk_redirect_usage(pCtx, 1); } /* Help and version sets rcExit to -1. Change it to zero. */ else if (rcExit == -1) rcExit = 0; /* * Cleanup. */ kBuiltinOptEnvCleanup(&papszEnvVars, cEnvVars, &cAllocatedEnvVars); if (pszSavedCwd) free(pszSavedCwd); kRedirectCleanupFdOrders(cOrders, aOrders, rcExit != 0 && !fChildExitCode); #ifdef USE_POSIX_SPAWN posix_spawn_file_actions_destroy(&FileActions); #endif #ifdef KBUILD_OS_OS2 for (ulLibPath = 0; ulLibPath < K_ELEMENTS(apszSavedLibPaths); ulLibPath++) if (apszSavedLibPaths[ulLibPath] != NULL) { APIRET rc = DosSetExtLIBPATH(apszSavedLibPaths[ulLibPath], ulLibPath); if (rc != 0) warnx(pCtx, "DosSetExtLIBPATH('%s',%u) failed with %u when restoring the original values!", apszSavedLibPaths[ulLibPath], ulLibPath, rc); free(apszSavedLibPaths[ulLibPath]); } #endif return rcExit; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_redirect", NULL }; return kmk_builtin_redirect(argc, argv, envp, &Ctx, NULL, NULL); } #endif kbuild-3686/src/kmk/kmkbuiltin/kDepObj.c0000664000175000017500000012574315053010074020127 0ustar locutuslocutus/* $Id: kDepObj.c 3364 2020-06-08 19:29:42Z bird $ */ /** @file * kDepObj - Extract dependency information from an object file. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #define MSCFAKES_NO_WINDOWS_H #include #include #include #include #include #include #include #if !defined(_MSC_VER) # include #else # include typedef intptr_t ssize_t; #endif #include "k/kDefs.h" #include "k/kTypes.h" #include "k/kLdrFmts/pe.h" #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "kDep.h" #include "err.h" #include "kmkbuiltin.h" /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ #if 0 # define dprintf(a) printf a # define dump(pb, cb, offBase) depHexDump(pb,cb,offBase) # define WITH_DPRINTF #else # define dprintf(a) do {} while (0) # define dump(pb, cb, offBase) do {} while (0) # undef WITH_DPRINTF #endif /** @name OMF defines * @{ */ #define KDEPOMF_THEADR 0x80 #define KDEPOMF_LHEADR 0x82 #define KDEPOMF_COMENT 0x88 #define KDEPOMF_CMTCLS_DEPENDENCY 0xe9 #define KDEPOMF_CMTCLS_DBGTYPE 0xa1 #define KDEPOMF_LINNUM 0x94 #define KDEPOMF_LINNUM32 0x95 /** @} */ /******************************************************************************* * Structures and Typedefs * *******************************************************************************/ /** @name OMF Structures * @{ */ #pragma pack(1) /** OMF record header. */ typedef struct KDEPOMFHDR { /** The record type. */ KU8 bType; /** The size of the record, excluding this header. */ KU16 cbRec; } KDEPOMFHDR; typedef KDEPOMFHDR *PKDEPOMFHDR; typedef const KDEPOMFHDR *PCKDEPOMFHDR; /** OMF string. */ typedef struct KDEPOMFSTR { KU8 cch; char ach[1]; } KDEPOMFSTR; typedef KDEPOMFSTR *PKDEPOMFSTR; typedef const KDEPOMFSTR *PCKDEPOMFSTR; /** THEADR/LHEADR. */ typedef struct KDEPOMFTHEADR { KDEPOMFHDR Hdr; KDEPOMFSTR Name; } KDEPOMFTHEADR; typedef KDEPOMFTHEADR *PKDEPOMFTHEADR; typedef const KDEPOMFTHEADR *PCKDEPOMFTHEADR; /** Dependency File. */ typedef struct KDEPOMFDEPFILE { KDEPOMFHDR Hdr; KU8 fType; KU8 bClass; KU16 wDosTime; KU16 wDosDate; KDEPOMFSTR Name; } KDEPOMFDEPFILE; typedef KDEPOMFDEPFILE *PKDEPOMFDEPFILE; typedef const KDEPOMFDEPFILE *PCKDEPOMFDEPFILE; #pragma pack() /** @} */ /** @name COFF Structures * @{ */ #pragma pack(1) typedef struct KDEPCVSYMHDR { /** The record size minus the size field. */ KU16 cb; /** The record type. */ KU16 uType; } KDEPCVSYMHDR; typedef KDEPCVSYMHDR *PKDEPCVSYMHDR; typedef const KDEPCVSYMHDR *PCKDEPCVSYMHDR; /** @name Selection of KDEPCVSYMHDR::uType values. * @{ */ #define K_CV8_S_MSTOOL KU16_C(0x1116) /** @} */ typedef struct KDEPCV8SYMHDR { /** The record type. */ KU32 uType; /** The record size minus the size field. */ KU32 cb; } KDEPCV8SYMHDR; typedef KDEPCV8SYMHDR *PKDEPCV8SYMHDR; typedef const KDEPCV8SYMHDR *PCKDEPCV8SYMHDR; /** @name Known KDEPCV8SYMHDR::uType Values. * @{ */ #define K_CV8_SYMBOL_INFO KU32_C(0x000000f1) #define K_CV8_LINE_NUMBERS KU32_C(0x000000f2) #define K_CV8_STRING_TABLE KU32_C(0x000000f3) #define K_CV8_SOURCE_FILES KU32_C(0x000000f4) #define K_CV8_COMDAT_XXXXX KU32_C(0x000000f5) /**< no idea about the format... */ /** @} */ #pragma pack() /** @} */ /** * Globals. */ typedef struct KDEPOBJGLOBALS { /** The command execution context. */ PKMKBUILTINCTX pCtx; /** Core instance. */ DEPGLOBALS Core; /** The file. */ const char *pszFile; } KDEPOBJGLOBALS; /** Pointer to kDepObj globals. */ typedef KDEPOBJGLOBALS *PKDEPOBJGLOBALS; /** * Prints an error message. * * @returns rc. * @param pThis kObjDep instance data. * @param rc The return code, for making one line return statements. * @param pszFormat The message format string. * @param ... Format arguments. * @todo Promote this to kDep.c. */ static int kDepErr(PKDEPOBJGLOBALS pThis, int rc, const char *pszFormat, ...) { char szMsg[2048]; va_list va; va_start(va, pszFormat); vsnprintf(szMsg, sizeof(szMsg) - 1, pszFormat, va); va_end(va); szMsg[sizeof(szMsg) - 1] = '\0'; if (pThis->pszFile) warnx(pThis->pCtx, "%s: error: %s", pThis->pszFile, szMsg); else errx(pThis->pCtx, rc, "%s", szMsg); return rc; } /** * Gets an index from the data. * * @returns The index, KU16_MAX on buffer underflow. * @param puData The current data stream position (in/out). * @param pcbLeft Number of bytes left (in/out). */ static KU16 kDepObjOMFGetIndex(KPCUINT *puData, KU16 *pcbLeft) { KU16 u16; if (*pcbLeft >= 1 && *pcbLeft != KU16_MAX) { *pcbLeft -= 1; u16 = *puData->pb++; if (u16 & KU16_C(0x80)) { if (*pcbLeft >= 1) { *pcbLeft -= 1; u16 = ((u16 & KU16_C(0x7f)) << 8) | *puData->pb++; } else u16 = KU16_MAX; } } else u16 = KU16_MAX; return u16; } /** * Parses the OMF file. * * @returns 0 on success, 1 on failure, 2 if no dependencies was found. * @param pThis The kDepObj instance data. * @param pbFile The start of the file. * @param cbFile The file size. */ int kDepObjOMFParse(PKDEPOBJGLOBALS pThis, const KU8 *pbFile, KSIZE cbFile) { PCKDEPOMFHDR pHdr = (PCKDEPOMFHDR)pbFile; KSIZE cbLeft = cbFile; char uDbgType = 0; /* H or C */ KU8 uDbgVer = KU8_MAX; KU32 iSrc = 0; KU32 iMaybeSrc = 0; KU8 uLinNumType = KU8_MAX; KU16 cLinNums = 0; KU32 cLinFiles = 0; KU32 iLinFile = 0; /* * Iterate thru the records until we hit the end or an invalid one. */ while ( cbLeft >= sizeof(*pHdr) && cbLeft >= pHdr->cbRec + sizeof(*pHdr)) { KPCUINT uData; uData.pv = pHdr + 1; /* process selected record types. */ dprintf(("%#07" KUPTR_PRI ": %#04x %#05x\n", (const KU8*)pHdr - pbFile, pHdr->bType, pHdr->cbRec)); switch (pHdr->bType) { /* * The T/L Header contains the source name. When emitting CodeView 4 * and earlier (like masm and watcom does), all includes used by the * line number tables have their own THEADR record. */ case KDEPOMF_THEADR: case KDEPOMF_LHEADR: { PCKDEPOMFTHEADR pTHeadr = (PCKDEPOMFTHEADR)pHdr; if (1 + pTHeadr->Name.cch + 1 != pHdr->cbRec) return kDepErr(pThis, 1, "%#07x - Bad %cHEADR record, length mismatch.", (const KU8*)pHdr - pbFile, pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L'); if ( ( pTHeadr->Name.cch > 2 && pTHeadr->Name.ach[pTHeadr->Name.cch - 2] == '.' && ( pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'o' || pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'O')) || ( pTHeadr->Name.cch > 4 && pTHeadr->Name.ach[pTHeadr->Name.cch - 4] == '.' && ( pTHeadr->Name.ach[pTHeadr->Name.cch - 3] == 'o' || pTHeadr->Name.ach[pTHeadr->Name.cch - 3] == 'O') && ( pTHeadr->Name.ach[pTHeadr->Name.cch - 2] == 'b' || pTHeadr->Name.ach[pTHeadr->Name.cch - 2] == 'B') && ( pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'j' || pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'J')) ) dprintf(("%cHEADR: %.*s [ignored]\n", pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L', pTHeadr->Name.cch, pTHeadr->Name.ach)); else { dprintf(("%cHEADR: %.*s\n", pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L', pTHeadr->Name.cch, pTHeadr->Name.ach)); depAdd(&pThis->Core, pTHeadr->Name.ach, pTHeadr->Name.cch); iMaybeSrc++; } uLinNumType = KU8_MAX; break; } case KDEPOMF_COMENT: { KU8 uClass; if (pHdr->cbRec < 2 + 1) return kDepErr(pThis, 1, "%#07x - Bad COMMENT record, too small.", (const KU8*)pHdr - pbFile); if (uData.pb[0] & 0x3f) return kDepErr(pThis, 1, "%#07x - Bad COMMENT record, reserved flags set.", (const KU8*)pHdr - pbFile); uClass = uData.pb[1]; uData.pb += 2; switch (uClass) { /* * Borland dependency file comment (famously used by wmake and Watcom). */ case KDEPOMF_CMTCLS_DEPENDENCY: { PCKDEPOMFDEPFILE pDep = (PCKDEPOMFDEPFILE)pHdr; if (K_OFFSETOF(KDEPOMFDEPFILE, Name.ach[pDep->Name.cch]) + 1 != pHdr->cbRec + sizeof(*pHdr)) { /* Empty record indicates the end of the dependency files, no need to go on. */ if (pHdr->cbRec == 2 + 1) return 0; return kDepErr(pThis, 1, "%#07lx - Bad DEPENDENCY FILE record, length mismatch. (%u/%u)", (long)((const KU8 *)pHdr - pbFile), K_OFFSETOF(KDEPOMFDEPFILE, Name.ach[pDep->Name.cch]) + 1, (unsigned)(pHdr->cbRec + sizeof(*pHdr))); } depAdd(&pThis->Core, pDep->Name.ach, pDep->Name.cch); iSrc++; break; } /* * Pick up the debug type so we can parse the LINNUM records. */ case KDEPOMF_CMTCLS_DBGTYPE: if (pHdr->cbRec < 2 + 3 + 1) break; /* ignore, Borland used this for something else apparently. */ if ( !(uData.pb[1] == 'C' && uData.pb[2] == 'V') && !(uData.pb[1] == 'H' && uData.pb[2] == 'L')) { dprintf(("Unknown debug type: %c%c (%u)\n", uData.pb[1], uData.pb[2], uData.pb[0])); break; } uDbgType = uData.pb[1]; uDbgVer = uData.pb[0]; dprintf(("Debug Type %s ver %u\n", uDbgType == 'H' ? "HLL" : "CodeView", uDbgVer)); break; } break; /* COMENT */ } /* * LINNUM + THEADR == sigar. */ case KDEPOMF_LINNUM: if (uDbgType == 'C') iMaybeSrc |= KU32_C(0x80000000); dprintf(("LINNUM:\n")); break; /* * The HLL v4 and v6 file names table will include all files when present, which * is perfect for generating dependencies. */ case KDEPOMF_LINNUM32: if ( uDbgType == 'H' && uDbgVer >= 3 && uDbgVer <= 6) { /* skip two indexes (group & segment) */ KU16 cbRecLeft = pHdr->cbRec - 1; KU16 uGrp = kDepObjOMFGetIndex(&uData, &cbRecLeft); KU16 uSeg = kDepObjOMFGetIndex(&uData, &cbRecLeft); if (uSeg == KU16_MAX) return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record", (long)((const KU8 *)pHdr - pbFile)); K_NOREF(uGrp); if (uLinNumType == KU8_MAX) { #ifdef WITH_DPRINTF static const char * const s_apsz[5] = { "source file", "listing file", "source & listing file", "file names table", "path table" }; #endif KU16 uLine; KU8 uReserved; KU16 uSeg2; KU32 cbLinNames; if (cbRecLeft < 2+1+1+2+2+4) return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, too short", (long)((const KU8 *)pHdr - pbFile)); cbRecLeft -= 2+1+1+2+2+4; uLine = *uData.pu16++; uLinNumType = *uData.pu8++; uReserved = *uData.pu8++; K_NOREF(uReserved); cLinNums = *uData.pu16++; K_NOREF(cLinNums); uSeg2 = *uData.pu16++; K_NOREF(uSeg2); cbLinNames = *uData.pu32++; K_NOREF(cbLinNames); dprintf(("LINNUM32: uGrp=%#x uSeg=%#x uSeg2=%#x uLine=%#x (MBZ) uReserved=%#x\n", uGrp, uSeg, uSeg2, uLine, uReserved)); dprintf(("LINNUM32: cLinNums=%#x (%u) cbLinNames=%#x (%u) uLinNumType=%#x (%s)\n", cLinNums, cLinNums, cbLinNames, cbLinNames, uLinNumType, uLinNumType < K_ELEMENTS(s_apsz) ? s_apsz[uLinNumType] : "??")); if (uLine != 0) return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, line %#x (MBZ)", (long)((const KU8 *)pHdr - pbFile), uLine); cLinFiles = iLinFile = KU32_MAX; if ( uLinNumType == 3 /* file names table */ || uLinNumType == 4 /* path table */) cLinNums = 0; /* no line numbers */ else if (uLinNumType > 4) return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, type %#x unknown", (long)((const KU8 *)pHdr - pbFile), uLinNumType); } else dprintf(("LINNUM32: uGrp=%#x uSeg=%#x\n", uGrp, uSeg)); /* Skip file numbers (we parse them to follow the stream correctly). */ if (uLinNumType != 3 && uLinNumType != 4) { static const KU16 s_acbTypes[3] = { 2+2+4, 4+4+4, 2+2+4+4+4 }; KU16 cbEntry = s_acbTypes[uLinNumType]; while (cLinNums && cbRecLeft) { if (cbRecLeft < cbEntry) return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, incomplete line entry", (long)((const KU8 *)pHdr - pbFile)); switch (uLinNumType) { case 0: /* source file */ dprintf((" Line %6" KU16_PRI " of file %2" KU16_PRI " at %#010" KX32_PRI "\n", uData.pu16[0], uData.pu16[1], uData.pu32[1])); break; case 1: /* listing file */ dprintf((" Line %6" KU32_PRI ", statement %6" KU32_PRI " at %#010" KX32_PRI "\n", uData.pu32[0], uData.pu32[1], uData.pu32[2])); break; case 2: /* source & listing file */ dprintf((" Line %6" KU16_PRI " of file %2" KU16_PRI ", listning line %6" KU32_PRI ", statement %6" KU32_PRI " at %#010" KX32_PRI "\n", uData.pu16[0], uData.pu16[1], uData.pu32[1], uData.pu32[2], uData.pu32[3])); break; } uData.pb += cbEntry; cbRecLeft -= cbEntry; cLinNums--; } /* If at end of the announced line number entiries, we may find a file names table here (who is actually emitting this?). */ if (!cLinNums) { uLinNumType = cbRecLeft > 0 ? 3 : KU8_MAX; dprintf(("End-of-line-numbers; uLinNumType=%u cbRecLeft=%#x\n", uLinNumType, cbRecLeft)); } } if (uLinNumType == 3 || uLinNumType == 4) { /* Read the file/path table header (first time only). */ if (cLinFiles == KU32_MAX && iLinFile == KU32_MAX) { KU32 iFirstCol; KU32 cCols; if (cbRecLeft < 4+4+4) return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, incomplete file/path table header", (long)((const KU8 *)pHdr - pbFile)); cbRecLeft -= 4+4+4; iFirstCol = *uData.pu32++; K_NOREF(iFirstCol); cCols = *uData.pu32++; K_NOREF(cCols); cLinFiles = *uData.pu32++; dprintf(("%s table header: cLinFiles=%#" KX32_PRI " (%" KU32_PRI ") iFirstCol=%" KU32_PRI " cCols=%" KU32_PRI"\n", uLinNumType == 3 ? "file names" : "path", cLinFiles, cLinFiles, iFirstCol, cCols)); if (cLinFiles == KU32_MAX) return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, too many file/path table entries.", (long)((const KU8 *)pHdr - pbFile)); iLinFile = 0; } /* Parse the file names / path table. */ while (iLinFile < cLinFiles && cbRecLeft) { KU16 cbName = *uData.pb++; if (cbRecLeft < 1 + cbName) return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, file/path table entry too long.", (long)((const KU8 *)pHdr - pbFile)); iLinFile++; dprintf(("#%" KU32_PRI": %.*s\n", iLinFile, cbName, uData.pch)); if (uLinNumType == 3) { depAdd(&pThis->Core, uData.pch, cbName); iSrc++; } cbRecLeft -= 1 + cbName; uData.pb += cbName; } /* The end? */ if (iLinFile == cLinFiles) { uLinNumType = KU8_MAX; dprintf(("End-of-file/path-table; cbRecLeft=%#x\n", cbRecLeft)); } } } else dprintf(("LINNUM32: Unknown or unsupported format\n")); break; } /* advance */ cbLeft -= pHdr->cbRec + sizeof(*pHdr); pHdr = (PCKDEPOMFHDR)((const KU8 *)(pHdr + 1) + pHdr->cbRec); } if (cbLeft) return kDepErr(pThis, 1, "%#07x - Unexpected EOF. cbLeft=%#x", (const KU8*)pHdr - pbFile, cbLeft); if (iSrc == 0 && iMaybeSrc <= 1) { dprintf(("kDepObjOMFParse: No cylindrical smoking thing: iSrc=0 iMaybeSrc=%#" KX32_PRI"\n", iMaybeSrc)); return 2; } dprintf(("kDepObjOMFParse: iSrc=%" KU32_PRI " iMaybeSrc=%#" KX32_PRI "\n", iSrc, iMaybeSrc)); return 0; } /** * Checks if this file is an OMF file or not. * * @returns K_TRUE if it's OMF, K_FALSE otherwise. * * @param pb The start of the file. * @param cb The file size. */ KBOOL kDepObjOMFTest(const KU8 *pbFile, KSIZE cbFile) { PCKDEPOMFTHEADR pHdr = (PCKDEPOMFTHEADR)pbFile; if (cbFile <= sizeof(*pHdr)) return K_FALSE; if ( pHdr->Hdr.bType != KDEPOMF_THEADR && pHdr->Hdr.bType != KDEPOMF_LHEADR) return K_FALSE; if (pHdr->Hdr.cbRec + sizeof(pHdr->Hdr) >= cbFile) return K_FALSE; if (pHdr->Hdr.cbRec != 1 + pHdr->Name.cch + 1) return K_FALSE; return K_TRUE; } /** * Parses a CodeView 8 symbol section. * * @returns 0 on success, 1 on failure, 2 if no dependencies was found. * @param pThis The kDepObj instance data. * @param pbSyms Pointer to the start of the symbol section. * @param cbSyms Size of the symbol section. */ int kDepObjCOFFParseCV8SymbolSection(PKDEPOBJGLOBALS pThis, const KU8 *pbSyms, KU32 cbSyms) { char const * pchStrTab = NULL; KU32 cbStrTab = 0; KPCUINT uSrcFiles = {0}; KU32 cbSrcFiles = 0; KU32 off = 4; KU32 iSrc = 0; if (cbSyms < 16) return 1; /* * The parsing loop. */ while (off < cbSyms) { PCKDEPCV8SYMHDR pHdr = (PCKDEPCV8SYMHDR)(pbSyms + off); KPCUINT uData; KU32 cbData; uData.pv = pHdr + 1; if (off + sizeof(*pHdr) >= cbSyms) { kDepErr(pThis, 1, "CV symbol table entry at %08" KX32_PRI " is too long; cbSyms=%#" KX32_PRI "", off, cbSyms); return 1; /* FIXME */ } cbData = pHdr->cb; if (off + cbData + sizeof(*pHdr) > cbSyms) { kDepErr(pThis, 1, "CV symbol table entry at %08" KX32_PRI " is too long; cbData=%#" KX32_PRI " cbSyms=%#" KX32_PRI, off, cbData, cbSyms); return 1; /* FIXME */ } /* If the size is 0, assume it covers the rest of the section. VC++ 2003 has been observed doing thing. */ if (!cbData) cbData = cbSyms - off; switch (pHdr->uType) { case K_CV8_SYMBOL_INFO: dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Symbol Info\n", off, cbData)); /*dump(uData.pb, cbData, 0);*/ break; case K_CV8_LINE_NUMBERS: dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Line numbers\n", off, cbData)); /*dump(uData.pb, cbData, 0);*/ break; case K_CV8_STRING_TABLE: dprintf(("%06" KX32_PRI " %06" KX32_PRI ": String table\n", off, cbData)); if (pchStrTab) warnx(pThis->pCtx, "%s: warning: Found yet another string table!", pThis->pszFile); pchStrTab = uData.pch; cbStrTab = cbData; /*dump(uData.pb, cbData, 0);*/ break; case K_CV8_SOURCE_FILES: dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Source files\n", off, cbData)); if (uSrcFiles.pb) warnx(pThis->pCtx, "%s: warning: Found yet another source files table!", pThis->pszFile); uSrcFiles = uData; cbSrcFiles = cbData; /*dump(uData.pb, cbData, 0);*/ break; case K_CV8_COMDAT_XXXXX: dprintf(("%06" KX32_PRI " %06" KX32_PRI ": 0xf5 Unknown COMDAT stuff\n", off, cbData)); /*dump(uData.pb, cbData, 0);*/ break; default: dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Unknown type %#" KX32_PRI "\n", off, cbData, pHdr->uType)); dump(uData.pb, cbData, 0); break; } /* next */ cbData = (cbData + 3) & ~KU32_C(3); off += cbData + sizeof(*pHdr); } /* * Did we find any source files and strings? */ if (!pchStrTab || !uSrcFiles.pv) { dprintf(("kDepObjCOFFParseCV8SymbolSection: No cylindrical smoking thing: pchStrTab=%p uSrcFiles.pv=%p\n", pchStrTab, uSrcFiles.pv)); return 2; } /* * Iterate the source file table. */ off = 0; while (off < cbSrcFiles) { KU32 offFile; const char *pszFile; KSIZE cchFile; KU16 u16Type; KPCUINT uSrc; KU32 cbSrc; /* * Validate and parse the entry (variable length record are fun). */ if (off + 8 > cbSrcFiles) return kDepErr(pThis, 1, "CV source file entry at %08" KX32_PRI " is too long; cbSrcFiles=%#" KX32_PRI, off, cbSrcFiles); uSrc.pb = uSrcFiles.pb + off; u16Type = uSrc.pu16[2]; switch (u16Type) { case 0x0110: cbSrc = 6 + 16 + 2; break; /* MD5 */ case 0x0214: cbSrc = 6 + 20 + 2; break; /* SHA1 */ /** @todo check this */ case 0x0320: cbSrc = 6 + 32 + 2; break; /* SHA-256 */ default: cbSrc = 6 + 0 + 2; break; } if (off + cbSrc > cbSrcFiles) return kDepErr(pThis, 1, "CV source file entry at %08" KX32_PRI " is too long; cbSrc=%#" KX32_PRI " cbSrcFiles=%#" KX32_PRI, off, cbSrc, cbSrcFiles); offFile = *uSrc.pu32; if (offFile > cbStrTab) return kDepErr(pThis, 1, "CV source file entry at %08" KX32_PRI " is out side the string table; offFile=%#" KX32_PRI " cbStrTab=%#" KX32_PRI, off, offFile, cbStrTab); pszFile = pchStrTab + offFile; cchFile = strlen(pszFile); if (cchFile == 0) return kDepErr(pThis, 1, "CV source file entry at %08" KX32_PRI " has an empty file name; offFile=%#x" KX32_PRI, off, offFile); /* * Display the result and add it to the dependency database. */ depAdd(&pThis->Core, pszFile, cchFile); #ifdef WITH_DPRINTF dprintf(("#%03" KU32_PRI ": ", iSrc)); { KU32 off = 6; for (;off < cbSrc - 2; off++) dprintf(("%02" KX8_PRI, uSrc.pb[off])); if (cbSrc == 6) dprintf(("type=%#06" KX16_PRI, u16Type)); dprintf((" '%s'\n", pszFile)); } #endif /* next */ iSrc++; off += cbSrc; } if (iSrc == 0) { dprintf(("kDepObjCOFFParseCV8SymbolSection: No cylindrical smoking thing: iSrc=0\n")); return 2; } dprintf(("kDepObjCOFFParseCV8SymbolSection: iSrc=%" KU32_PRI "\n", iSrc)); return 0; } /** * Parses the OMF file. * * @returns 0 on success, 1 on failure, 2 if no dependencies was found. * @param pThis The kDepObj instance data. * @param pbFile The start of the file. * @param cbFile The file size. */ int kDepObjCOFFParse(PKDEPOBJGLOBALS pThis, const KU8 *pbFile, KSIZE cbFile) { IMAGE_FILE_HEADER const *pFileHdr = (IMAGE_FILE_HEADER const *)pbFile; ANON_OBJECT_HEADER_BIGOBJ const *pBigObjHdr = (ANON_OBJECT_HEADER_BIGOBJ const *)pbFile; IMAGE_SECTION_HEADER const *paSHdrs; KU32 cSHdrs; unsigned iSHdr; KPCUINT u; KBOOL fDebugS = K_FALSE; int rcRet = 2; int rc; if ( pBigObjHdr->Sig1 == 0 && pBigObjHdr->Sig2 == KU16_MAX) { paSHdrs = (IMAGE_SECTION_HEADER const *)(pBigObjHdr + 1); cSHdrs = pBigObjHdr->NumberOfSections; } else { paSHdrs = (IMAGE_SECTION_HEADER const *)((KU8 const *)(pFileHdr + 1) + pFileHdr->SizeOfOptionalHeader); cSHdrs = pFileHdr->NumberOfSections; } dprintf(("COFF file!\n")); for (iSHdr = 0; iSHdr < cSHdrs; iSHdr++) { if ( !memcmp(paSHdrs[iSHdr].Name, ".debug$S", sizeof(".debug$S") - 1) && paSHdrs[iSHdr].SizeOfRawData > 4) { u.pb = pbFile + paSHdrs[iSHdr].PointerToRawData; dprintf(("CV symbol table: version=%x\n", *u.pu32)); if (*u.pu32 == 0x000000004) rc = kDepObjCOFFParseCV8SymbolSection(pThis, u.pb, paSHdrs[iSHdr].SizeOfRawData); else rc = 2; dprintf(("rc=%d\n", rc)); if (rcRet == 2) rcRet = rc; if (rcRet != 2) return rc; fDebugS = K_TRUE; } dprintf(("#%d: %.8s\n", iSHdr, paSHdrs[iSHdr].Name)); } /* If we found no dependencies but did find a .debug$S section, check if this is a case where the compile didn't emit any because there is no code in this compilation unit. */ if (rcRet == 2) { if (fDebugS) { for (iSHdr = 0; iSHdr < cSHdrs; iSHdr++) if (!memcmp(paSHdrs[iSHdr].Name, ".text", sizeof(".text") - 1)) return kDepErr(pThis, 2, "%s: no dependencies (has text).", pThis->pszFile); warnx(pThis->pCtx, "%s: no dependencies, but also no text, so probably (mostly) harmless.", pThis->pszFile); return 0; } kDepErr(pThis, 2, "%s: no dependencies.", pThis->pszFile); } return rcRet; } /** * Checks if this file is a COFF file or not. * * @returns K_TRUE if it's COFF, K_FALSE otherwise. * * @param pThis The kDepObj instance data. * @param pb The start of the file. * @param cb The file size. */ KBOOL kDepObjCOFFTest(PKDEPOBJGLOBALS pThis, const KU8 *pbFile, KSIZE cbFile) { IMAGE_FILE_HEADER const *pFileHdr = (IMAGE_FILE_HEADER const *)pbFile; ANON_OBJECT_HEADER_BIGOBJ const *pBigObjHdr = (ANON_OBJECT_HEADER_BIGOBJ const *)pbFile; IMAGE_SECTION_HEADER const *paSHdrs; KU32 cSHdrs; KU32 iSHdr; KSIZE cbHdrs; if (cbFile <= sizeof(*pFileHdr)) return K_FALSE; /* * Deal with -bigobj output first. */ if ( pBigObjHdr->Sig1 == 0 && pBigObjHdr->Sig2 == KU16_MAX) { static const KU8 s_abClsId[16] = { ANON_OBJECT_HEADER_BIGOBJ_CLS_ID_BYTES }; paSHdrs = (IMAGE_SECTION_HEADER const *)(pBigObjHdr + 1); cSHdrs = pBigObjHdr->NumberOfSections; cbHdrs = sizeof(IMAGE_SECTION_HEADER) * cSHdrs; if (cbFile <= sizeof(*pBigObjHdr)) return K_FALSE; if (pBigObjHdr->Version != 2) return K_FALSE; if (memcmp(&pBigObjHdr->ClassID[0], s_abClsId, sizeof(pBigObjHdr->ClassID)) != 0) return K_FALSE; if ( pBigObjHdr->Machine != IMAGE_FILE_MACHINE_I386 && pBigObjHdr->Machine != IMAGE_FILE_MACHINE_AMD64 && pBigObjHdr->Machine != IMAGE_FILE_MACHINE_ARM && pBigObjHdr->Machine != IMAGE_FILE_MACHINE_ARMNT && pBigObjHdr->Machine != IMAGE_FILE_MACHINE_ARM64 && pBigObjHdr->Machine != IMAGE_FILE_MACHINE_EBC) { kDepErr(pThis, 1, "bigobj Machine not supported: %#x", pBigObjHdr->Machine); return K_FALSE; } if (pBigObjHdr->Flags != 0) { kDepErr(pThis, 1, "bigobj Flags field is non-zero: %#x", pBigObjHdr->Flags); return K_FALSE; } if (pBigObjHdr->SizeOfData != 0) { kDepErr(pThis, 1, "bigobj SizeOfData field is non-zero: %#x", pBigObjHdr->SizeOfData); return K_FALSE; } if ( pBigObjHdr->PointerToSymbolTable != 0 && ( pBigObjHdr->PointerToSymbolTable < cbHdrs || pBigObjHdr->PointerToSymbolTable > cbFile)) return K_FALSE; if ( pBigObjHdr->PointerToSymbolTable == 0 && pBigObjHdr->NumberOfSymbols != 0) return K_FALSE; } /* * Look for normal COFF object. */ else { paSHdrs = (IMAGE_SECTION_HEADER const *)((KU8 const *)(pFileHdr + 1) + pFileHdr->SizeOfOptionalHeader); cSHdrs = pFileHdr->NumberOfSections; cbHdrs = (const KU8 *)&paSHdrs[cSHdrs] - (const KU8 *)pbFile; if ( pFileHdr->Machine != IMAGE_FILE_MACHINE_I386 && pFileHdr->Machine != IMAGE_FILE_MACHINE_AMD64 && pFileHdr->Machine != IMAGE_FILE_MACHINE_ARM && pFileHdr->Machine != IMAGE_FILE_MACHINE_ARMNT && pFileHdr->Machine != IMAGE_FILE_MACHINE_ARM64 && pFileHdr->Machine != IMAGE_FILE_MACHINE_EBC) return K_FALSE; if (pFileHdr->SizeOfOptionalHeader != 0) return K_FALSE; /* COFF files doesn't have an optional header */ if ( pFileHdr->PointerToSymbolTable != 0 && ( pFileHdr->PointerToSymbolTable < cbHdrs || pFileHdr->PointerToSymbolTable > cbFile)) return K_FALSE; if ( pFileHdr->PointerToSymbolTable == 0 && pFileHdr->NumberOfSymbols != 0) return K_FALSE; if ( pFileHdr->Characteristics & ( IMAGE_FILE_DLL | IMAGE_FILE_SYSTEM | IMAGE_FILE_UP_SYSTEM_ONLY | IMAGE_FILE_NET_RUN_FROM_SWAP | IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP | IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_RELOCS_STRIPPED)) return K_FALSE; } if ( cSHdrs <= 1 || cSHdrs > cbFile) return K_FALSE; if (cbHdrs >= cbFile) return K_FALSE; /* * Check the section headers. */ for (iSHdr = 0; iSHdr < cSHdrs; iSHdr++) { if ( paSHdrs[iSHdr].PointerToRawData != 0 && ( paSHdrs[iSHdr].PointerToRawData < cbHdrs || paSHdrs[iSHdr].PointerToRawData >= cbFile || paSHdrs[iSHdr].PointerToRawData + paSHdrs[iSHdr].SizeOfRawData > cbFile)) return K_FALSE; if ( paSHdrs[iSHdr].PointerToRelocations != 0 && ( paSHdrs[iSHdr].PointerToRelocations < cbHdrs || paSHdrs[iSHdr].PointerToRelocations >= cbFile || paSHdrs[iSHdr].PointerToRelocations + paSHdrs[iSHdr].NumberOfRelocations * 10 > cbFile)) /* IMAGE_RELOCATION */ return K_FALSE; if ( paSHdrs[iSHdr].PointerToLinenumbers != 0 && ( paSHdrs[iSHdr].PointerToLinenumbers < cbHdrs || paSHdrs[iSHdr].PointerToLinenumbers >= cbFile || paSHdrs[iSHdr].PointerToLinenumbers + paSHdrs[iSHdr].NumberOfLinenumbers * 6 > cbFile)) /* IMAGE_LINENUMBER */ return K_FALSE; } return K_TRUE; } /** * Read the file into memory and parse it. */ static int kDepObjProcessFile(PKDEPOBJGLOBALS pThis, FILE *pInput) { size_t cbFile; KU8 *pbFile; void *pvOpaque; int rc = 0; /* * Read the file into memory. */ pbFile = (KU8 *)depReadFileIntoMemory(pInput, &cbFile, &pvOpaque); if (!pbFile) return 1; /* * See if it's an OMF file, then process it. */ if (kDepObjOMFTest(pbFile, cbFile)) rc = kDepObjOMFParse(pThis, pbFile, cbFile); else if (kDepObjCOFFTest(pThis, pbFile, cbFile)) rc = kDepObjCOFFParse(pThis, pbFile, cbFile); else rc = kDepErr(pThis, 1, "Doesn't recognize the header of the OMF/COFF file."); depFreeFileMemory(pbFile, pvOpaque); return rc; } static void kDebObjUsage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s -o -t [-fqs] [-e ] \n" " or: %s --help\n" " or: %s --version\n", pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); } int kmk_builtin_kDepObj(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { int i; KDEPOBJGLOBALS This; /* Arguments. */ FILE *pOutput = NULL; const char *pszOutput = NULL; FILE *pInput = NULL; const char *pszTarget = NULL; int fStubs = 0; int fFixCase = 0; const char *pszIgnoreExt = NULL; /* Argument parsing. */ int fInput = 0; /* set when we've found input argument. */ int fQuiet = 0; /* Init instance data. */ This.pCtx = pCtx; This.pszFile = NULL; /* * Parse arguments. */ if (argc <= 1) { kDebObjUsage(pCtx, 0); return 1; } for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { const char *pszValue; const char *psz = &argv[i][1]; char chOpt; chOpt = *psz++; if (chOpt == '-') { /* Convert long to short option. */ if (!strcmp(psz, "quiet")) chOpt = 'q'; else if (!strcmp(psz, "help")) chOpt = '?'; else if (!strcmp(psz, "version")) chOpt = 'V'; else { errx(pCtx, 2, "Invalid argument '%s'.", argv[i]); kDebObjUsage(pCtx, 1); return 2; } psz = ""; } /* * Requires value? */ switch (chOpt) { case 'o': case 't': case 'e': if (*psz) pszValue = psz; else if (++i < argc) pszValue = argv[i]; else return errx(pCtx, 2, "The '-%c' option takes a value.", chOpt); break; default: pszValue = NULL; break; } switch (chOpt) { /* * Output file. */ case 'o': { if (pOutput) return errx(pCtx, 2, "only one output file!"); pszOutput = pszValue; if (pszOutput[0] == '-' && !pszOutput[1]) pOutput = stdout; else pOutput = fopen(pszOutput, "w" KMK_FOPEN_NO_INHERIT_MODE); if (!pOutput) return err(pCtx, 1, "Failed to create output file '%s'", pszOutput); break; } /* * Target name. */ case 't': { if (pszTarget) return errx(pCtx, 2, "only one target!"); pszTarget = pszValue; break; } /* * Fix case. */ case 'f': { fFixCase = 1; break; } /* * Quiet. */ case 'q': { fQuiet = 1; break; } /* * Generate stubs. */ case 's': { fStubs = 1; break; } /* * Extension to ignore. */ case 'e': { if (pszIgnoreExt) return errx(pCtx, 2, "The '-e' option can only be used once!"); pszIgnoreExt = pszValue; break; } /* * The mandatory version & help. */ case '?': kDebObjUsage(pCtx, 0); return 0; case 'V': case 'v': return kbuild_version(argv[0]); /* * Invalid argument. */ default: errx(pCtx, 2, "Invalid argument '%s'.", argv[i]); kDebObjUsage(pCtx, 1); return 2; } } else { pInput = fopen(argv[i], "rb" KMK_FOPEN_NO_INHERIT_MODE); if (!pInput) return err(pCtx, 1, "Failed to open input file '%s'", argv[i]); This.pszFile = argv[i]; fInput = 1; } /* * End of the line? */ if (fInput) { if (++i < argc) return errx(pCtx, 2, "No arguments shall follow the input spec."); break; } } /* * Got all we require? */ if (!pInput) return errx(pCtx, 2, "No input!"); if (!pOutput) return errx(pCtx, 2, "No output!"); if (!pszTarget) return errx(pCtx, 2, "No target!"); /* * Do the parsing. */ depInit(&This.Core); i = kDepObjProcessFile(&This, pInput); fclose(pInput); /* * Write the dependecy file. */ if (!i) { depOptimize(&This.Core, fFixCase, fQuiet, pszIgnoreExt); depPrintTargetWithDeps(&This.Core, pOutput, pszTarget, 1 /*fEscapeTarget*/); if (fStubs) depPrintStubs(&This.Core, pOutput); } /* * Close the output, delete output on failure. */ if (!i && ferror(pOutput)) i = errx(pCtx, 1, "Error writing to '%s'", pszOutput); fclose(pOutput); if (i) { if (unlink(pszOutput)) warn(pCtx, "warning: failed to remove output file '%s' on failure.", pszOutput); } depCleanup(&This.Core); return i; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kDepObj", NULL }; return kmk_builtin_kDepObj(argc, argv, envp, &Ctx); } #endif kbuild-3686/src/kmk/kmkbuiltin/kDepIDB.c0000664000175000017500000006246715053010074020016 0ustar locutuslocutus/* $Id: kDepIDB.c 3315 2020-03-31 01:12:19Z bird $ */ /** @file * kDepIDB - Extract dependency information from a MS Visual C++ .idb file. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #include "config.h" #include #include #include #include #include #include #ifdef HAVE_ALLOCA_H # include #endif #if !defined(_MSC_VER) # include #else # include #endif #include "k/kDefs.h" #include "k/kTypes.h" #include "kDep.h" #include "err.h" #include "kmkbuiltin.h" /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ /*#define DEBUG*/ #ifdef DEBUG # define dprintf(a) printf a # define dump(pb, cb, offBase) depHexDump(pb,cb,offBase) #else # define dprintf(a) do {} while (0) # define dump(pb, cb, offBase) do {} while (0) #endif /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ typedef struct KDEPIDBGLOBALS { PKMKBUILTINCTX pCtx; DEPGLOBALS Core; } KDEPIDBGLOBALS; typedef KDEPIDBGLOBALS *PKDEPIDBGLOBALS; /** * Scans a stream (chunk of data really) for dependencies. * * @returns 0 on success. * @returns !0 on failure. * @param pThis The kDepIDB instance. * @param pbStream The stream bits. * @param cbStream The size of the stream. * @param pszPrefix The dependency prefix. * @param cchPrefix The size of the prefix. */ static int ScanStream(PKDEPIDBGLOBALS pThis, KU8 *pbStream, size_t cbStream, const char *pszPrefix, size_t cchPrefix) { const KU8 *pbCur = pbStream; size_t cbLeft = cbStream; register char chFirst = *pszPrefix; while (cbLeft > cchPrefix + 2) { if ( *pbCur != chFirst || memcmp(pbCur, pszPrefix, cchPrefix)) { pbCur++; cbLeft--; } else { size_t cchDep; pbCur += cchPrefix; cchDep = strlen((const char *)pbCur); depAdd(&pThis->Core, (const char *) pbCur, cchDep); dprintf(("%05x: '%s'\n", pbCur - pbStream, pbCur)); pbCur += cchDep; cbLeft -= cchDep + cchPrefix; } } return 0; } /*///////////////////////////////////////////////////////////////////////////// // // // P D B 7 . 0 // // /////////////////////////////////////////////////////////////////////////////*/ /** A PDB 7.0 Page number. */ typedef KU32 PDB70PAGE; /** Pointer to a PDB 7.0 Page number. */ typedef PDB70PAGE *PPDB70PAGE; /** * A PDB 7.0 stream. */ typedef struct PDB70STREAM { /** The size of the stream. */ KU32 cbStream; } PDB70STREAM, *PPDB70STREAM; /** The PDB 7.00 signature. */ #define PDB_SIGNATURE_700 "Microsoft C/C++ MSF 7.00\r\n\x1A" "DS\0\0" /** * The PDB 7.0 header. */ typedef struct PDB70HDR { /** The signature string. */ KU8 szSignature[sizeof(PDB_SIGNATURE_700)]; /** The page size. */ KU32 cbPage; /** The start page. */ PDB70PAGE iStartPage; /** The number of pages in the file. */ PDB70PAGE cPages; /** The root stream directory. */ KU32 cbRoot; /** Unknown function, always 0. */ KU32 u32Reserved; /** The page index of the root page table. */ PDB70PAGE iRootPages; } PDB70HDR, *PPDB70HDR; /** * The PDB 7.0 root directory. */ typedef struct PDB70ROOT { /** The number of streams */ KU32 cStreams; /** Array of streams. */ PDB70STREAM aStreams[1]; /* KU32 aiPages[] */ } PDB70ROOT, *PPDB70ROOT; /** * The PDB 7.0 name stream (#1) header. */ typedef struct PDB70NAMES { /** The structure version. */ KU32 Version; /** Timestamp. */ KU32 TimeStamp; /** Unknown. */ KU32 Unknown1; /** GUID. */ KU32 u32Guid[4]; /** The size of the following name table. */ KU32 cbNames; /** The name table. */ char szzNames[1]; } PDB70NAMES, *PPDB70NAMES; /** The version / magic of the names structure. */ #define PDB70NAMES_VERSION 20000404 static int Pdb70ValidateHeader(PKDEPIDBGLOBALS pThis, PPDB70HDR pHdr, size_t cbFile) { if (pHdr->cbPage * pHdr->cPages != cbFile) return errx(pThis->pCtx, 1, "Bad PDB 2.0 header - cbPage * cPages != cbFile."); if (pHdr->iStartPage >= pHdr->cPages && pHdr->iStartPage <= 0) return errx(pThis->pCtx, 1, "Bad PDB 2.0 header - iStartPage=%u cPages=%u.", pHdr->iStartPage, pHdr->cPages); if (pHdr->iRootPages >= pHdr->cPages && pHdr->iRootPages <= 0) return errx(pThis->pCtx, 1, "Bad PDB 2.0 header - iRootPages=%u cPage=%u.", pHdr->iStartPage, pHdr->cPages); return 0; } #ifdef DEBUG static size_t Pdb70Align(PPDB70HDR pHdr, size_t cb) { if (cb == ~(KU32)0 || !cb) return 0; return ((cb + pHdr->cbPage - 1) / pHdr->cbPage) * pHdr->cbPage; } #endif /* DEBUG */ static size_t Pdb70Pages(PPDB70HDR pHdr, size_t cb) { if (cb == ~(KU32)0 || !cb) return 0; return (cb + pHdr->cbPage - 1) / pHdr->cbPage; } static void *Pdb70AllocAndRead(PKDEPIDBGLOBALS pThis, PPDB70HDR pHdr, size_t cb, PPDB70PAGE paiPageMap) { const size_t cbPage = pHdr->cbPage; size_t cPages = Pdb70Pages(pHdr, cb); KU8 *pbBuf = malloc(cPages * cbPage + 1); if (pbBuf) { size_t iPage = 0; while (iPage < cPages) { size_t off = paiPageMap[iPage]; if (off < pHdr->cPages) { off *= cbPage; memcpy(pbBuf + iPage * cbPage, (KU8 *)pHdr + off, cbPage); dump(pbBuf + iPage * cbPage, iPage + 1 < cPages ? cbPage : cb % cbPage, off); } else { warnx(pThis->pCtx, "warning: Invalid page index %u (max %u)!\n", (unsigned)off, pHdr->cPages); memset(pbBuf + iPage * cbPage, 0, cbPage); } iPage++; } pbBuf[cPages * cbPage] = '\0'; } else { errx(pThis->pCtx, 1, "failed to allocate %lu bytes", (unsigned long)(cPages * cbPage + 1)); return NULL; } return pbBuf; } static PPDB70ROOT Pdb70AllocAndReadRoot(PKDEPIDBGLOBALS pThis, PPDB70HDR pHdr) { /* * The tricky bit here is to find the right length. Really? * (Todo: Check if we can just use the stream #0 size..) */ PPDB70PAGE piPageMap = (KU32 *)((KU8 *)pHdr + pHdr->iRootPages * pHdr->cbPage); PPDB70ROOT pRoot = Pdb70AllocAndRead(pThis, pHdr, pHdr->cbRoot, piPageMap); if (pRoot) { #if 1 /* This stuff is probably unnecessary: */ /* size = stream header + array of stream. */ size_t cb = K_OFFSETOF(PDB70ROOT, aStreams[pRoot->cStreams]); free(pRoot); pRoot = Pdb70AllocAndRead(pThis, pHdr, cb, piPageMap); if (pRoot) { /* size += page tables. */ unsigned iStream = pRoot->cStreams; while (iStream-- > 0) if (pRoot->aStreams[iStream].cbStream != ~(KU32)0) cb += Pdb70Pages(pHdr, pRoot->aStreams[iStream].cbStream) * sizeof(PDB70PAGE); free(pRoot); pRoot = Pdb70AllocAndRead(pThis, pHdr, cb, piPageMap); if (pRoot) { /* validate? */ return pRoot; } } #else /* validate? */ return pRoot; #endif } return NULL; } static void *Pdb70AllocAndReadStream(PKDEPIDBGLOBALS pThis, PPDB70HDR pHdr, PPDB70ROOT pRoot, unsigned iStream, size_t *pcbStream) { const size_t cbStream = pRoot->aStreams[iStream].cbStream; PPDB70PAGE paiPageMap; if ( iStream >= pRoot->cStreams || cbStream == ~(KU32)0) { errx(pThis->pCtx, 1, "Invalid stream %d", iStream); return NULL; } paiPageMap = (PPDB70PAGE)&pRoot->aStreams[pRoot->cStreams]; while (iStream-- > 0) if (pRoot->aStreams[iStream].cbStream != ~(KU32)0) paiPageMap += Pdb70Pages(pHdr, pRoot->aStreams[iStream].cbStream); if (pcbStream) *pcbStream = cbStream; return Pdb70AllocAndRead(pThis, pHdr, cbStream, paiPageMap); } static int Pdb70Process(PKDEPIDBGLOBALS pThis, KU8 *pbFile, size_t cbFile) { PPDB70HDR pHdr = (PPDB70HDR)pbFile; PPDB70ROOT pRoot; PPDB70NAMES pNames; size_t cbStream = 0; unsigned fDone = 0; unsigned iStream; int rc = 0; dprintf(("pdb70\n")); /* * Validate the header and read the root stream. */ if (Pdb70ValidateHeader(pThis, pHdr, cbFile)) return 1; pRoot = Pdb70AllocAndReadRoot(pThis, pHdr); if (!pRoot) return 1; /* * The names we want are usually all found in the 'Names' stream, that is #1. */ dprintf(("Reading the names stream....\n")); pNames = Pdb70AllocAndReadStream(pThis, pHdr, pRoot, 1, &cbStream); if (pNames) { dprintf(("Names: Version=%u cbNames=%u (%#x)\n", pNames->Version, pNames->cbNames, pNames->cbNames)); if ( pNames->Version == PDB70NAMES_VERSION && pNames->cbNames > 32 && pNames->cbNames + K_OFFSETOF(PDB70NAMES, szzNames) <= pRoot->aStreams[1].cbStream) { /* * Iterate the names and add the /mr/inversedeps/ ones to the dependency list. */ const char *psz = &pNames->szzNames[0]; size_t cb = pNames->cbNames; size_t off = 0; dprintf(("0x0000 #0: %6d bytes [root / toc]\n", pRoot->aStreams[0].cbStream)); for (iStream = 1; cb > 0; iStream++) { int fAdded = 0; size_t cch = strlen(psz); if ( cch >= sizeof("/mr/inversedeps/") && !memcmp(psz, "/mr/inversedeps/", sizeof("/mr/inversedeps/") - 1)) { depAdd(&pThis->Core, psz + sizeof("/mr/inversedeps/") - 1, cch - (sizeof("/mr/inversedeps/") - 1)); fAdded = 1; } dprintf(("%#06x #%d: %6d bytes %s%s\n", off, iStream, iStream < pRoot->cStreams ? pRoot->aStreams[iStream].cbStream : -1, psz, fAdded ? " [dep]" : "")); (void)fAdded; /* next */ if (cch >= cb) { dprintf(("warning! cch=%d cb=%d\n", cch, cb)); cch = cb - 1; } cb -= cch + 1; psz += cch + 1; off += cch + 1; } rc = 0; fDone = 1; } else dprintf(("Unknown version or bad size: Version=%u cbNames=%d cbStream=%d\n", pNames->Version, pNames->cbNames, cbStream)); free(pNames); } if (!fDone) { /* * Iterate the streams in the root and scan their content for * dependencies. */ rc = 0; for (iStream = 0; iStream < pRoot->cStreams && !rc; iStream++) { KU8 *pbStream; if ( pRoot->aStreams[iStream].cbStream == ~(KU32)0 || !pRoot->aStreams[iStream].cbStream) continue; dprintf(("Stream #%d: %#x bytes (%#x aligned)\n", iStream, pRoot->aStreams[iStream].cbStream, Pdb70Align(pHdr, pRoot->aStreams[iStream].cbStream))); pbStream = (KU8 *)Pdb70AllocAndReadStream(pThis, pHdr, pRoot, iStream, &cbStream); if (pbStream) { rc = ScanStream(pThis, pbStream, cbStream, "/mr/inversedeps/", sizeof("/mr/inversedeps/") - 1); free(pbStream); } else rc = 1; } } free(pRoot); return rc; } /*///////////////////////////////////////////////////////////////////////////// // // // P D B 2 . 0 // // /////////////////////////////////////////////////////////////////////////////*/ /** A PDB 2.0 Page number. */ typedef KU16 PDB20PAGE; /** Pointer to a PDB 2.0 Page number. */ typedef PDB20PAGE *PPDB20PAGE; /** * A PDB 2.0 stream. */ typedef struct PDB20STREAM { /** The size of the stream. */ KU32 cbStream; /** Some unknown value. */ KU32 u32Unknown; } PDB20STREAM, *PPDB20STREAM; /** The PDB 2.00 signature. */ #define PDB_SIGNATURE_200 "Microsoft C/C++ program database 2.00\r\n\x1A" "JG\0" /** * The PDB 2.0 header. */ typedef struct PDB20HDR { /** The signature string. */ KU8 szSignature[sizeof(PDB_SIGNATURE_200)]; /** The page size. */ KU32 cbPage; /** The start page - whatever that is... */ PDB20PAGE iStartPage; /** The number of pages in the file. */ PDB20PAGE cPages; /** The root stream directory. */ PDB20STREAM RootStream; /** The root page table. */ PDB20PAGE aiRootPageMap[1]; } PDB20HDR, *PPDB20HDR; /** * The PDB 2.0 root directory. */ typedef struct PDB20ROOT { /** The number of streams */ KU16 cStreams; /** Reserved or high part of cStreams. */ KU16 u16Reserved; /** Array of streams. */ PDB20STREAM aStreams[1]; } PDB20ROOT, *PPDB20ROOT; static int Pdb20ValidateHeader(PKDEPIDBGLOBALS pThis, PPDB20HDR pHdr, size_t cbFile) { if (pHdr->cbPage * pHdr->cPages != cbFile) return errx(pThis->pCtx, 1, "Bad PDB 2.0 header - cbPage * cPages != cbFile."); if (pHdr->iStartPage >= pHdr->cPages && pHdr->iStartPage <= 0) return errx(pThis->pCtx, 1, "Bad PDB 2.0 header - cbPage * cPages != cbFile."); return 0; } static size_t Pdb20Pages(PPDB20HDR pHdr, size_t cb) { if (cb == ~(KU32)0 || !cb) return 0; return (cb + pHdr->cbPage - 1) / pHdr->cbPage; } static void *Pdb20AllocAndRead(PKDEPIDBGLOBALS pThis, PPDB20HDR pHdr, size_t cb, PPDB20PAGE paiPageMap) { size_t cPages = Pdb20Pages(pHdr, cb); KU8 *pbBuf = malloc(cPages * pHdr->cbPage + 1); if (pbBuf) { size_t iPage = 0; while (iPage < cPages) { size_t off = paiPageMap[iPage]; off *= pHdr->cbPage; memcpy(pbBuf + iPage * pHdr->cbPage, (KU8 *)pHdr + off, pHdr->cbPage); iPage++; } pbBuf[cPages * pHdr->cbPage] = '\0'; } else errx(pThis->pCtx, 1, "failed to allocate %lu bytes", (unsigned long)(cPages * pHdr->cbPage + 1)); return pbBuf; } static PPDB20ROOT Pdb20AllocAndReadRoot(PKDEPIDBGLOBALS pThis, PPDB20HDR pHdr) { /* * The tricky bit here is to find the right length. * (Todo: Check if we can just use the stream size..) */ PPDB20ROOT pRoot = Pdb20AllocAndRead(pThis, pHdr, sizeof(*pRoot), &pHdr->aiRootPageMap[0]); if (pRoot) { /* size = stream header + array of stream. */ size_t cb = K_OFFSETOF(PDB20ROOT, aStreams[pRoot->cStreams]); free(pRoot); pRoot = Pdb20AllocAndRead(pThis, pHdr, cb, &pHdr->aiRootPageMap[0]); if (pRoot) { /* size += page tables. */ unsigned iStream = pRoot->cStreams; while (iStream-- > 0) if (pRoot->aStreams[iStream].cbStream != ~(KU32)0) cb += Pdb20Pages(pHdr, pRoot->aStreams[iStream].cbStream) * sizeof(PDB20PAGE); free(pRoot); pRoot = Pdb20AllocAndRead(pThis, pHdr, cb, &pHdr->aiRootPageMap[0]); if (pRoot) { /* validate? */ return pRoot; } } } return NULL; } static void *Pdb20AllocAndReadStream(PKDEPIDBGLOBALS pThis, PPDB20HDR pHdr, PPDB20ROOT pRoot, unsigned iStream, size_t *pcbStream) { size_t cbStream = pRoot->aStreams[iStream].cbStream; PPDB20PAGE paiPageMap; if ( iStream >= pRoot->cStreams || cbStream == ~(KU32)0) { errx(pThis->pCtx, 1, "Invalid stream %d", iStream); return NULL; } paiPageMap = (PPDB20PAGE)&pRoot->aStreams[pRoot->cStreams]; while (iStream-- > 0) if (pRoot->aStreams[iStream].cbStream != ~(KU32)0) paiPageMap += Pdb20Pages(pHdr, pRoot->aStreams[iStream].cbStream); if (pcbStream) *pcbStream = cbStream; return Pdb20AllocAndRead(pThis, pHdr, cbStream, paiPageMap); } static int Pdb20Process(PKDEPIDBGLOBALS pThis, KU8 *pbFile, size_t cbFile) { PPDB20HDR pHdr = (PPDB20HDR)pbFile; PPDB20ROOT pRoot; unsigned iStream; int rc = 0; /* * Validate the header and read the root stream. */ if (Pdb20ValidateHeader(pThis, pHdr, cbFile)) return 1; pRoot = Pdb20AllocAndReadRoot(pThis, pHdr); if (!pRoot) return 1; /* * Iterate the streams in the root and scan their content for * dependencies. */ rc = 0; for (iStream = 0; iStream < pRoot->cStreams && !rc; iStream++) { KU8 *pbStream; if (pRoot->aStreams[iStream].cbStream == ~(KU32)0) continue; pbStream = (KU8 *)Pdb20AllocAndReadStream(pThis, pHdr, pRoot, iStream, NULL); if (pbStream) { rc = ScanStream(pThis, pbStream, pRoot->aStreams[iStream].cbStream, "/ipm/header/", sizeof("/ipm/header/") - 1); free(pbStream); } else rc = 1; } free(pRoot); return rc; } /** * Make an attempt at parsing a Visual C++ IDB file. */ static int ProcessIDB(PKDEPIDBGLOBALS pThis, FILE *pInput) { size_t cbFile; KU8 *pbFile; void *pvOpaque; int rc = 0; /* * Read the file into memory. */ pbFile = (KU8 *)depReadFileIntoMemory(pInput, &cbFile, &pvOpaque); if (!pbFile) return 1; /* * Figure out which parser to use. */ if (!memcmp(pbFile, PDB_SIGNATURE_700, sizeof(PDB_SIGNATURE_700))) rc = Pdb70Process(pThis, pbFile, cbFile); else if (!memcmp(pbFile, PDB_SIGNATURE_200, sizeof(PDB_SIGNATURE_200))) rc = Pdb20Process(pThis, pbFile, cbFile); else rc = errx(pThis->pCtx, 1, "Doesn't recognize the header of the Visual C++ IDB file."); depFreeFileMemory(pbFile, pvOpaque); return rc; } static void kDepIDBUsage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s -o -t [-fqs] \n" " or: %s --help\n" " or: %s --version\n", pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); } int kmk_builtin_kDepIDB(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { int i; KDEPIDBGLOBALS This; /* Arguments. */ FILE *pOutput = NULL; const char *pszOutput = NULL; FILE *pInput = NULL; const char *pszTarget = NULL; int fStubs = 0; int fFixCase = 0; /* Argument parsing. */ int fInput = 0; /* set when we've found input argument. */ int fQuiet = 0; /* Init the instance data. */ This.pCtx = pCtx; /* * Parse arguments. */ if (argc <= 1) { kDepIDBUsage(pCtx, 0); return 1; } for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { const char *psz = &argv[i][1]; if (*psz == '-') { if (!strcmp(psz, "-quiet")) psz = "q"; else if (!strcmp(psz, "-help")) psz = "?"; else if (!strcmp(psz, "-version")) psz = "V"; } switch (*psz) { /* * Output file. */ case 'o': { pszOutput = &argv[i][2]; if (pOutput) return errx(pCtx, 2, "only one output file!"); if (!*pszOutput) { if (++i >= argc) return errx(pCtx, 2, "The '-o' argument is missing the filename."); pszOutput = argv[i]; } if (pszOutput[0] == '-' && !pszOutput[1]) pOutput = stdout; else pOutput = fopen(pszOutput, "w" KMK_FOPEN_NO_INHERIT_MODE); if (!pOutput) return err(pCtx, 1, "Failed to create output file '%s'", pszOutput); break; } /* * Target name. */ case 't': { if (pszTarget) return errx(pCtx, 2, "only one target!"); pszTarget = &argv[i][2]; if (!*pszTarget) { if (++i >= argc) return errx(pCtx, 2, "The '-t' argument is missing the target name."); pszTarget = argv[i]; } break; } /* * Fix case. */ case 'f': { fFixCase = 1; break; } /* * Quiet. */ case 'q': { fQuiet = 1; break; } /* * Generate stubs. */ case 's': { fStubs = 1; break; } /* * The mandatory version & help. */ case '?': kDepIDBUsage(pCtx, 0); return 0; case 'V': case 'v': return kbuild_version(pCtx->pszProgName); /* * Invalid argument. */ default: errx(pCtx, 2, "Invalid argument '%s.'", argv[i]); kDepIDBUsage(pCtx, 1); return 2; } } else { pInput = fopen(argv[i], "rb" KMK_FOPEN_NO_INHERIT_MODE); if (!pInput) return err(pCtx, 1, "Failed to open input file '%s'", argv[i]); fInput = 1; } /* * End of the line? */ if (fInput) { if (++i < argc) return errx(pCtx, 2, "No arguments shall follow the input spec."); break; } } /* * Got all we require? */ if (!pInput) return errx(pCtx, 2, "No input!"); if (!pOutput) return errx(pCtx, 2, "No output!"); if (!pszTarget) return errx(pCtx, 2, "No target!"); /* * Do the parsing. */ depInit(&This.Core); i = ProcessIDB(&This, pInput); fclose(pInput); /* * Write the dependecy file. */ if (!i) { depOptimize(&This.Core, fFixCase, fQuiet, NULL /*pszIgnoredExt*/); depPrintTargetWithDeps(&This.Core, pOutput, pszTarget, 1 /*fEscapeTarget*/); if (fStubs) depPrintStubs(&This.Core, pOutput); } /* * Close the output, delete output on failure. */ if (!i && ferror(pOutput)) i = errx(pCtx, 1, "Error writing to '%s'.", pszOutput); fclose(pOutput); if (i) { if (unlink(pszOutput)) warnx(pCtx, "warning: failed to remove output file '%s' on failure.", pszOutput); } depCleanup(&This.Core); return i; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_kDepIDB", NULL }; return kmk_builtin_kDepIDB(argc, argv, envp, &Ctx); } #endif kbuild-3686/src/kmk/kmkbuiltin/fts.c0000664000175000017500000010715715053010074017404 0ustar locutuslocutus/* $NetBSD: __fts13.c,v 1.44 2005/01/19 00:59:48 mycroft Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 * 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. 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. */ #ifdef __sun__ # define _POSIX_C_SOURCE 199506L /* for dirfd() */ # define __EXTENSIONS__ 1 /* for u_short and friends */ #endif #if HAVE_NBTOOL_CONFIG_H #include "nbtool_config.h" #endif /*#include */ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94"; #else __RCSID("$NetBSD: __fts13.c,v 1.44 2005/01/19 00:59:48 mycroft Exp $"); #endif #endif /* LIBC_SCCS and not lint */ #include "config.h" /*#include "namespace.h"*/ #ifndef _MSC_VER #include #endif #include #include #include #include #include #include "ftsfake.h" #include #include #include #ifdef HAVE_ALLOCA_H # include #endif #include "kmkbuiltin.h" /* MAXPATHLEN for GNU/hurd */ #ifdef __sun__ # include "solfakes.h" # define dirfd(dir) ((dir)->d_fd) #endif #ifdef _MSC_VER # include "mscfakes.h" # define dirfd(dir) -1 #endif #if ! HAVE_NBTOOL_CONFIG_H # if !defined(__sun__) && !defined(__gnu_linux__) && !defined(__HAIKU__) # define HAVE_STRUCT_DIRENT_D_NAMLEN 1 # endif #endif #if 0 #ifdef __weak_alias #ifdef __LIBC12_SOURCE__ __weak_alias(fts_children,_fts_children) __weak_alias(fts_close,_fts_close) __weak_alias(fts_open,_fts_open) __weak_alias(fts_read,_fts_read) __weak_alias(fts_set,_fts_set) #endif /* __LIBC12_SOURCE__ */ #endif /* __weak_alias */ #endif #ifdef __LIBC12_SOURCE__ #define STAT stat12 #else #define STAT stat #endif #ifdef __LIBC12_SOURCE__ __warn_references(fts_children, "warning: reference to compatibility fts_children();" " include for correct reference") __warn_references(fts_close, "warning: reference to compatibility fts_close();" " include for correct reference") __warn_references(fts_open, "warning: reference to compatibility fts_open();" " include for correct reference") __warn_references(fts_read, "warning: reference to compatibility fts_read();" " include for correct reference") __warn_references(fts_set, "warning: reference to compatibility fts_set();" " include for correct reference") #endif static FTSENT *fts_alloc(FTS *, const char *, size_t); static FTSENT *fts_build(FTS *, int); static void fts_lfree(FTSENT *); static void fts_load(FTS *, FTSENT *); static size_t fts_maxarglen(char * const *); static size_t fts_pow2(size_t); static int fts_palloc(FTS *, size_t); static void fts_padjust(FTS *, FTSENT *); static FTSENT *fts_sort(FTS *, FTSENT *, size_t); static u_short fts_stat(FTS *, FTSENT *, int); #ifdef _MSC_VER static u_short fts_stat_dirent(FTS *sp, FTSENT *p, int follow, struct dirent *pDirEnt); #endif static int fts_safe_changedir(const FTS *, const FTSENT *, int, const char *); #ifdef _MSC_VER # undef HAVE_FCHDIR #endif #if defined(__EMX__) || defined(_MSC_VER) # define NEED_STRRSLASH # define IS_SLASH(ch) ( (ch) == '/' || (ch) == '\\' ) #else # define HAVE_FCHDIR # define IS_SLASH(ch) ( (ch) == '/' ) #endif #define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) #define CLR(opt) (sp->fts_options &= ~(opt)) #define ISSET(opt) (sp->fts_options & (opt)) #define SET(opt) (sp->fts_options |= (opt)) #define CHDIR(sp, path) (!ISSET(FTS_NOCHDIR) && chdir(path)) #ifdef HAVE_FCHDIR #define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) #else #define FCHDIR(sp, rdir) CHDIR(sp, rdir) #endif /* fts_build flags */ #define BCHILD 1 /* fts_children */ #define BNAMES 2 /* fts_children, names only */ #define BREAD 3 /* fts_read */ #ifndef DTF_HIDEW #undef FTS_WHITEOUT #endif #ifndef _DIAGASSERT #define _DIAGASSERT assert #endif FTS * fts_open(argv, options, compar) char * const *argv; int options; int (*compar)(const FTSENT **, const FTSENT **); { FTS *sp; FTSENT *p, *root; size_t nitems; FTSENT *parent, *tmp = NULL; /* pacify gcc */ size_t len; _DIAGASSERT(argv != NULL); /* Options check. */ if (options & ~FTS_OPTIONMASK) { errno = EINVAL; return (NULL); } /* Allocate/initialize the stream */ if ((sp = malloc((u_int)sizeof(FTS))) == NULL) return (NULL); memset(sp, 0, sizeof(FTS)); sp->fts_compar = compar; sp->fts_options = options; /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ if (ISSET(FTS_LOGICAL)) SET(FTS_NOCHDIR); /* * Start out with 1K of path space, and enough, in any case, * to hold the user's paths. */ if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN))) goto mem1; /* Allocate/initialize root's parent. */ if ((parent = fts_alloc(sp, "", 0)) == NULL) goto mem2; parent->fts_level = FTS_ROOTPARENTLEVEL; /* Allocate/initialize root(s). */ for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) { /* Don't allow zero-length paths. */ if ((len = strlen(*argv)) == 0) { errno = ENOENT; goto mem3; } if ((p = fts_alloc(sp, *argv, len)) == NULL) goto mem3; p->fts_level = FTS_ROOTLEVEL; p->fts_parent = parent; p->fts_accpath = p->fts_name; p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW)); /* Command-line "." and ".." are real directories. */ if (p->fts_info == FTS_DOT) p->fts_info = FTS_D; /* * If comparison routine supplied, traverse in sorted * order; otherwise traverse in the order specified. */ if (compar) { p->fts_link = root; root = p; } else { p->fts_link = NULL; if (root == NULL) tmp = root = p; else { tmp->fts_link = p; tmp = p; } } } if (compar && nitems > 1) root = fts_sort(sp, root, nitems); /* * Allocate a dummy pointer and make fts_read think that we've just * finished the node before the root(s); set p->fts_info to FTS_INIT * so that everything about the "current" node is ignored. */ if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL) goto mem3; sp->fts_cur->fts_link = root; sp->fts_cur->fts_info = FTS_INIT; /* * If using chdir(2), grab a file descriptor pointing to dot to insure * that we can get back here; this could be avoided for some paths, * but almost certainly not worth the effort. Slashes, symbolic links, * and ".." are all fairly nasty problems. Note, if we can't get the * descriptor we run anyway, just more slowly. */ if (!ISSET(FTS_NOCHDIR)) { #ifdef HAVE_FCHDIR if ((sp->fts_rfd = open(".", O_RDONLY | KMK_OPEN_NO_INHERIT, 0)) == -1) SET(FTS_NOCHDIR); else if (fcntl(sp->fts_rfd, F_SETFD, FD_CLOEXEC) == -1) { close(sp->fts_rfd); SET(FTS_NOCHDIR); } #else if ((sp->fts_rdir = getcwd(NULL, 0)) != NULL) SET(FTS_NOCHDIR); #endif } return (sp); mem3: fts_lfree(root); free(parent); mem2: free(sp->fts_path); mem1: free(sp); return (NULL); } #ifdef NEED_STRRSLASH static char *strrslash(register char *psz) { register char ch; char *pszLast = NULL; for (; (ch = *psz); psz++) switch (ch) { case '/': case '\\': case ':': pszLast = psz; break; } return pszLast; } #endif static void fts_load(sp, p) FTS *sp; FTSENT *p; { size_t len; char *cp; _DIAGASSERT(sp != NULL); _DIAGASSERT(p != NULL); /* * Load the stream structure for the next traversal. Since we don't * actually enter the directory until after the preorder visit, set * the fts_accpath field specially so the chdir gets done to the right * place and the user can access the first node. From fts_open it's * known that the path will fit. */ len = p->fts_pathlen = p->fts_namelen; memmove(sp->fts_path, p->fts_name, len + 1); #ifdef NEED_STRRSLASH if ((cp = strrslash(p->fts_name)) && (cp != p->fts_name || cp[1])) { #else if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) { #endif len = strlen(++cp); memmove(p->fts_name, cp, len + 1); p->fts_namelen = len; } p->fts_accpath = p->fts_path = sp->fts_path; sp->fts_dev = p->fts_dev; } int fts_close(sp) FTS *sp; { FTSENT *freep, *p; int saved_errno = 0; _DIAGASSERT(sp != NULL); /* * This still works if we haven't read anything -- the dummy structure * points to the root list, so we step through to the end of the root * list which has a valid parent pointer. */ if (sp->fts_cur) { #ifndef _MSC_VER if (ISSET(FTS_SYMFOLLOW)) (void)close(sp->fts_cur->fts_symfd); #endif for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) { freep = p; p = p->fts_link ? p->fts_link : p->fts_parent; free(freep); } free(p); } /* Free up child linked list, sort array, path buffer. */ if (sp->fts_child) fts_lfree(sp->fts_child); if (sp->fts_array) free(sp->fts_array); free(sp->fts_path); /* Return to original directory, save errno if necessary. */ if (!ISSET(FTS_NOCHDIR)) { #ifdef HAVE_FCHDIR if (fchdir(sp->fts_rfd)) saved_errno = errno; (void)close(sp->fts_rfd); #else if (chdir(sp->fts_rdir)) saved_errno = errno; free(sp->fts_rdir); sp->fts_rdir = NULL; #endif } /* Free up the stream pointer. */ free(sp); /* ISSET() is illegal after this, since the macro touches sp */ /* Set errno and return. */ if (saved_errno) { errno = saved_errno; return (-1); } return (0); } /* * Special case a root of "/" so that slashes aren't appended which would * cause paths to be written as "//foo". */ #define NAPPEND(p) \ (p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 && \ IS_SLASH(p->fts_path[0]) ? 0 : p->fts_pathlen) FTSENT * fts_read(sp) FTS *sp; { FTSENT *p, *tmp; int instr; char *t; int saved_errno; _DIAGASSERT(sp != NULL); /* If finished or unrecoverable error, return NULL. */ if (sp->fts_cur == NULL || ISSET(FTS_STOP)) return (NULL); /* Set current node pointer. */ p = sp->fts_cur; /* Save and zero out user instructions. */ instr = p->fts_instr; p->fts_instr = FTS_NOINSTR; /* Any type of file may be re-visited; re-stat and re-turn. */ if (instr == FTS_AGAIN) { p->fts_info = fts_stat(sp, p, 0); return (p); } /* * Following a symlink -- SLNONE test allows application to see * SLNONE and recover. If indirecting through a symlink, have * keep a pointer to current location. If unable to get that * pointer, follow fails. */ if (instr == FTS_FOLLOW && (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { p->fts_info = fts_stat(sp, p, 1); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { #ifdef HAVE_FCHDIR if ((p->fts_symfd = open(".", O_RDONLY | KMK_OPEN_NO_INHERIT, 0)) == -1) { p->fts_errno = errno; p->fts_info = FTS_ERR; } else if (fcntl(p->fts_symfd, F_SETFD, FD_CLOEXEC) == -1) { p->fts_errno = errno; p->fts_info = FTS_ERR; close(p->fts_symfd); } else p->fts_flags |= FTS_SYMFOLLOW; #endif } return (p); } /* Directory in pre-order. */ if (p->fts_info == FTS_D) { /* If skipped or crossed mount point, do post-order visit. */ if (instr == FTS_SKIP || (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) { #ifdef HAVE_FCHDIR if (p->fts_flags & FTS_SYMFOLLOW) (void)close(p->fts_symfd); #endif if (sp->fts_child) { fts_lfree(sp->fts_child); sp->fts_child = NULL; } p->fts_info = FTS_DP; return (p); } /* Rebuild if only read the names and now traversing. */ if (sp->fts_child && ISSET(FTS_NAMEONLY)) { CLR(FTS_NAMEONLY); fts_lfree(sp->fts_child); sp->fts_child = NULL; } /* * Cd to the subdirectory. * * If have already read and now fail to chdir, whack the list * to make the names come out right, and set the parent errno * so the application will eventually get an error condition. * Set the FTS_DONTCHDIR flag so that when we logically change * directories back to the parent we don't do a chdir. * * If haven't read do so. If the read fails, fts_build sets * FTS_STOP or the fts_info field of the node. */ if (sp->fts_child) { if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { p->fts_errno = errno; p->fts_flags |= FTS_DONTCHDIR; for (p = sp->fts_child; p; p = p->fts_link) p->fts_accpath = p->fts_parent->fts_accpath; } } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) { if (ISSET(FTS_STOP)) return (NULL); return (p); } p = sp->fts_child; sp->fts_child = NULL; goto name; } /* Move to the next node on this level. */ next: tmp = p; if ((p = p->fts_link) != NULL) { free(tmp); /* * If reached the top, return to the original directory, and * load the paths for the next root. */ if (p->fts_level == FTS_ROOTLEVEL) { #ifdef HAVE_FCHDIR if (FCHDIR(sp, sp->fts_rfd)) { #else if (CHDIR(sp, sp->fts_rdir)) { #endif SET(FTS_STOP); return (NULL); } fts_load(sp, p); return (sp->fts_cur = p); } /* * User may have called fts_set on the node. If skipped, * ignore. If followed, get a file descriptor so we can * get back if necessary. */ if (p->fts_instr == FTS_SKIP) goto next; if (p->fts_instr == FTS_FOLLOW) { p->fts_info = fts_stat(sp, p, 1); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { #ifdef HAVE_FCHDIR if ((p->fts_symfd = open(".", O_RDONLY | KMK_OPEN_NO_INHERIT, 0)) == -1) { p->fts_errno = errno; p->fts_info = FTS_ERR; } else if (fcntl(p->fts_symfd, F_SETFD, FD_CLOEXEC) == -1) { p->fts_errno = errno; p->fts_info = FTS_ERR; close(p->fts_symfd); } else p->fts_flags |= FTS_SYMFOLLOW; #endif } p->fts_instr = FTS_NOINSTR; } name: t = sp->fts_path + NAPPEND(p->fts_parent); *t++ = '/'; memmove(t, p->fts_name, (size_t)(p->fts_namelen + 1)); return (sp->fts_cur = p); } /* Move up to the parent node. */ p = tmp->fts_parent; free(tmp); if (p->fts_level == FTS_ROOTPARENTLEVEL) { /* * Done; free everything up and set errno to 0 so the user * can distinguish between error and EOF. */ free(p); errno = 0; return (sp->fts_cur = NULL); } /* Nul terminate the pathname. */ sp->fts_path[p->fts_pathlen] = '\0'; /* * Return to the parent directory. If at a root node or came through * a symlink, go back through the file descriptor. Otherwise, cd up * one directory. */ if (p->fts_level == FTS_ROOTLEVEL) { #ifdef HAVE_FCHDIR if (FCHDIR(sp, sp->fts_rfd)) { #else if (CHDIR(sp, sp->fts_rdir)) { #endif SET(FTS_STOP); return (NULL); } #ifdef HAVE_FCHDIR } else if (p->fts_flags & FTS_SYMFOLLOW) { if (FCHDIR(sp, p->fts_symfd)) { saved_errno = errno; (void)close(p->fts_symfd); errno = saved_errno; SET(FTS_STOP); return (NULL); } (void)close(p->fts_symfd); #else (void)saved_errno; #endif } else if (!(p->fts_flags & FTS_DONTCHDIR) && fts_safe_changedir(sp, p->fts_parent, -1, "..")) { SET(FTS_STOP); return (NULL); } p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; return (sp->fts_cur = p); } /* * Fts_set takes the stream as an argument although it's not used in this * implementation; it would be necessary if anyone wanted to add global * semantics to fts using fts_set. An error return is allowed for similar * reasons. */ /* ARGSUSED */ int fts_set(sp, p, instr) FTS *sp; FTSENT *p; int instr; { _DIAGASSERT(sp != NULL); _DIAGASSERT(p != NULL); if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW && instr != FTS_NOINSTR && instr != FTS_SKIP) { errno = EINVAL; return (1); } p->fts_instr = instr; return (0); } FTSENT * fts_children(sp, instr) FTS *sp; int instr; { FTSENT *p; #ifdef HAVE_FCHDIR int fd; #else char *pszRoot; int rc; #endif _DIAGASSERT(sp != NULL); if (instr && instr != FTS_NAMEONLY) { errno = EINVAL; return (NULL); } /* Set current node pointer. */ p = sp->fts_cur; /* * Errno set to 0 so user can distinguish empty directory from * an error. */ errno = 0; /* Fatal errors stop here. */ if (ISSET(FTS_STOP)) return (NULL); /* Return logical hierarchy of user's arguments. */ if (p->fts_info == FTS_INIT) return (p->fts_link); /* * If not a directory being visited in pre-order, stop here. Could * allow FTS_DNR, assuming the user has fixed the problem, but the * same effect is available with FTS_AGAIN. */ if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */) return (NULL); /* Free up any previous child list. */ if (sp->fts_child) fts_lfree(sp->fts_child); if (instr == FTS_NAMEONLY) { SET(FTS_NAMEONLY); instr = BNAMES; } else instr = BCHILD; /* * If using chdir on a relative path and called BEFORE fts_read does * its chdir to the root of a traversal, we can lose -- we need to * chdir into the subdirectory, and we don't know where the current * directory is, so we can't get back so that the upcoming chdir by * fts_read will work. */ if (p->fts_level != FTS_ROOTLEVEL || IS_SLASH(p->fts_accpath[0]) || ISSET(FTS_NOCHDIR)) return (sp->fts_child = fts_build(sp, instr)); #ifdef HAVE_FCHDIR if ((fd = open(".", O_RDONLY | KMK_OPEN_NO_INHERIT, 0)) == -1) #else if ((pszRoot = getcwd(NULL, 0)) == NULL) #endif return (sp->fts_child = NULL); sp->fts_child = fts_build(sp, instr); #ifdef HAVE_FCHDIR if (fchdir(fd)) { (void)close(fd); return (NULL); } (void)close(fd); #else rc = chdir(pszRoot); free(pszRoot); if (rc) return (NULL); #endif return (sp->fts_child); } /* * This is the tricky part -- do not casually change *anything* in here. The * idea is to build the linked list of entries that are used by fts_children * and fts_read. There are lots of special cases. * * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is * set and it's a physical walk (so that symbolic links can't be directories), * we can do things quickly. First, if it's a 4.4BSD file system, the type * of the file is in the directory entry. Otherwise, we assume that the number * of subdirectories in a node is equal to the number of links to the parent. * The former skips all stat calls. The latter skips stat calls in any leaf * directories and for any files after the subdirectories in the directory have * been found, cutting the stat calls by about 2/3. */ static FTSENT * fts_build(sp, type) FTS *sp; int type; { struct dirent *dp; FTSENT *p, *head; size_t nitems; FTSENT *cur, *tail; DIR *dirp; int adjust, cderrno, descend, len, level, nlinks, saved_errno, nostat; size_t maxlen; #ifdef FTS_WHITEOUT int oflag; #endif char *cp = NULL; /* pacify gcc */ _DIAGASSERT(sp != NULL); /* Set current node pointer. */ cur = sp->fts_cur; /* * Open the directory for reading. If this fails, we're done. * If being called from fts_read, set the fts_info field. */ #if defined(FTS_WHITEOUT) && !defined(__OS2__) if (ISSET(FTS_WHITEOUT)) oflag = DTF_NODUP|DTF_REWIND; else oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND; #elif defined(_MSC_VER) # define __opendir2(path, flag) birdDirOpenExtraInfo(path) #else #define __opendir2(path, flag) opendir(path) #endif if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) { if (type == BREAD) { cur->fts_info = FTS_DNR; cur->fts_errno = errno; } return (NULL); } /* * Nlinks is the number of possible entries of type directory in the * directory if we're cheating on stat calls, 0 if we're not doing * any stat calls at all, -1 if we're doing stats on everything. */ if (type == BNAMES) { nlinks = 0; nostat = 1; } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) { nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2); nostat = 1; } else { nlinks = -1; nostat = 0; } #ifdef notdef (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink); (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n", ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT)); #endif /* * If we're going to need to stat anything or we want to descend * and stay in the directory, chdir. If this fails we keep going, * but set a flag so we don't chdir after the post-order visit. * We won't be able to stat anything, but we can still return the * names themselves. Note, that since fts_read won't be able to * chdir into the directory, it will have to return different path * names than before, i.e. "a/b" instead of "b". Since the node * has already been visited in pre-order, have to wait until the * post-order visit to return the error. There is a special case * here, if there was nothing to stat then it's not an error to * not be able to stat. This is all fairly nasty. If a program * needed sorted entries or stat information, they had better be * checking FTS_NS on the returned nodes. */ cderrno = 0; if (nlinks || type == BREAD) { #ifdef HAVE_FCHDIR if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { #else if (fts_safe_changedir(sp, cur, dirfd(dirp), cur->fts_accpath)) { #endif if (nlinks && type == BREAD) cur->fts_errno = errno; cur->fts_flags |= FTS_DONTCHDIR; descend = 0; cderrno = errno; } else descend = 1; } else descend = 0; /* * Figure out the max file name length that can be stored in the * current path -- the inner loop allocates more path as necessary. * We really wouldn't have to do the maxlen calculations here, we * could do them in fts_read before returning the path, but it's a * lot easier here since the length is part of the dirent structure. * * If not changing directories set a pointer so that can just append * each new name into the path. */ len = NAPPEND(cur); if (ISSET(FTS_NOCHDIR)) { cp = sp->fts_path + len; *cp++ = '/'; } len++; maxlen = sp->fts_pathlen - len; level = cur->fts_level + 1; /* Read the directory, attaching each entry to the `link' pointer. */ adjust = 0; for (head = tail = NULL, nitems = 0; (dp = readdir(dirp)) != NULL;) { size_t dlen; if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) continue; #if HAVE_STRUCT_DIRENT_D_NAMLEN dlen = dp->d_namlen; #else dlen = strlen(dp->d_name); #endif if ((p = fts_alloc(sp, dp->d_name, dlen)) == NULL) goto mem1; if (dlen >= maxlen) { /* include space for NUL */ if (fts_palloc(sp, len + dlen + 1)) { /* * No more memory for path or structures. Save * errno, free up the current structure and the * structures already allocated. */ mem1: saved_errno = errno; if (p) free(p); fts_lfree(head); (void)closedir(dirp); errno = saved_errno; cur->fts_info = FTS_ERR; SET(FTS_STOP); return (NULL); } adjust = 1; if (ISSET(FTS_NOCHDIR)) cp = sp->fts_path + len; maxlen = sp->fts_pathlen - len; } p->fts_pathlen = len + dlen; p->fts_parent = sp->fts_cur; p->fts_level = level; #ifdef FTS_WHITEOUT if (dp->d_type == DT_WHT) p->fts_flags |= FTS_ISW; #endif if (cderrno) { if (nlinks) { p->fts_info = FTS_NS; p->fts_errno = cderrno; } else p->fts_info = FTS_NSOK; p->fts_accpath = cur->fts_accpath; } else if (nlinks == 0 #ifdef DT_DIR || (nostat && dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN) #endif ) { p->fts_accpath = ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name; p->fts_info = FTS_NSOK; } else { /* Build a file name for fts_stat to stat. */ if (ISSET(FTS_NOCHDIR)) { p->fts_accpath = p->fts_path; memmove(cp, p->fts_name, (size_t)(p->fts_namelen + 1)); } else p->fts_accpath = p->fts_name; /* Stat it. */ #ifdef _MSC_VER p->fts_info = fts_stat_dirent(sp, p, 0, dp); #else p->fts_info = fts_stat(sp, p, 0); #endif /* Decrement link count if applicable. */ if (nlinks > 0 && (p->fts_info == FTS_D || p->fts_info == FTS_DC || p->fts_info == FTS_DOT)) --nlinks; } /* We walk in directory order so "ls -f" doesn't get upset. */ p->fts_link = NULL; if (head == NULL) head = tail = p; else { tail->fts_link = p; tail = p; } ++nitems; } (void)closedir(dirp); /* * If had to realloc the path, adjust the addresses for the rest * of the tree. */ if (adjust) fts_padjust(sp, head); /* * If not changing directories, reset the path back to original * state. */ if (ISSET(FTS_NOCHDIR)) { if (cp - 1 > sp->fts_path) --cp; *cp = '\0'; } /* * If descended after called from fts_children or after called from * fts_read and nothing found, get back. At the root level we use * the saved fd; if one of fts_open()'s arguments is a relative path * to an empty directory, we wind up here with no other way back. If * can't get back, we're done. */ if (descend && (type == BCHILD || !nitems) && (cur->fts_level == FTS_ROOTLEVEL ? #ifdef HAVE_FCHDIR FCHDIR(sp, sp->fts_rfd) : #else CHDIR(sp, sp->fts_rdir) : #endif fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { cur->fts_info = FTS_ERR; SET(FTS_STOP); return (NULL); } /* If didn't find anything, return NULL. */ if (!nitems) { if (type == BREAD) cur->fts_info = FTS_DP; return (NULL); } /* Sort the entries. */ if (sp->fts_compar && nitems > 1) head = fts_sort(sp, head, nitems); return (head); } #ifdef _MSC_VER /** Special version of fts_stat that takes the information from the directory * entry returned by readdir(). * * Directory listing returns all the stat information on systems likes * Windows and OS/2. */ static u_short fts_stat_dirent(FTS *sp, FTSENT *p, int follow, struct dirent *pDirEnt) { FTSENT *t; dev_t dev; ino_t ino; struct STAT *sbp, sb; int saved_errno; _DIAGASSERT(sp != NULL); _DIAGASSERT(p != NULL); /* If user needs stat info, stat buffer already allocated. */ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; /* * Copy over the stat info from the direntry. */ *sbp = pDirEnt->d_stat; /* * If doing a logical walk, or application requested FTS_FOLLOW, do * a stat(2) on symlinks. If that fails, assume non-existent * symlink and set the errno from the stat call. */ if (S_ISLNK(sbp->st_mode) && (ISSET(FTS_LOGICAL) || follow)) { if (stat(p->fts_accpath, sbp)) { saved_errno = errno; errno = 0; return (FTS_SLNONE); } } if (S_ISDIR(sbp->st_mode)) { /* * Set the device/inode. Used to find cycles and check for * crossing mount points. Also remember the link count, used * in fts_build to limit the number of stat calls. It is * understood that these fields are only referenced if fts_info * is set to FTS_D. */ dev = p->fts_dev = sbp->st_dev; ino = p->fts_ino = sbp->st_ino; p->fts_nlink = sbp->st_nlink; if (ISDOT(p->fts_name)) return (FTS_DOT); /* * Cycle detection is done by brute force when the directory * is first encountered. If the tree gets deep enough or the * number of symbolic links to directories is high enough, * something faster might be worthwhile. */ #ifdef _MSC_VER if (ino && dev) /** @todo ino emulation on windows... */ #endif for (t = p->fts_parent; t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) if (ino == t->fts_ino && dev == t->fts_dev) { p->fts_cycle = t; return (FTS_DC); } return (FTS_D); } if (S_ISLNK(sbp->st_mode)) return (FTS_SL); if (S_ISREG(sbp->st_mode)) return (FTS_F); return (FTS_DEFAULT); } #endif /* fts_stat_dirent */ static u_short fts_stat(sp, p, follow) FTS *sp; FTSENT *p; int follow; { FTSENT *t; dev_t dev; ino_t ino; struct STAT *sbp, sb; int saved_errno; _DIAGASSERT(sp != NULL); _DIAGASSERT(p != NULL); /* If user needs stat info, stat buffer already allocated. */ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; #ifdef FTS_WHITEOUT /* check for whiteout */ if (p->fts_flags & FTS_ISW) { if (sbp != &sb) { memset(sbp, '\0', sizeof (*sbp)); sbp->st_mode = S_IFWHT; } return (FTS_W); } #endif /* * If doing a logical walk, or application requested FTS_FOLLOW, do * a stat(2). If that fails, check for a non-existent symlink. If * fail, set the errno from the stat call. */ if (ISSET(FTS_LOGICAL) || follow) { if (stat(p->fts_accpath, sbp)) { saved_errno = errno; if (!lstat(p->fts_accpath, sbp)) { errno = 0; return (FTS_SLNONE); } p->fts_errno = saved_errno; goto err; } } else if (lstat(p->fts_accpath, sbp)) { p->fts_errno = errno; err: memset(sbp, 0, sizeof(struct STAT)); return (FTS_NS); } if (S_ISDIR(sbp->st_mode)) { /* * Set the device/inode. Used to find cycles and check for * crossing mount points. Also remember the link count, used * in fts_build to limit the number of stat calls. It is * understood that these fields are only referenced if fts_info * is set to FTS_D. */ dev = p->fts_dev = sbp->st_dev; ino = p->fts_ino = sbp->st_ino; p->fts_nlink = sbp->st_nlink; if (ISDOT(p->fts_name)) return (FTS_DOT); /* * Cycle detection is done by brute force when the directory * is first encountered. If the tree gets deep enough or the * number of symbolic links to directories is high enough, * something faster might be worthwhile. */ #ifdef _MSC_VER if (ino && dev) /** @todo ino emulation on windows... */ #endif for (t = p->fts_parent; t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) if (ino == t->fts_ino && dev == t->fts_dev) { p->fts_cycle = t; return (FTS_DC); } return (FTS_D); } if (S_ISLNK(sbp->st_mode)) return (FTS_SL); if (S_ISREG(sbp->st_mode)) return (FTS_F); return (FTS_DEFAULT); } static FTSENT * fts_sort(sp, head, nitems) FTS *sp; FTSENT *head; size_t nitems; { FTSENT **ap, *p; _DIAGASSERT(sp != NULL); _DIAGASSERT(head != NULL); /* * Construct an array of pointers to the structures and call qsort(3). * Reassemble the array in the order returned by qsort. If unable to * sort for memory reasons, return the directory entries in their * current order. Allocate enough space for the current needs plus * 40 so don't realloc one entry at a time. */ if (nitems > sp->fts_nitems) { FTSENT **new; new = realloc(sp->fts_array, sizeof(FTSENT *) * (nitems + 40)); if (new == 0) return (head); sp->fts_array = new; sp->fts_nitems = nitems + 40; } for (ap = sp->fts_array, p = head; p; p = p->fts_link) *ap++ = p; qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), (int (*)(const void *, const void *))sp->fts_compar); for (head = *(ap = sp->fts_array); --nitems; ++ap) ap[0]->fts_link = ap[1]; ap[0]->fts_link = NULL; return (head); } static FTSENT * fts_alloc(sp, name, namelen) FTS *sp; const char *name; size_t namelen; { FTSENT *p; size_t len; _DIAGASSERT(sp != NULL); _DIAGASSERT(name != NULL); #if defined(ALIGNBYTES) && defined(ALIGN) /* * The file name is a variable length array and no stat structure is * necessary if the user has set the nostat bit. Allocate the FTSENT * structure, the file name and the stat structure in one chunk, but * be careful that the stat structure is reasonably aligned. Since the * fts_name field is declared to be of size 1, the fts_name pointer is * namelen + 2 before the first possible address of the stat structure. */ len = sizeof(FTSENT) + namelen; if (!ISSET(FTS_NOSTAT)) len += sizeof(struct STAT) + ALIGNBYTES; if ((p = malloc(len)) == NULL) return (NULL); if (!ISSET(FTS_NOSTAT)) p->fts_statp = (struct STAT *)ALIGN((u_long)(p->fts_name + namelen + 2)); #else (void)len; if ((p = malloc(sizeof(FTSENT) + namelen)) == NULL) return (NULL); if (!ISSET(FTS_NOSTAT)) if ((p->fts_statp = malloc(sizeof(struct STAT))) == NULL) { free(p); return (NULL); } #endif /* Copy the name plus the trailing NULL. */ memmove(p->fts_name, name, namelen + 1); p->fts_namelen = namelen; p->fts_path = sp->fts_path; p->fts_errno = 0; p->fts_flags = 0; p->fts_instr = FTS_NOINSTR; p->fts_number = 0; p->fts_pointer = NULL; return (p); } static void fts_lfree(head) FTSENT *head; { FTSENT *p; /* XXX: head may be NULL ? */ /* Free a linked list of structures. */ while ((p = head) != NULL) { head = head->fts_link; #if !defined(ALIGNBYTES) || !defined(ALIGN) if (p->fts_statp) free(p->fts_statp); #endif free(p); } } static size_t fts_pow2(x) size_t x; { x--; x |= x>>1; x |= x>>2; x |= x>>4; x |= x>>8; x |= x>>16; #if LONG_BIT > 32 x |= x>>32; #endif #if LONG_BIT > 64 x |= x>>64; #endif x++; return (x); } /* * Allow essentially unlimited paths; find, rm, ls should all work on any tree. * Most systems will allow creation of paths much longer than MAXPATHLEN, even * though the kernel won't resolve them. Round up the new size to a power of 2, * so we don't realloc the path 2 bytes at a time. */ static int fts_palloc(sp, size) FTS *sp; size_t size; { char *new; _DIAGASSERT(sp != NULL); #if 1 /* Protect against fts_pathlen overflow. */ if (size > USHRT_MAX + 1) { errno = ENOMEM; return (1); } #endif size = fts_pow2(size); new = realloc(sp->fts_path, size); if (new == 0) return (1); sp->fts_path = new; sp->fts_pathlen = size; return (0); } /* * When the path is realloc'd, have to fix all of the pointers in structures * already returned. */ static void fts_padjust(sp, head) FTS *sp; FTSENT *head; { FTSENT *p; char *addr; _DIAGASSERT(sp != NULL); #define ADJUST(p) do { \ if ((p)->fts_accpath != (p)->fts_name) \ (p)->fts_accpath = \ addr + ((p)->fts_accpath - (p)->fts_path); \ (p)->fts_path = addr; \ } while (/*CONSTCOND*/0) addr = sp->fts_path; /* Adjust the current set of children. */ for (p = sp->fts_child; p; p = p->fts_link) ADJUST(p); /* Adjust the rest of the tree, including the current level. */ for (p = head; p->fts_level >= FTS_ROOTLEVEL;) { ADJUST(p); p = p->fts_link ? p->fts_link : p->fts_parent; } } static size_t fts_maxarglen(argv) char * const *argv; { size_t len, max; _DIAGASSERT(argv != NULL); for (max = 0; *argv; ++argv) if ((len = strlen(*argv)) > max) max = len; return (max + 1); } /* * Change to dir specified by fd or p->fts_accpath without getting * tricked by someone changing the world out from underneath us. * Assumes p->fts_dev and p->fts_ino are filled in. */ static int fts_safe_changedir(sp, p, fd, path) const FTS *sp; const FTSENT *p; int fd; const char *path; { int oldfd = fd, ret = -1; struct STAT sb; if (ISSET(FTS_NOCHDIR)) return 0; #ifdef HAVE_FCHDIR if (oldfd < 0) { if (!path) /* shuts up gcc nonull checks*/ return -1; fd = open(path, O_RDONLY | KMK_OPEN_NO_INHERIT); if (fd == -1) return -1; } if (fstat(fd, &sb) == -1) goto bail; #else if (stat(path, &sb)) goto bail; #endif if (sb.st_ino != p->fts_ino || sb.st_dev != p->fts_dev) { errno = ENOENT; goto bail; } #ifdef HAVE_FCHDIR ret = fchdir(fd); #else ret = chdir(path); #endif bail: #ifdef HAVE_FCHDIR if (oldfd < 0) { int save_errno = errno; (void)close(fd); errno = save_errno; } #endif return ret; } kbuild-3686/src/kmk/kmkbuiltin/sleep.c0000664000175000017500000001220315053010074017703 0ustar locutuslocutus/* $Id: sleep.c 3192 2018-03-26 20:25:56Z bird $ */ /** @file * kmk_sleep - suspend execution for an interval of time. */ /* * Copyright (c) 2008-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include #if defined(_MSC_VER) # include #else # include # include #endif #include "err.h" #include "../kmkbuiltin.h" static int kmk_builtin_sleep_usage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s [s]\n" " or: %s ms\n" " or: %s m\n" " or: %s h\n" " or: %s d\n" " or: %s --help\n" " or: %s --version\n" "\n" "Only integer values are accepted.\n" , pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); return 1; } int kmk_builtin_sleep(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { long cMsToSleep; long lTmp; unsigned long ulFactor; char *pszInterval; char *pszSuff; /* * Parse arguments. */ if (argc != 2) return kmk_builtin_sleep_usage(pCtx, 1); /* help request */ if ( !strcmp(argv[1], "-h") || !strcmp(argv[1], "-?") || !strcmp(argv[1], "-H") || !strcmp(argv[1], "--help")) { kmk_builtin_sleep_usage(pCtx, 0); return 0; } /* version request */ if ( !strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) { printf("kmk_sleep - kBuild version %d.%d.%d (r%u)\n" "Copyright (c) 2008-2009 knut st. osmundsen\n", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, KBUILD_SVN_REV); return 0; } /* * Try convert the argument to a time period. * Allow spaces before, between and after the different parts. */ pszInterval = argv[1]; while (isspace(*pszInterval)) pszInterval++; cMsToSleep = strtol(pszInterval, &pszSuff, 0); if (pszSuff == pszInterval) return errx(pCtx, 1, "malformed interval '%s'!\n", pszInterval); while (isspace(*pszSuff)) pszSuff++; if (!*pszSuff) ulFactor = 1000; /* s */ else { /* find the suffix length and check that it's only white space following it. */ int cchSuff; int i = 1; while (pszSuff[i] && !isspace(pszSuff[i])) i++; cchSuff = i; while (pszSuff[i]) { if (!isspace(pszSuff[i])) return errx(pCtx, 1, "malformed interval '%s'!\n", pszInterval); i++; } if (cchSuff == 2 && !strncmp (pszSuff, "ms", 2)) ulFactor = 1; else if (cchSuff == 1 && *pszSuff == 's') ulFactor = 1000; else if (cchSuff == 1 && *pszSuff == 'm') ulFactor = 60*1000; else if (cchSuff == 1 && *pszSuff == 'h') ulFactor = 60*60*1000; else if (cchSuff == 1 && *pszSuff == 'd') ulFactor = 24*60*60*1000; else return errx(pCtx, 1, "unknown suffix '%.*s'!\n", cchSuff, pszSuff); } lTmp = cMsToSleep; cMsToSleep *= ulFactor; if ((cMsToSleep / ulFactor) != (unsigned long)lTmp) return errx(pCtx, 1, "time interval overflow!\n"); /* * Do the actual sleeping. */ if (cMsToSleep > 0) { #if defined(_MSC_VER) Sleep(cMsToSleep); #else if (cMsToSleep) { struct timespec TimeSpec; TimeSpec.tv_nsec = (cMsToSleep % 1000) * 1000000; TimeSpec.tv_sec = cMsToSleep / 1000; nanosleep(&TimeSpec, NULL); } #endif } return 0; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_sleep", NULL }; return kmk_builtin_sleep(argc, argv, envp, &Ctx); } #endif kbuild-3686/src/kmk/kmkbuiltin/getopt_r.h0000664000175000017500000001347415053010074020436 0ustar locutuslocutus/* Reentrant version of getopt. Based on ../getopt*.*: Declarations for getopt. Copyright (C) 1989-2016 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . Modifications: Copyright (c) 2018 knut st. osmundsen */ /* Not quite safe to mix when converting code. */ #ifdef _GETOPT_H # define _GETOPT_H "getopt.h was included already" # error "getopt.h was included already" #endif #ifndef INCLUDED_GETOPT_R_H #define INCLUDED_GETOPT_R_H 1 #include #ifdef __cplusplus extern "C" { #endif typedef struct getopt_state_r { /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ /*extern*/ char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /*extern*/ int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ /*extern*/ int opterr; /* Set to an option character which was unrecognized. */ /*extern*/ int optopt; /* Internal state: */ /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ /*static*/ char *nextchar; /* REQUIRE_ORDER, PERMUTE or RETURN_IN_ORDER, see getopt_r.c. */ /*static*/ int ordering; /* Value of POSIXLY_CORRECT environment variable. */ /*static*/ const char *posixly_correct; /* bird: added 'const' */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ /*static*/ int first_nonopt; /*static*/ int last_nonopt; /* Mainly for asserting usage sanity. */ /*static*/ void *__getopt_initialized; /* New internal state (to resubmitting same parameters in each call): */ /* new: the argument vector length. */ int argc; /* new: the argument vector. */ char * const *argv; /* new: the short option string (can be NULL/empty). */ const char *optstring; /* new: the short option string length. */ size_t len_optstring; /* new: the long options (can be NULL) */ const struct option *long_options; /* Output context for err.h. */ struct KMKBUILTINCTX *pCtx; } getopt_state_r; #ifndef no_argument /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if defined (__STDC__) && __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #endif /* Same as ../getopt.h. Fix later? */ extern void getopt_initialize_r (struct getopt_state_r *gos, int argc, char *const *argv, const char *shortopts, const struct option *longopts, char **envp, struct KMKBUILTINCTX *pCtx); extern int getopt_r (struct getopt_state_r *gos); extern int getopt_long_r (struct getopt_state_r *gos, int *longind); extern int getopt_long_only_r (struct getopt_state_r *gos, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal_r (struct getopt_state_r *gos, const struct option *longopts, int *longind, int long_only); #ifdef __cplusplus } #endif #endif /* getopt_r.h */ kbuild-3686/src/kmk/kmkbuiltin/rm.c0000664000175000017500000006354215053010074017225 0ustar locutuslocutus/*- * Copyright (c) 1990, 1993, 1994 * 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. * 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 0 #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1990, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)rm.c 8.5 (Berkeley) 4/18/94"; #endif /* not lint */ #include /*__FBSDID("$FreeBSD: src/bin/rm/rm.c,v 1.47 2004/04/06 20:06:50 markm Exp $");*/ #endif /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #define FAKES_NO_GETOPT_H /* bird */ #include "config.h" #include #if !defined(_MSC_VER) && !defined(__HAIKU__) # include # ifndef __gnu_hurd__ # include # endif #endif #include "err.h" #include #include #include "fts.h" #include #include #include #include #include #ifndef __HAIKU__ # include #endif #include #include #include "getopt_r.h" #ifdef __HAIKU__ # include "haikufakes.h" #endif #ifdef __NetBSD__ # include # define fflagstostr(flags) flags_to_string(flags, "") #endif #ifdef KBUILD_OS_WINDOWS # ifdef _MSC_VER # include "mscfakes.h" # endif # include "nt/ntunlink.h" /* redefines both unlink & rmdir */ #endif #if defined(__OS2__) || defined(_MSC_VER) # include # include #endif #include "kmkbuiltin.h" #include "kbuild_protection.h" #include "k/kDefs.h" /* for K_OS */ /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ #if defined(__EMX__) || defined(KBUILD_OS_WINDOWS) # define IS_SLASH(ch) ( (ch) == '/' || (ch) == '\\' ) # define HAVE_DOS_PATHS 1 # define DEFAULT_PROTECTION_DEPTH 1 #else # define IS_SLASH(ch) ( (ch) == '/' ) # undef HAVE_DOS_PATHS # define DEFAULT_PROTECTION_DEPTH 2 #endif #ifdef __EMX__ #undef S_IFWHT #undef S_ISWHT #endif #ifndef S_IFWHT #define S_IFWHT 0 #define S_ISWHT(s) 0 #define undelete(s) (-1) #endif #if 1 #define CUR_LINE_H2(x) "[line " #x "]" #define CUR_LINE_H1(x) CUR_LINE_H2(x) #define CUR_LINE() CUR_LINE_H1(__LINE__) #else # define CUR_LINE() #endif /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ typedef struct RMINSTANCE { PKMKBUILTINCTX pCtx; int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok; #ifdef KBUILD_OS_WINDOWS int fUseNtDeleteFile; #endif uid_t uid; KBUILDPROTECTION g_ProtData; } RMINSTANCE; typedef RMINSTANCE *PRMINSTANCE; /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { "disable-protection", no_argument, 0, 263 }, { "enable-protection", no_argument, 0, 264 }, { "enable-full-protection", no_argument, 0, 265 }, { "disable-full-protection", no_argument, 0, 266 }, { "protection-depth", required_argument, 0, 267 }, #ifdef KBUILD_OS_WINDOWS { "nt-delete-file", no_argument, 0, 268 }, #endif { 0, 0, 0, 0 }, }; /********************************************************************************************************************************* * Internal Functions * *********************************************************************************************************************************/ extern void bsd_strmode(mode_t mode, char *p); /* strmode.c */ static int check(PRMINSTANCE, char *, char *, struct stat *); static void checkdot(PRMINSTANCE, char **); static int rm_file(PRMINSTANCE, char **); static int rm_overwrite(PRMINSTANCE, char *, struct stat *); static int rm_tree(PRMINSTANCE, char **); static int usage(PKMKBUILTINCTX, int); /* * rm -- * This rm is different from historic rm's, but is expected to match * POSIX 1003.2 behavior. The most visible difference is that -f * has two specific effects now, ignore non-existent files and force * file removal. */ int kmk_builtin_rm(int argc, char *argv[], char **envp, PKMKBUILTINCTX pCtx) { RMINSTANCE This; struct getopt_state_r gos; int ch, rflag; /* Init global instance data */ This.pCtx = pCtx; This.dflag = 0; This.eval = 0; This.fflag = 0; This.iflag = 0; This.Pflag = 0; This.vflag = 0; This.Wflag = 0; This.stdin_ok = 0; #ifdef KBUILD_OS_WINDOWS This.fUseNtDeleteFile = 0; #endif This.uid = 0; kBuildProtectionInit(&This.g_ProtData, pCtx); rflag = 0; getopt_initialize_r(&gos, argc, argv, "dfiPRvW", long_options, envp, pCtx); while ((ch = getopt_long_r(&gos, NULL)) != -1) switch (ch) { case 'd': This.dflag = 1; break; case 'f': This.fflag = 1; This.iflag = 0; break; case 'i': This.fflag = 0; This.iflag = 1; break; case 'P': This.Pflag = 1; break; case 'R': #if 0 case 'r': /* Compatibility. */ #endif rflag = 1; break; case 'v': This.vflag = 1; break; #ifdef FTS_WHITEOUT case 'W': This.Wflag = 1; break; #endif case 261: kBuildProtectionTerm(&This.g_ProtData); usage(pCtx, 0); return 0; case 262: kBuildProtectionTerm(&This.g_ProtData); return kbuild_version(argv[0]); case 263: kBuildProtectionDisable(&This.g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); break; case 264: kBuildProtectionEnable(&This.g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); break; case 265: kBuildProtectionEnable(&This.g_ProtData, KBUILDPROTECTIONTYPE_FULL); break; case 266: kBuildProtectionDisable(&This.g_ProtData, KBUILDPROTECTIONTYPE_FULL); break; case 267: if (kBuildProtectionSetDepth(&This.g_ProtData, gos.optarg)) { kBuildProtectionTerm(&This.g_ProtData); return 1; } break; #ifdef KBUILD_OS_WINDOWS case 268: This.fUseNtDeleteFile = 1; break; #endif case '?': default: kBuildProtectionTerm(&This.g_ProtData); return usage(pCtx, 1); } argc -= gos.optind; argv += gos.optind; if (argc < 1) { kBuildProtectionTerm(&This.g_ProtData); if (This.fflag) return (0); return usage(pCtx, 1); } if (!kBuildProtectionScanEnv(&This.g_ProtData, envp, "KMK_RM_")) { checkdot(&This, argv); This.uid = geteuid(); if (*argv) { This.stdin_ok = isatty(STDIN_FILENO); if (rflag) This.eval |= rm_tree(&This, argv); else This.eval |= rm_file(&This, argv); } } else { This.eval = 1; } kBuildProtectionTerm(&This.g_ProtData); return This.eval; } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_rm", NULL }; return kmk_builtin_rm(argc, argv, envp, &Ctx); } #endif static int rm_tree(PRMINSTANCE pThis, char **argv) { FTS *fts; FTSENT *p; int needstat; int flags; int rval; /* * Check up front before anything is deleted. This will not catch * everything, but we'll check the individual items later. */ int i; for (i = 0; argv[i]; i++) { if (kBuildProtectionEnforce(&pThis->g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, argv[i])) { return 1; } } /* * Remove a file hierarchy. If forcing removal (-f), or interactive * (-i) or can't ask anyway (stdin_ok), don't stat the file. */ needstat = !pThis->uid || (!pThis->fflag && !pThis->iflag && pThis->stdin_ok); /* * If the -i option is specified, the user can skip on the pre-order * visit. The fts_number field flags skipped directories. */ #define SKIPPED 1 flags = FTS_PHYSICAL; #ifndef KMK_BUILTIN_STANDALONE flags |= FTS_NOCHDIR; /* Must not change the directory from inside kmk! */ #endif if (!needstat) flags |= FTS_NOSTAT; #ifdef FTS_WHITEOUT if (pThis->Wflag) flags |= FTS_WHITEOUT; #endif if (!(fts = fts_open(argv, flags, NULL))) { return err(pThis->pCtx, 1, "fts_open"); } while ((p = fts_read(fts)) != NULL) { const char *operation = "chflags"; switch (p->fts_info) { case FTS_DNR: if (!pThis->fflag || p->fts_errno != ENOENT) pThis->eval = errx(pThis->pCtx, 1, "fts: %s: %s" CUR_LINE() "\n", p->fts_path, strerror(p->fts_errno)); continue; case FTS_ERR: fts_close(fts); return errx(pThis->pCtx, 1, "fts: %s: %s " CUR_LINE(), p->fts_path, strerror(p->fts_errno)); case FTS_NS: /* * Assume that since fts_read() couldn't stat the * file, it can't be unlinked. */ if (!needstat) break; if (!pThis->fflag || p->fts_errno != ENOENT) pThis->eval = errx(pThis->pCtx, 1, "fts: %s: %s " CUR_LINE() "\n", p->fts_path, strerror(p->fts_errno)); continue; case FTS_D: /* Pre-order: give user chance to skip. */ if (!pThis->fflag && !check(pThis, p->fts_path, p->fts_accpath, p->fts_statp)) { (void)fts_set(fts, p, FTS_SKIP); p->fts_number = SKIPPED; } #ifdef UF_APPEND else if (!pThis->uid && (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) && !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) && chflags(p->fts_accpath, p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0) goto err; #endif continue; case FTS_DP: /* Post-order: see if user skipped. */ if (p->fts_number == SKIPPED) continue; break; default: if (!pThis->fflag && !check(pThis, p->fts_path, p->fts_accpath, p->fts_statp)) continue; } /* * Protect against deleting root files and directories. */ if (kBuildProtectionEnforce(&pThis->g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, p->fts_accpath)) { fts_close(fts); return 1; } rval = 0; #ifdef UF_APPEND if (!pThis->uid && (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) && !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE))) rval = chflags(p->fts_accpath, p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)); #endif if (rval == 0) { /* * If we can't read or search the directory, may still be * able to remove it. Don't print out the un{read,search}able * message unless the remove fails. */ switch (p->fts_info) { case FTS_DP: case FTS_DNR: #ifdef KBUILD_OS_WINDOWS if (p->fts_parent->fts_dirfd != NT_FTS_INVALID_HANDLE_VALUE) { rval = birdRmDirForcedEx(p->fts_parent->fts_dirfd, p->fts_name); } else { rval = birdRmDirForced(p->fts_accpath); } #else rval = rmdir(p->fts_accpath); #endif if (rval == 0 || (pThis->fflag && errno == ENOENT)) { if (rval == 0 && pThis->vflag) kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s\n", p->fts_path); #if defined(KMK) && defined(KBUILD_OS_WINDOWS) if (rval == 0) { extern int dir_cache_deleted_directory(const char *pszDir); dir_cache_deleted_directory(p->fts_accpath); } #endif continue; } operation = "rmdir"; break; #ifdef FTS_W case FTS_W: rval = undelete(p->fts_accpath); if (rval == 0 && (pThis->fflag && errno == ENOENT)) { if (pThis->vflag) kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s\n", p->fts_path); continue; } operation = "undelete"; break; #endif case FTS_NS: /* * Assume that since fts_read() couldn't stat * the file, it can't be unlinked. */ if (pThis->fflag) continue; /* FALLTHROUGH */ default: if (pThis->Pflag) if (!rm_overwrite(pThis, p->fts_accpath, NULL)) continue; #ifdef KBUILD_OS_WINDOWS if (p->fts_parent->fts_dirfd != NT_FTS_INVALID_HANDLE_VALUE) { if (p->fts_info != FTS_SL && p->fts_info != FTS_SLNONE) { rval = birdUnlinkForcedFastEx(p->fts_parent->fts_dirfd, p->fts_name); } else { /* NtDeleteFile doesn't work on directory links, so slow symlink deletion: */ if (p->fts_stat.st_isdirsymlink) { rval = birdRmDirForcedEx(p->fts_parent->fts_dirfd, p->fts_name); } else { rval = birdUnlinkForcedEx(p->fts_parent->fts_dirfd, p->fts_name); } } } else { if (p->fts_info != FTS_SL && p->fts_info != FTS_SLNONE) { rval = birdUnlinkForcedFast(p->fts_accpath); } else { /* NtDeleteFile doesn't work on directory links, so slow symlink deletion: */ if (p->fts_stat.st_isdirsymlink) { rval = birdRmDirForced(p->fts_accpath); } else { rval = birdUnlinkForced(p->fts_accpath); } } } #else rval = unlink(p->fts_accpath); #endif if (rval == 0 || (pThis->fflag && errno == ENOENT)) { if (rval == 0 && pThis->vflag) kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s\n", p->fts_path); continue; } operation = "unlink"; break; } } #ifdef UF_APPEND err: #endif pThis->eval = errx(pThis->pCtx, 1, "%s: %s failed: %s " CUR_LINE() "\n", p->fts_path, operation, strerror(errno)); } if (errno) { pThis->eval = errx(pThis->pCtx, 1, "fts_read: %s " CUR_LINE() "\n", strerror(errno)); } fts_close(fts); return pThis->eval; } static int rm_file(PRMINSTANCE pThis, char **argv) { struct stat sb; int rval; char *f; /* * Check up front before anything is deleted. */ int i; for (i = 0; argv[i]; i++) { if (kBuildProtectionEnforce(&pThis->g_ProtData, KBUILDPROTECTIONTYPE_FULL, argv[i])) return 1; } /* * Remove a file. POSIX 1003.2 states that, by default, attempting * to remove a directory is an error, so must always stat the file. */ while ((f = *argv++) != NULL) { const char *operation = "?"; /* Assume if can't stat the file, can't unlink it. */ if (lstat(f, &sb)) { #ifdef FTS_WHITEOUT if (pThis->Wflag) { sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR; } else { #else { #endif if (!pThis->fflag || errno != ENOENT) pThis->eval = errx(pThis->pCtx, 1, "%s: lstat failed: %s " CUR_LINE() "\n", f, strerror(errno)); continue; } #ifdef FTS_WHITEOUT } else if (pThis->Wflag) { errx(pThis->pCtx, 1, "%s: %s\n", f, strerror(EEXIST)); pThis->eval = 1; continue; #endif } if (S_ISDIR(sb.st_mode) && !pThis->dflag) { pThis->eval = errx(pThis->pCtx, 1, "%s: is a directory\n", f); continue; } if (!pThis->fflag && !S_ISWHT(sb.st_mode) && !check(pThis, f, f, &sb)) continue; rval = 0; #ifdef UF_APPEND if (!pThis->uid && (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) && !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE))) rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE)); #endif if (rval == 0) { if (S_ISWHT(sb.st_mode)) { rval = undelete(f); operation = "undelete"; } else if (S_ISDIR(sb.st_mode)) { rval = rmdir(f); operation = "rmdir"; } else { if (pThis->Pflag) if (!rm_overwrite(pThis, f, &sb)) continue; #ifndef KBUILD_OS_WINDOWS rval = unlink(f); operation = "unlink"; #else /*if (sb.st_isdirsymlink) { rval = birdRmDirForced(f); operation = "rmdir"; } else*/ if (pThis->fUseNtDeleteFile /*&& S_ISREG(sb.st_mode) && !sb.st_isdirsymlink*/) { rval = birdUnlinkForcedFast(f); operation = "NtDeleteFile"; } else { rval = birdUnlinkForced(f); operation = "unlink"; } #endif } } if (rval && (!pThis->fflag || errno != ENOENT)) pThis->eval = errx(pThis->pCtx, 1, "%s: %s failed: %s" CUR_LINE() "\n", f, operation, strerror(errno)); if (pThis->vflag && rval == 0) kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s\n", f); } return pThis->eval; } /* * rm_overwrite -- * Overwrite the file 3 times with varying bit patterns. * * XXX * This is a cheap way to *really* delete files. Note that only regular * files are deleted, directories (and therefore names) will remain. * Also, this assumes a fixed-block file system (like FFS, or a V7 or a * System V file system). In a logging file system, you'll have to have * kernel support. */ static int rm_overwrite(PRMINSTANCE pThis, char *file, struct stat *sbp) { struct stat sb; #ifdef HAVE_FSTATFS struct statfs fsb; #endif off_t len; int bsize, fd, wlen; char *buf = NULL; const char *operation = "lstat"; int error; fd = -1; if (sbp == NULL) { if (lstat(file, &sb)) goto err; sbp = &sb; } if (!S_ISREG(sbp->st_mode)) return (1); operation = "open"; if ((fd = open(file, O_WRONLY | KMK_OPEN_NO_INHERIT, 0)) == -1) goto err; #ifdef HAVE_FSTATFS if (fstatfs(fd, &fsb) == -1) goto err; bsize = MAX(fsb.f_iosize, 1024); #elif defined(HAVE_ST_BLKSIZE) bsize = MAX(sb.st_blksize, 1024); #else bsize = 1024; #endif if ((buf = malloc(bsize)) == NULL) { err(pThis->pCtx, 1, "%s: malloc", file); close(fd); return 1; } #define PASS(byte) { \ operation = "write"; \ memset(buf, byte, bsize); \ for (len = sbp->st_size; len > 0; len -= wlen) { \ wlen = len < bsize ? len : bsize; \ if (write(fd, buf, wlen) != wlen) \ goto err; \ } \ } PASS(0xff); operation = "fsync/lseek"; if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) goto err; PASS(0x00); operation = "fsync/lseek"; if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) goto err; PASS(0xff); if (!fsync(fd) && !close(fd)) { free(buf); return (1); } operation = "fsync/close"; err: pThis->eval = 1; error = errno; if (buf) free(buf); if (fd != -1) close(fd); errx(pThis->pCtx, 1, "%s: %s: %s: %s" CUR_LINE() "\n", operation, pThis->pCtx->pszProgName, file, strerror(error)); return (0); } static int check(PRMINSTANCE pThis, char *path, char *name, struct stat *sp) { int ch, first; char modep[15], *flagsp; /* Check -i first. */ if (pThis->iflag) (void)fprintf(stderr, "%s: remove %s? ", pThis->pCtx->pszProgName, path); else { /* * If it's not a symbolic link and it's unwritable and we're * talking to a terminal, ask. Symbolic links are excluded * because their permissions are meaningless. Check stdin_ok * first because we may not have stat'ed the file. * Also skip this check if the -P option was specified because * we will not be able to overwrite file contents and will * barf later. */ if (!pThis->stdin_ok || S_ISLNK(sp->st_mode) || pThis->Pflag || (!access(name, W_OK) && #ifdef SF_APPEND !(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) && (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !pThis->uid)) #else 1) #endif ) return (1); bsd_strmode(sp->st_mode, modep); #if defined(SF_APPEND) && K_OS != K_OS_GNU_KFBSD && K_OS != K_OS_GNU_HURD if ((flagsp = fflagstostr(sp->st_flags)) == NULL) { err(pThis->pCtx, 1, "fflagstostr"); flagsp = ""; } (void)fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ", modep + 1, modep[9] == ' ' ? "" : " ", user_from_uid(sp->st_uid, 0), group_from_gid(sp->st_gid, 0), *flagsp ? flagsp : "", *flagsp ? " " : "", path); free(flagsp); #else (void)flagsp; (void)fprintf(stderr, "override %s%s %d/%d for %s? ", modep + 1, modep[9] == ' ' ? "" : " ", sp->st_uid, sp->st_gid, path); #endif } (void)fflush(stderr); first = ch = getchar(); while (ch != '\n' && ch != EOF) ch = getchar(); return (first == 'y' || first == 'Y'); } #define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2]))) static void checkdot(PRMINSTANCE pThis, char **argv) { char *p, **save, **t; int complained; complained = 0; for (t = argv; *t;) { #ifdef HAVE_DOS_PATHS const char *tmp = p = *t; while (*tmp) { switch (*tmp) { case '/': case '\\': case ':': p = (char *)tmp + 1; break; } tmp++; } #else if ((p = strrchr(*t, '/')) != NULL) ++p; else p = *t; #endif if (ISDOT(p)) { if (!complained++) warnx(pThis->pCtx, "\".\" and \"..\" may not be removed\n"); pThis->eval = 1; for (save = t; (t[0] = t[1]) != NULL; ++t) continue; t = save; } else ++t; } } static int usage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s [options] file ...\n" " or: %s --help\n" " or: %s --version\n" "\n" "Options:\n" " -f\n" " Attempt to remove files without prompting, regardless of the file\n" " permission. Ignore non-existing files. Overrides previous -i's.\n" " -i\n" " Prompt for each file. Always.\n" " -d\n" " Attempt to remove directories as well as other kinds of files.\n" " -P\n" " Overwrite regular files before deleting; three passes: ff,0,ff\n" " -R\n" " Attempt to remove the file hierachy rooted in each file argument.\n" " This option implies -d and file protection.\n" " -v\n" " Be verbose, show files as they are removed.\n" " -W\n" " Undelete white-out files.\n" " --disable-protection\n" " Will disable the protection file protection applied with -R.\n" " --enable-protection\n" " Will enable the protection file protection applied with -R.\n" " --enable-full-protection\n" " Will enable the protection file protection for all operations.\n" " --disable-full-protection\n" " Will disable the protection file protection for all operations.\n" " --protection-depth\n" " Number or path indicating the file protection depth. Default: %d\n" "\n" "Environment:\n" " KMK_RM_DISABLE_PROTECTION\n" " Same as --disable-protection. Overrides command line.\n" " KMK_RM_ENABLE_PROTECTION\n" " Same as --enable-protection. Overrides everyone else.\n" " KMK_RM_ENABLE_FULL_PROTECTION\n" " Same as --enable-full-protection. Overrides everyone else.\n" " KMK_RM_DISABLE_FULL_PROTECTION\n" " Same as --disable-full-protection. Overrides command line.\n" " KMK_RM_PROTECTION_DEPTH\n" " Same as --protection-depth. Overrides command line.\n" "\n" "The file protection of the top %d layers of the file hierarchy is there\n" "to try prevent makefiles from doing bad things to your system. This\n" "protection is not bulletproof, but should help prevent you from shooting\n" "yourself in the foot.\n" , pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth()); return EX_USAGE; } kbuild-3686/src/kmk/kmkbuiltin/printf.c0000664000175000017500000005650115053010074020106 0ustar locutuslocutus/* $NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $ */ /* * Copyright (c) 1989, 1993 * 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. 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. */ /*#include #ifndef lint #if !defined(BUILTIN) && !defined(SHELL) __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ The Regents of the University of California. All rights reserved.\n"); #endif #endif #ifndef lint #if 0 static char sccsid[] = "@(#)printf.c 8.2 (Berkeley) 3/22/95"; #else __RCSID("$NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $"); #endif #endif*/ /* not lint */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #define FAKES_NO_GETOPT_H /* bird */ #if !defined(KMK_BUILTIN_STANDALONE) && !defined(BUILTIN) && !defined(SHELL) # include "../makeint.h" # include "../filedef.h" # include "../variable.h" #else # include "config.h" #endif #include #include #include "err.h" #include #include #include #include #include #include #include #include #include #include "getopt_r.h" #ifdef __sun__ # include "solfakes.h" #endif #ifdef _MSC_VER # include "mscfakes.h" #endif #include "../kmkbuiltin.h" #ifdef KBUILD_OS_WINDOWS /* This is a trick to speed up console output on windows. */ # include "console.h" # undef fwrite # define fwrite maybe_con_fwrite #endif #if 0 #ifdef BUILTIN /* csh builtin */ #define kmk_builtin_printf progprintf #endif #ifdef SHELL /* sh (aka ash) builtin */ #define kmk_builtin_printf printfcmd #include "../../bin/sh/bltin/bltin.h" #endif /* SHELL */ #endif /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ #if 0 /*def __GNUC__ - bird: gcc complains about non-ISO-standard escape. */ #define ESCAPE '\e' #else #define ESCAPE 033 #endif #define PF(f, func) { \ if (fieldwidth != -1) { \ if (precision != -1) \ (void)wrap_printf(pThis, f, fieldwidth, precision, func); \ else \ (void)wrap_printf(pThis, f, fieldwidth, func); \ } else if (precision != -1) \ (void)wrap_printf(pThis, f, precision, func); \ else \ (void)wrap_printf(pThis, f, func); \ } #define APF(cpp, f, func) { \ if (fieldwidth != -1) { \ if (precision != -1) \ (void)asprintf(cpp, f, fieldwidth, precision, func); \ else \ (void)asprintf(cpp, f, fieldwidth, func); \ } else if (precision != -1) \ (void)asprintf(cpp, f, precision, func); \ else \ (void)asprintf(cpp, f, func); \ } /********************************************************************************************************************************* * Structures and Typedefs * *********************************************************************************************************************************/ typedef struct PRINTFINSTANCE { PKMKBUILTINCTX pCtx; /* former globals */ size_t b_length; char *b_fmt; int rval; char **gargv; #ifndef KMK_BUILTIN_STANDALONE char *g_o; #endif /* former function level statics in common_printf(); both need freeing. */ char *a, *t; /* former function level statics in conv_expand(); needs freeing. */ char *conv_str; /* Buffer the output because windows doesn't do line buffering of stdout. */ size_t g_cchBuf; char g_achBuf[256]; } PRINTFINSTANCE; typedef PRINTFINSTANCE *PPRINTFINSTANCE; /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; /********************************************************************************************************************************* * Internal Functions * *********************************************************************************************************************************/ static int common_printf(PPRINTFINSTANCE pThis, char *argv[], PKMKBUILTINCTX pCtx); static int common_printf_inner(PPRINTFINSTANCE pThis, char *argv[]); static void conv_escape_str(PPRINTFINSTANCE, char *, void (*)(PPRINTFINSTANCE, int)); static char *conv_escape(PPRINTFINSTANCE, char *, char *); static const char *conv_expand(PPRINTFINSTANCE, const char *); static int getchr(PPRINTFINSTANCE); static double getdouble(PPRINTFINSTANCE); static int getwidth(PPRINTFINSTANCE); static intmax_t getintmax(PPRINTFINSTANCE); static uintmax_t getuintmax(PPRINTFINSTANCE); static char *getstr(PPRINTFINSTANCE); static char *mklong(PPRINTFINSTANCE, const char *, int, char[64]); static void check_conversion(PPRINTFINSTANCE, const char *, const char *); static int usage(PKMKBUILTINCTX, int); static int flush_buffer(PPRINTFINSTANCE); static void b_count(PPRINTFINSTANCE, int); static void b_output(PPRINTFINSTANCE, int); static int wrap_putchar(PPRINTFINSTANCE, int ch); static int wrap_printf(PPRINTFINSTANCE, const char *, ...); int kmk_builtin_printf(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) { PRINTFINSTANCE This; struct getopt_state_r gos; int ch; getopt_initialize_r(&gos, argc, argv, "", long_options, envp, pCtx); while ((ch = getopt_long_r(&gos, NULL)) != -1) { switch (ch) { case 261: usage(pCtx, 0); return 0; case 262: return kbuild_version(argv[0]); case '?': default: return usage(pCtx, 1); } } argc -= gos.optind; argv += gos.optind; if (argc < 1) return usage(pCtx, 1); #ifndef KMK_BUILTIN_STANDALONE This.g_o = NULL; #endif return common_printf(&This, argv, pCtx); } #ifdef KMK_BUILTIN_STANDALONE int main(int argc, char **argv, char **envp) { KMKBUILTINCTX Ctx = { "kmk_printf", NULL }; setlocale(LC_ALL, ""); return kmk_builtin_printf(argc, argv, envp, &Ctx); } #else /* KMK_BUILTIN_STANDALONE */ /* entry point used by function.c $(printf ..,..). */ char *kmk_builtin_func_printf(char *o, char **argv, const char *funcname) { PRINTFINSTANCE This; int rc; int argc; for (argc = 0; argv[argc] != NULL; argc++) /* nothing */; if (argc == 0) fatal(NILF, strlen(funcname) + INTSTR_LENGTH, _("$(%s): no format string\n"), funcname); This.g_o = o; rc = common_printf(&This, argv, NULL); o = This.g_o; if (rc != 0) fatal(NILF, strlen(funcname) + INTSTR_LENGTH, _("$(%s): failure rc=%d\n"), funcname, rc); return o; } #endif /* KMK_BUILTIN_STANDALONE */ static int common_printf(PPRINTFINSTANCE pThis, char *argv[], PKMKBUILTINCTX pCtx) { int rc; /* Init all but g_o. */ pThis->pCtx = pCtx; pThis->b_length = 0; pThis->b_fmt = NULL; pThis->rval = 0; pThis->gargv = NULL; pThis->g_cchBuf = 0; pThis->a = NULL; pThis->t = NULL; pThis->conv_str = NULL; rc = common_printf_inner(pThis, argv); /* Cleanup allocations. */ if (pThis->a) { free(pThis->a); pThis->a = NULL; } if (pThis->t) { free(pThis->t); pThis->t = NULL; } if (pThis->conv_str) { free(pThis->conv_str); pThis->conv_str = NULL; } return rc; } static int common_printf_inner(PPRINTFINSTANCE pThis, char *argv[]) { char *fmt, *start; int fieldwidth, precision; char nextch; char *format; int ch; char longbuf[64]; format = *argv; pThis->gargv = ++argv; #define SKIP1 "#-+ 0" #define SKIP2 "*0123456789" do { /* * Basic algorithm is to scan the format string for conversion * specifications -- once one is found, find out if the field * width or precision is a '*'; if it is, gather up value. * Note, format strings are reused as necessary to use up the * provided arguments, arguments of zero/null string are * provided to use up the format string. */ /* find next format specification */ for (fmt = format; (ch = *fmt++) != '\0';) { if (ch == '\\') { char c_ch; fmt = conv_escape(pThis, fmt, &c_ch); wrap_putchar(pThis, c_ch); continue; } if (ch != '%' || (*fmt == '%' && ++fmt)) { (void)wrap_putchar(pThis, ch); continue; } /* Ok - we've found a format specification, Save its address for a later printf(). */ start = fmt - 1; /* skip to field width */ fmt += strspn(fmt, SKIP1); fieldwidth = *fmt == '*' ? getwidth(pThis) : -1; /* skip to possible '.', get following precision */ fmt += strspn(fmt, SKIP2); if (*fmt == '.') ++fmt; precision = *fmt == '*' ? getwidth(pThis) : -1; fmt += strspn(fmt, SKIP2); ch = *fmt; if (!ch) { flush_buffer(pThis); warnx(pThis->pCtx, "missing format character"); return (1); } /* null terminate format string to we can use it as an argument to printf. */ nextch = fmt[1]; fmt[1] = 0; switch (ch) { case 'B': { const char *p = conv_expand(pThis, getstr(pThis)); *fmt = 's'; PF(start, p); break; } case 'b': { /* There has to be a better way to do this, * but the string we generate might have * embedded nulls. */ char *cp = getstr(pThis); /* Free on entry in case shell longjumped out */ if (pThis->a != NULL) { free(pThis->a); pThis->a = NULL; } if (pThis->t != NULL) { free(pThis->t); pThis->t = NULL; } /* Count number of bytes we want to output */ pThis->b_length = 0; conv_escape_str(pThis, cp, b_count); pThis->t = malloc(pThis->b_length + 1); if (pThis->t == NULL) break; memset(pThis->t, 'x', pThis->b_length); pThis->t[pThis->b_length] = 0; /* Get printf to calculate the lengths */ *fmt = 's'; APF(&pThis->a, start, pThis->t); pThis->b_fmt = pThis->a; /* Output leading spaces and data bytes */ conv_escape_str(pThis, cp, b_output); /* Add any trailing spaces */ wrap_printf(pThis, "%s", pThis->b_fmt); break; } case 'c': { char p = getchr(pThis); PF(start, p); break; } case 's': { char *p = getstr(pThis); PF(start, p); break; } case 'd': case 'i': { intmax_t p = getintmax(pThis); char *f = mklong(pThis, start, ch, longbuf); PF(f, p); break; } case 'o': case 'u': case 'x': case 'X': { uintmax_t p = getuintmax(pThis); char *f = mklong(pThis, start, ch, longbuf); PF(f, p); break; } case 'e': case 'E': case 'f': case 'g': case 'G': { double p = getdouble(pThis); PF(start, p); break; } default: flush_buffer(pThis); warnx(pThis->pCtx, "%s: invalid directive", start); return 1; } *fmt++ = ch; *fmt = nextch; /* escape if a \c was encountered */ if (pThis->rval & 0x100) { flush_buffer(pThis); return pThis->rval & ~0x100; } } } while (pThis->gargv != argv && *pThis->gargv); flush_buffer(pThis); return pThis->rval; } /* helper functions for conv_escape_str */ static void /*ARGSUSED*/ b_count(PPRINTFINSTANCE pThis, int ch) { pThis->b_length++; (void)ch; } /* Output one converted character for every 'x' in the 'format' */ static void b_output(PPRINTFINSTANCE pThis, int ch) { for (;;) { switch (*pThis->b_fmt++) { case 0: pThis->b_fmt--; return; case ' ': wrap_putchar(pThis, ' '); break; default: wrap_putchar(pThis, ch); return; } } } static int wrap_putchar(PPRINTFINSTANCE pThis, int ch) { #ifndef KMK_BUILTIN_STANDALONE if (pThis->g_o) { char sz[2]; sz[0] = ch; sz[1] = '\0'; pThis->g_o = variable_buffer_output(pThis->g_o, sz, 1); } else #endif /* Buffered output. */ if (pThis->g_cchBuf + 1 < sizeof(pThis->g_achBuf)) { pThis->g_achBuf[pThis->g_cchBuf++] = ch; } else { int rc = flush_buffer(pThis); pThis->g_achBuf[pThis->g_cchBuf++] = ch; if (rc) return -1; } return 0; } static int wrap_printf(PPRINTFINSTANCE pThis, const char * fmt, ...) { ssize_t cchRet; va_list va; char *pszTmp; va_start(va, fmt); cchRet = vasprintf(&pszTmp, fmt, va); va_end(va); if (cchRet >= 0) { #ifndef KMK_BUILTIN_STANDALONE if (pThis->g_o) { pThis->g_o = variable_buffer_output(pThis->g_o, pszTmp, cchRet); } else #endif { if (cchRet + pThis->g_cchBuf <= sizeof(pThis->g_achBuf)) { /* We've got space in the buffer. */ memcpy(&pThis->g_achBuf[pThis->g_cchBuf], pszTmp, cchRet); pThis->g_cchBuf += cchRet; } else { /* Try write out complete lines. */ const char *pszLeft = pszTmp; ssize_t cchLeft = cchRet; while (cchLeft > 0) { const char *pchNewLine = strchr(pszLeft, '\n'); ssize_t cchLine = pchNewLine ? pchNewLine - pszLeft + 1 : cchLeft; if (pThis->g_cchBuf + cchLine <= sizeof(pThis->g_achBuf)) { memcpy(&pThis->g_achBuf[pThis->g_cchBuf], pszLeft, cchLine); pThis->g_cchBuf += cchLine; } else { if (flush_buffer(pThis) < 0) { return -1; } #ifndef KMK_BUILTIN_STANDALONE if (output_write_text(pThis->pCtx->pOut, 0,pszLeft, cchLine) < 1) #else if (fwrite(pszLeft, cchLine, 1, stdout) < 1) #endif return -1; } pszLeft += cchLine; cchLeft -= cchLine; } } } free(pszTmp); } return (int)cchRet; } /** * Flushes the g_abBuf/g_cchBuf. */ static int flush_buffer(PPRINTFINSTANCE pThis) { ssize_t cchToWrite = pThis->g_cchBuf; if (cchToWrite > 0) { #ifndef KMK_BUILTIN_STANDALONE ssize_t cchWritten = output_write_text(pThis->pCtx->pOut, 0, pThis->g_achBuf, cchToWrite); #else ssize_t cchWritten = fwrite(pThis->g_achBuf, 1, cchToWrite, stdout); #endif pThis->g_cchBuf = 0; if (cchWritten >= cchToWrite) { /* likely */ } else { ssize_t off = cchWritten; if (cchWritten >= 0) { off = cchWritten; } else if (errno == EINTR) { cchWritten = 0; } else { return -1; } while (off < cchToWrite) { #ifndef KMK_BUILTIN_STANDALONE cchWritten = output_write_text(pThis->pCtx->pOut, 0, &pThis->g_achBuf[off], cchToWrite - off); #else cchWritten = fwrite(&pThis->g_achBuf[off], 1, cchToWrite - off, stdout); #endif if (cchWritten > 0) { off += cchWritten; } else if (errno == EINTR) { /* nothing */ } else { return -1; } } } } return 0; } /* * Print SysV echo(1) style escape string * Halts processing string if a \c escape is encountered. */ static void conv_escape_str(PPRINTFINSTANCE pThis, char *str, void (*do_putchar)(PPRINTFINSTANCE, int)) { int value; int ch; char c; while ((ch = *str++) != '\0') { if (ch != '\\') { do_putchar(pThis, ch); continue; } ch = *str++; if (ch == 'c') { /* \c as in SYSV echo - abort all processing.... */ pThis->rval |= 0x100; break; } /* * %b string octal constants are not like those in C. * They start with a \0, and are followed by 0, 1, 2, * or 3 octal digits. */ if (ch == '0') { int octnum = 0, i; for (i = 0; i < 3; i++) { if (!isdigit((unsigned char)*str) || *str > '7') break; octnum = (octnum << 3) | (*str++ - '0'); } do_putchar(pThis, octnum); continue; } /* \[M][^|-]C as defined by vis(3) */ if (ch == 'M' && *str == '-') { do_putchar(pThis, 0200 | str[1]); str += 2; continue; } if (ch == 'M' && *str == '^') { str++; value = 0200; ch = '^'; } else value = 0; if (ch == '^') { ch = *str++; if (ch == '?') value |= 0177; else value |= ch & 037; do_putchar(pThis, value); continue; } /* Finally test for sequences valid in the format string */ str = conv_escape(pThis, str - 1, &c); do_putchar(pThis, c); } } /* * Print "standard" escape characters */ static char * conv_escape(PPRINTFINSTANCE pThis, char *str, char *conv_ch) { int value; int ch; char num_buf[4], *num_end; ch = *str++; switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': num_buf[0] = ch; ch = str[0]; num_buf[1] = ch; num_buf[2] = ch ? str[1] : 0; num_buf[3] = 0; value = strtoul(num_buf, &num_end, 8); str += num_end - (num_buf + 1); break; case 'x': /* Hexadecimal character constants are not required to be supported (by SuS v1) because there is no consistent way to detect the end of the constant. Supporting 2 byte constants is a compromise. */ ch = str[0]; num_buf[0] = ch; num_buf[1] = ch ? str[1] : 0; num_buf[2] = 0; value = strtoul(num_buf, &num_end, 16); str += num_end - num_buf; break; case '\\': value = '\\'; break; /* backslash */ case '\'': value = '\''; break; /* single quote */ case '"': value = '"'; break; /* double quote */ case 'a': value = '\a'; break; /* alert */ case 'b': value = '\b'; break; /* backspace */ case 'e': value = ESCAPE; break; /* escape */ case 'f': value = '\f'; break; /* form-feed */ case 'n': value = '\n'; break; /* newline */ case 'r': value = '\r'; break; /* carriage-return */ case 't': value = '\t'; break; /* tab */ case 'v': value = '\v'; break; /* vertical-tab */ default: warnx(pThis->pCtx, "unknown escape sequence `\\%c'", ch); pThis->rval = 1; value = ch; break; } *conv_ch = value; return str; } /* expand a string so that everything is printable */ static const char * conv_expand(PPRINTFINSTANCE pThis, const char *str) { static const char no_memory[] = ""; char *cp; int ch; if (pThis->conv_str) free(pThis->conv_str); /* get a buffer that is definitely large enough.... */ pThis->conv_str = cp = malloc(4 * strlen(str) + 1); if (!cp) return no_memory; while ((ch = *(const unsigned char *)str++) != '\0') { switch (ch) { /* Use C escapes for expected control characters */ case '\\': ch = '\\'; break; /* backslash */ case '\'': ch = '\''; break; /* single quote */ case '"': ch = '"'; break; /* double quote */ case '\a': ch = 'a'; break; /* alert */ case '\b': ch = 'b'; break; /* backspace */ case ESCAPE: ch = 'e'; break; /* escape */ case '\f': ch = 'f'; break; /* form-feed */ case '\n': ch = 'n'; break; /* newline */ case '\r': ch = 'r'; break; /* carriage-return */ case '\t': ch = 't'; break; /* tab */ case '\v': ch = 'v'; break; /* vertical-tab */ default: /* Copy anything printable */ if (isprint(ch)) { *cp++ = ch; continue; } /* Use vis(3) encodings for the rest */ *cp++ = '\\'; if (ch & 0200) { *cp++ = 'M'; ch &= ~0200; } if (ch == 0177) { *cp++ = '^'; *cp++ = '?'; continue; } if (ch < 040) { *cp++ = '^'; *cp++ = ch | 0100; continue; } *cp++ = '-'; *cp++ = ch; continue; } *cp++ = '\\'; *cp++ = ch; } *cp = 0; return pThis->conv_str; } static char * mklong(PPRINTFINSTANCE pThis, const char *str, int ch, char copy[64]) { size_t len; len = strlen(str) - 1; if (len > 64 - 5) { warnx(pThis->pCtx, "format %s too complex\n", str); len = 4; } (void)memmove(copy, str, len); #ifndef _MSC_VER copy[len++] = 'j'; #else copy[len++] = 'I'; copy[len++] = '6'; copy[len++] = '4'; #endif copy[len++] = ch; copy[len] = '\0'; return copy; } static int getchr(PPRINTFINSTANCE pThis) { if (!*pThis->gargv) return 0; return (int)**pThis->gargv++; } static char * getstr(PPRINTFINSTANCE pThis) { static char empty[] = ""; if (!*pThis->gargv) return empty; return *pThis->gargv++; } static int getwidth(PPRINTFINSTANCE pThis) { long val; char *s, *ep; s = *pThis->gargv; if (!s) return (0); pThis->gargv++; errno = 0; val = strtoul(s, &ep, 0); check_conversion(pThis, s, ep); /* Arbitrarily 'restrict' field widths to 1Mbyte */ if (val < 0 || val > 1 << 20) { warnx(pThis->pCtx, "%s: invalid field width", s); return 0; } return val; } static intmax_t getintmax(PPRINTFINSTANCE pThis) { intmax_t val; char *cp, *ep; cp = *pThis->gargv; if (cp == NULL) return 0; pThis->gargv++; if (*cp == '\"' || *cp == '\'') return *(cp+1); errno = 0; val = strtoimax(cp, &ep, 0); check_conversion(pThis, cp, ep); return val; } static uintmax_t getuintmax(PPRINTFINSTANCE pThis) { uintmax_t val; char *cp, *ep; cp = *pThis->gargv; if (cp == NULL) return 0; pThis->gargv++; if (*cp == '\"' || *cp == '\'') return *(cp + 1); /* strtoumax won't error -ve values */ while (isspace(*(unsigned char *)cp)) cp++; if (*cp == '-') { warnx(pThis->pCtx, "%s: expected positive numeric value", cp); pThis->rval = 1; return 0; } errno = 0; val = strtoumax(cp, &ep, 0); check_conversion(pThis, cp, ep); return val; } static double getdouble(PPRINTFINSTANCE pThis) { double val; char *ep; char *s; s = *pThis->gargv; if (!s) return (0.0); pThis->gargv++; if (*s == '\"' || *s == '\'') return (double) s[1]; errno = 0; val = strtod(s, &ep); check_conversion(pThis, s, ep); return val; } static void check_conversion(PPRINTFINSTANCE pThis, const char *s, const char *ep) { if (*ep) { if (ep == s) warnx(pThis->pCtx, "%s: expected numeric value", s); else warnx(pThis->pCtx, "%s: not completely converted", s); pThis->rval = 1; } else if (errno == ERANGE) { warnx(pThis->pCtx, "%s: %s", s, strerror(ERANGE)); pThis->rval = 1; } } static int usage(PKMKBUILTINCTX pCtx, int fIsErr) { kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s format [arg ...]\n" " or: %s --help\n" " or: %s --version\n", pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); return 1; } kbuild-3686/src/kmk/kmkbuiltin/haikufakes.c0000664000175000017500000000276415053010075020722 0ustar locutuslocutus/* $Id: haikufakes.c 2546 2011-10-01 19:49:54Z bird $ */ /** @file * Fake Unix/BSD stuff for Haiku. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include #include "haikufakes.h" int haiku_lchmod(const char *pszPath, mode_t mode) { /* * Weed out symbolic links. */ struct stat s; if ( !lstat(pszPath, &s) && S_ISLNK(s.st_mode)) { errno = -ENOSYS; return -1; } return chmod(pszPath, mode); } kbuild-3686/src/kmk/kmkbuiltin/ftsfake.h0000664000175000017500000001306015053010074020225 0ustar locutuslocutus/* $NetBSD: fts.h,v 1.12 2005/02/03 04:39:32 perry Exp $ */ /* * Copyright (c) 1989, 1993 * 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. 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. * * @(#)fts.h 8.3 (Berkeley) 8/14/94 */ #ifndef _FTS_H_ #define _FTS_H_ #ifdef _MSC_VER # include "kmkbuiltin/mscfakes.h" #endif typedef struct { struct _ftsent *fts_cur; /* current node */ struct _ftsent *fts_child; /* linked list of children */ struct _ftsent **fts_array; /* sort array */ dev_t fts_dev; /* starting device # */ char *fts_path; /* path for this descent */ #if defined(_MSC_VER) || defined(__OS2__) char *fts_rdir; /* path of root */ #else int fts_rfd; /* fd for root */ #endif u_int fts_pathlen; /* sizeof(path) */ u_int fts_nitems; /* elements in the sort array */ int (*fts_compar) /* compare function */ (const struct _ftsent **, const struct _ftsent **); #define FTS_COMFOLLOW 0x001 /* follow command line symlinks */ #define FTS_LOGICAL 0x002 /* logical walk */ #define FTS_NOCHDIR 0x004 /* don't change directories */ #define FTS_NOSTAT 0x008 /* don't get stat info */ #define FTS_PHYSICAL 0x010 /* physical walk */ #define FTS_SEEDOT 0x020 /* return dot and dot-dot */ #define FTS_XDEV 0x040 /* don't cross devices */ #ifndef _MSC_VER #define FTS_WHITEOUT 0x080 /* return whiteout information */ #endif #define FTS_OPTIONMASK 0x0ff /* valid user option mask */ #define FTS_NAMEONLY 0x100 /* (private) child names only */ #define FTS_STOP 0x200 /* (private) unrecoverable error */ int fts_options; /* fts_open options, global flags */ } FTS; typedef struct _ftsent { struct _ftsent *fts_cycle; /* cycle node */ struct _ftsent *fts_parent; /* parent directory */ struct _ftsent *fts_link; /* next file in directory */ long fts_number; /* local numeric value */ void *fts_pointer; /* local address value */ char *fts_accpath; /* access path */ char *fts_path; /* root path */ int fts_errno; /* errno for this node */ #ifndef _MSC_VER int fts_symfd; /* fd for symlink */ #endif u_short fts_pathlen; /* strlen(fts_path) */ u_short fts_namelen; /* strlen(fts_name) */ ino_t fts_ino; /* inode */ dev_t fts_dev; /* device */ #ifdef __LIBC12_SOURCE__ u_int16_t fts_nlink; /* link count */ #else #ifndef _MSC_VER nlink_t fts_nlink; /* link count */ #else int fts_nlink; /* link count */ #endif #endif #define FTS_ROOTPARENTLEVEL -1 #define FTS_ROOTLEVEL 0 short fts_level; /* depth (-1 to N) */ #define FTS_D 1 /* preorder directory */ #define FTS_DC 2 /* directory that causes cycles */ #define FTS_DEFAULT 3 /* none of the above */ #define FTS_DNR 4 /* unreadable directory */ #define FTS_DOT 5 /* dot or dot-dot */ #define FTS_DP 6 /* postorder directory */ #define FTS_ERR 7 /* error; errno is set */ #define FTS_F 8 /* regular file */ #define FTS_INIT 9 /* initialized only */ #define FTS_NS 10 /* stat(2) failed */ #define FTS_NSOK 11 /* no stat(2) requested */ #define FTS_SL 12 /* symbolic link */ #define FTS_SLNONE 13 /* symbolic link without target */ #ifndef _MSC_VER #define FTS_W 14 /* whiteout object */ #endif u_short fts_info; /* user flags for FTSENT structure */ #define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ #define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ #ifndef _MSC_VER #define FTS_ISW 0x04 /* this is a whiteout object */ #endif u_short fts_flags; /* private flags for FTSENT structure */ #define FTS_AGAIN 1 /* read node again */ #define FTS_FOLLOW 2 /* follow symbolic link */ #define FTS_NOINSTR 3 /* no instructions */ #define FTS_SKIP 4 /* discard node */ u_short fts_instr; /* fts_set() instructions */ #ifdef __LIBC12_SOURCE__ struct stat12 *fts_statp; /* stat(2) information */ #else struct stat *fts_statp; /* stat(2) information */ #endif char fts_name[1]; /* file name */ } FTSENT; #ifdef __cplusplus extern "C" { #endif FTSENT *fts_children(FTS *, int); int fts_close(FTS *); FTS *fts_open(char * const *, int, int (*)(const FTSENT **, const FTSENT **)); FTSENT *fts_read(FTS *); int fts_set(FTS *, FTSENT *, int); #ifdef __cplusplus } #endif #endif /* !_FTS_H_ */ kbuild-3686/src/kmk/kmkbuiltin/cp_extern.h0000664000175000017500000000476715053010074020607 0ustar locutuslocutus/*- * Copyright (c) 1991, 1993, 1994 * 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. * 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. * * @(#)extern.h 8.2 (Berkeley) 4/1/94 * $FreeBSD: src/bin/cp/extern.h,v 1.19 2004/04/06 20:06:44 markm Exp $ */ #include "kmkbuiltin.h" /* for PATH_MAX on GNU/hurd */ typedef struct { char *p_end; /* pointer to NULL at end of path */ char *target_end; /* pointer to end of target base */ char p_path[PATH_MAX]; /* pointer to the start of a path */ } PATH_T; typedef struct CPUTILSINSTANCE { PKMKBUILTINCTX pCtx; /*extern*/ PATH_T to; /*extern*/ int fflag, iflag, nflag, pflag, vflag; } CPUTILSINSTANCE; #if defined(SIGINFO) && defined(KMK_BUILTIN_STANDALONE) extern volatile sig_atomic_t g_cp_info; #endif int copy_fifo(CPUTILSINSTANCE *pThis, struct stat *, int); int copy_file(CPUTILSINSTANCE *pThis, const FTSENT *, int, int, int *); int copy_link(CPUTILSINSTANCE *pThis, const FTSENT *, int); int copy_special(CPUTILSINSTANCE *pThis, struct stat *, int); int copy_file_attribs(CPUTILSINSTANCE *pThis, struct stat *, int); kbuild-3686/src/kmk/kmkbuiltin/err.h0000664000175000017500000000237315053010074017377 0ustar locutuslocutus/* $Id: err.h 3192 2018-03-26 20:25:56Z bird $ */ /** @file * Override err.h stuff so we get the program names right. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ #ifndef ___err_h #define ___err_h #include "../kmkbuiltin.h" int err(PKMKBUILTINCTX pCtx, int eval, const char *fmt, ...); int errx(PKMKBUILTINCTX pCtx, int eval, const char *fmt, ...); void warn(PKMKBUILTINCTX pCtx, const char *fmt, ...); void warnx(PKMKBUILTINCTX pCtx, const char *fmt, ...); void kmk_builtin_ctx_printf(PKMKBUILTINCTX pCtx, int fIsErr, const char *pszFormat, ...); #endif kbuild-3686/src/kmk/kmkbuiltin/solfakes.h0000664000175000017500000000263615053010075020421 0ustar locutuslocutus/* $Id: solfakes.h 3213 2018-03-30 21:03:28Z bird $ */ /** @file * Unix fakes for Solaris. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ #ifndef ___solfakes_h #define ___solfakes_h #ifdef __sun__ #include #include #ifndef FAKES_NO_GETOPT_H # include "getopt.h" #endif #define _PATH_DEVNULL "/dev/null" #define ALLPERMS 0000777 #define lutimes(path, tvs) utimes(path, tvs) #define lchmod sol_lchmod #define MAX(a,b) ((a) >= (b) ? (a) : (b)) #ifndef USHRT_MAX # define USHRT_MAX 65535 #endif int vasprintf(char **strp, const char *fmt, va_list va); int asprintf(char **strp, const char *fmt, ...); int sol_lchmod(const char *pszPath, mode_t mode); #endif /* __sun__ */ #endif /* !___solfakes_h */ kbuild-3686/src/kmk/kmkbuiltin/kbuild_protection.c0000664000175000017500000002614315053010074022323 0ustar locutuslocutus/* $Id: kbuild_protection.c 3192 2018-03-26 20:25:56Z bird $ */ /** @file * Simple File Protection. */ /* * Copyright (c) 2008-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild 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 3 of the License, or * (at your option) any later version. * * kBuild 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 kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include #if defined(_MSC_VER) || defined(__OS2__) # include # include #else # include #endif #include "kbuild_protection.h" #include "err.h" /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ #define KBUILD_PROTECTION_MAGIC 0x00111100 #if defined(__EMX__) || defined(_MSC_VER) # define IS_SLASH(ch) ( (ch) == '/' || (ch) == '\\' ) # define DEFAULT_PROTECTION_DEPTH 1 #else # define IS_SLASH(ch) ( (ch) == '/' ) # define DEFAULT_PROTECTION_DEPTH 2 #endif /** * Counts the components in the specified sub path. * This is a helper for count_path_components. * * etc = 1 * etc/ = 1 * etc/x11 = 2 * and so and and so forth. */ static int countSubPathComponents(const char *pszPath, int cDepth) { for (;;) { const char *pszEnd; size_t cch; /* skip slashes. */ while (IS_SLASH(*pszPath)) pszPath++; if (!*pszPath) break; /* find end of component. */ pszEnd = pszPath; while (!IS_SLASH(*pszEnd) && *pszEnd) pszEnd++; /* count it, checking for '..' and '.'. */ cch = pszEnd - pszPath; if (cch == 2 && pszPath[0] == '.' && pszPath[1] == '.') { if (cDepth > 0) cDepth--; } else if (cch != 1 || pszPath[0] != '.') cDepth++; /* advance */ if (!*pszEnd) break; pszPath = pszEnd + 1; } return cDepth; } /** * Parses the specified path counting the number of components * relative to root. * * We don't check symbolic links and such, just some simple and cheap * path parsing. * * @param pszPath The path to process. * * @returns 0 or higher on success. * On failure an error is printed, eval is set and -1 is returned. */ static int countPathComponents(PCKBUILDPROTECTION pThis, const char *pszPath) { int cComponents = 0; /* * Deal with root, UNC, drive letter. */ #if defined(_MSC_VER) || defined(__OS2__) if (IS_SLASH(pszPath[0]) && IS_SLASH(pszPath[1]) && !IS_SLASH(pszPath[2])) { /* skip the root - UNC */ pszPath += 3; while (!IS_SLASH(*pszPath) && *pszPath) /* server name */ pszPath++; while (IS_SLASH(*pszPath)) pszPath++; while (!IS_SLASH(*pszPath) && *pszPath) /* share name */ pszPath++; while (IS_SLASH(*pszPath)) pszPath++; } else { unsigned uDriveLetter = (unsigned)toupper(pszPath[0]) - (unsigned)'A'; if (uDriveLetter <= (unsigned)('Z' - 'A') && pszPath[1] == ':') uDriveLetter++; /* A == 1 */ else uDriveLetter = 0; /* 0 == default */ if (!IS_SLASH(pszPath[uDriveLetter ? 2 : 0])) { /* * Relative path, must count cwd depth first. */ #ifdef __OS2__ /** @todo remove when ticket 194 has been fixed */ char *pszCwd = _getdcwd(uDriveLetter, NULL, PATH_MAX); #else char *pszCwd = _getdcwd(uDriveLetter, NULL, 0); #endif char *pszTmp = pszCwd; if (!pszTmp) { err(pThis->pCtx, 1, "_getdcwd"); return -1; } if (IS_SLASH(pszTmp[0]) && IS_SLASH(pszTmp[1])) { /* skip the root - UNC */ pszTmp += 2; while (!IS_SLASH(*pszTmp) && *pszTmp) /* server name */ pszTmp++; while (IS_SLASH(*pszTmp)) pszTmp++; while (!IS_SLASH(*pszTmp) && *pszTmp) /* share name */ pszTmp++; } else { /* skip the drive letter and while we're at it, the root slash too. */ pszTmp += 1 + (pszTmp[1] == ':'); } cComponents = countSubPathComponents(pszTmp, 0); free(pszCwd); } else { /* skip the drive letter and while we're at it, the root slash too. */ pszPath += uDriveLetter ? 3 : 1; } } #else /* !WIN && !OS2 */ if (!IS_SLASH(pszPath[0])) { /* * Relative path, must count cwd depth first. */ char szCwd[4096]; if (!getcwd(szCwd, sizeof(szCwd))) { err(pThis->pCtx, 1, "getcwd"); return -1; } cComponents = countSubPathComponents(szCwd, 0); } #endif /* !WIN && !OS2 */ /* * We're now past any UNC or drive letter crap, possibly positioned * at the root slash or at the start of a path component at the * given depth. Count the remainder. */ return countSubPathComponents(pszPath, cComponents); } /** * Initializes the instance data. * * @param pThis Pointer to the instance data. */ void kBuildProtectionInit(PKBUILDPROTECTION pThis, PKMKBUILTINCTX pCtx) { pThis->uMagic = KBUILD_PROTECTION_MAGIC; pThis->pCtx = pCtx; pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] = 0; pThis->afTypes[KBUILDPROTECTIONTYPE_RECURSIVE] = 1; pThis->cProtectionDepth = DEFAULT_PROTECTION_DEPTH; } /** * Destroys the instance data. * * @param pThis Pointer to the instance data. */ void kBuildProtectionTerm(PKBUILDPROTECTION pThis) { pThis->uMagic = 0; } void kBuildProtectionEnable(PKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType) { assert(pThis->uMagic == KBUILD_PROTECTION_MAGIC); assert(enmType < KBUILDPROTECTIONTYPE_MAX && enmType >= KBUILDPROTECTIONTYPE_FIRST); pThis->afTypes[enmType] |= 1; } void kBuildProtectionDisable(PKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType) { assert(pThis->uMagic == KBUILD_PROTECTION_MAGIC); assert(enmType < KBUILDPROTECTIONTYPE_MAX && enmType >= KBUILDPROTECTIONTYPE_FIRST); pThis->afTypes[enmType] &= ~1U; } /** * Sets the protection depth according to the option argument. * * @param pszValue The value. * * @returns 0 on success, -1 and errx on failure. */ int kBuildProtectionSetDepth(PKBUILDPROTECTION pThis, const char *pszValue) { /* skip leading blanks, they don't count either way. */ while (isspace(*pszValue)) pszValue++; /* number or path? */ if (!isdigit(*pszValue) || strpbrk(pszValue, ":/\\")) pThis->cProtectionDepth = countPathComponents(pThis, pszValue); else { char *pszMore = 0; pThis->cProtectionDepth = strtol(pszValue, &pszMore, 0); if (pThis->cProtectionDepth != 0 && pszMore) { /* trailing space is harmless. */ while (isspace(*pszMore)) pszMore++; } if (!pThis->cProtectionDepth || pszValue == pszMore || *pszMore) return errx(pThis->pCtx, 1, "bogus protection depth: %s", pszValue); } if (pThis->cProtectionDepth < 1) return errx(pThis->pCtx, 1, "bogus protection depth: %s", pszValue); return 0; } /** * Scans the environment for option overrides. * * @param pThis Pointer to the instance data. * @param papszEnv The environment array. * @param pszPrefix The variable prefix. * * @returns 0 on success, -1 and err*() on failure. */ int kBuildProtectionScanEnv(PKBUILDPROTECTION pThis, char **papszEnv, const char *pszPrefix) { unsigned i; const size_t cchPrefix = strlen(pszPrefix); for (i = 0; papszEnv[i]; i++) { const char *pszVar = papszEnv[i]; if (!strncmp(pszVar, pszPrefix, cchPrefix)) { pszVar += cchPrefix; if (!strncmp(pszVar, "PROTECTION_DEPTH=", sizeof("PROTECTION_DEPTH=") - 1)) { const char *pszVal = pszVar + sizeof("PROTECTION_DEPTH=") - 1; if (kBuildProtectionSetDepth(pThis, pszVal)) return -1; } else if (!strncmp(pszVar, "DISABLE_PROTECTION=", sizeof("DISABLE_PROTECTION=") - 1)) pThis->afTypes[KBUILDPROTECTIONTYPE_RECURSIVE] &= ~1U; else if (!strncmp(pszVar, "ENABLE_PROTECTION=", sizeof("ENABLE_PROTECTION=") - 1)) pThis->afTypes[KBUILDPROTECTIONTYPE_RECURSIVE] |= 3; else if (!strncmp(pszVar, "DISABLE_FULL_PROTECTION=", sizeof("DISABLE_FULL_PROTECTION=") - 1)) pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] &= ~1U; else if (!strncmp(pszVar, "ENABLE_FULL_PROTECTION=", sizeof("ENABLE_FULL_PROTECTION=") - 1)) pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] |= 3; } } return 0; } /** * Protect the upper layers of the file system against accidental * or malicious deletetion attempt from within a makefile. * * @param pszPath The path to check. * @param required_depth The minimum number of components in the * path counting from the root. * * @returns 0 on success. * On failure an error is printed and -1 is returned. */ int kBuildProtectionEnforce(PCKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType, const char *pszPath) { assert(pThis->uMagic == KBUILD_PROTECTION_MAGIC); assert(enmType < KBUILDPROTECTIONTYPE_MAX && enmType >= KBUILDPROTECTIONTYPE_FIRST); if ( (pThis->afTypes[enmType] & 3) || (pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] & 3)) { /* * Count the path and compare it with the required depth. */ int cComponents = countPathComponents(pThis, pszPath); if (cComponents < 0) return -1; if ((unsigned int)cComponents <= pThis->cProtectionDepth) { errx(pThis->pCtx, 1, "%s: protected", pszPath); return -1; } } return 0; } /** * Retrieve the default path protection depth. * * @returns the default value. */ int kBuildProtectionDefaultDepth(void) { return DEFAULT_PROTECTION_DEPTH; } kbuild-3686/src/kmk/config.h.win0000664000175000017500000004004115053010075016472 0ustar locutuslocutus/* config.h.W32 -- hand-massaged config.h file for Windows builds -*-C-*- Copyright (C) 1996-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . */ #ifndef ___config_h_win #define ___config_h_win /* Suppress some Visual C++ warnings. Maybe after the code cleanup for ISO C we can remove some/all of these. */ #if _MSC_VER > 1000 # pragma warning(disable:4100) /* unreferenced formal parameter */ # pragma warning(disable:4102) /* unreferenced label */ # pragma warning(disable:4127) /* conditional expression is constant */ # pragma warning(disable:4131) /* uses old-style declarator */ # pragma warning(disable:4702) /* unreachable code */ # ifndef _CRT_SECURE_NO_WARNINGS # define _CRT_SECURE_NO_WARNINGS /* function or variable may be unsafe */ # endif # ifndef _CRT_NONSTDC_NO_WARNINGS # define _CRT_NONSTDC_NO_WARNINGS /* functions w/o a leading underscore */ # endif #endif /* Define to 1 if the 'closedir' function returns void instead of 'int'. */ /* #undef CLOSEDIR_VOID */ /* Define to one of '_getb67', 'GETB67', 'getb67' for Cray-2 and Cray-YMP systems. This function is required for 'alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using 'alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if using 'getloadavg.c'. */ #define C_GETLOADAVG 1 /* Define to 1 for DGUX with . */ /* #undef DGUX */ /* Define to 1 if translation of program messages to the user's native language is requested. */ /* #undef ENABLE_NLS */ /* Use high resolution file timestamps if nonzero. */ #define FILE_TIMESTAMP_HI_RES 0 /* Define to 1 if the 'getloadavg' function needs to be run setuid or setgid. */ /* #undef GETLOADAVG_PRIVILEGED */ /* Define to 1 if you have 'alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ /* #undef HAVE_ALLOCA_H */ /* Define to 1 if you have the 'atexit' function. */ #define HAVE_ATEXIT 1 /* Define if your compiler conforms to the ANSI C standard. */ #define HAVE_ANSI_COMPILER 1 /* Use case insensitive file names */ /* #undef HAVE_CASE_INSENSITIVE_FS */ /* Define to 1 if you have the clock_gettime function. */ /* #undef HAVE_CLOCK_GETTIME */ /* Embed GNU Guile support. Windows build sets this on the compilation command line. */ /* #undef HAVE_GUILE */ /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* #undef HAVE_DCGETTEXT */ /* Define to 1 if you have the declaration of 'bsd_signal', and to 0 if you don't. */ #define HAVE_DECL_BSD_SIGNAL 0 /* Define to 1 if you have the declaration of 'sys_siglist', and to 0 if you don't. */ #define HAVE_DECL_SYS_SIGLIST 0 /* Define to 1 if you have the declaration of '_sys_siglist', and to 0 if you don't. */ #define HAVE_DECL__SYS_SIGLIST 0 /* Define to 1 if you have the declaration of '__sys_siglist', and to 0 if you don't. */ #define HAVE_DECL___SYS_SIGLIST 0 /* Define to 1 if you have the header file, and it defines 'DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you have the header file, and it defines getcwd() and chdir(). */ #if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(__INTERIX) # define HAVE_DIRECT_H 1 #endif /* Use platform specific coding */ #define HAVE_DOS_PATHS 1 /* Define to 1 if you have the 'dup2' function. */ #define HAVE_DUP2 1 /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define to 1 if you have the 'fdopen' function. */ #ifdef __MINGW32__ #define HAVE_FDOPEN 1 #endif /* Define to 1 if you have the 'fileno' function. */ #define HAVE_FILENO 1 /* Define to 1 if you have the 'getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the 'getgroups' function. */ /* #undef HAVE_GETGROUPS */ /* Define to 1 if you have the 'gethostbyname' function. */ /* #undef HAVE_GETHOSTBYNAME */ /* Define to 1 if you have the 'gethostname' function. */ /* #undef HAVE_GETHOSTNAME */ /* Define to 1 if you have the 'getloadavg' function. */ /* #undef HAVE_GETLOADAVG */ /* Define to 1 if you have the 'getrlimit' function. */ /* #undef HAVE_GETRLIMIT */ /* Define if the GNU gettext() function is already present or preinstalled. */ /* #undef HAVE_GETTEXT */ /* Define to 1 if you have a standard gettimeofday function */ #ifdef __MINGW32__ #define HAVE_GETTIMEOFDAY 1 #endif /* Define if you have the iconv() function. */ /* #undef HAVE_ICONV */ /* Define to 1 if you have the header file. */ #ifdef __MINGW32__ #define HAVE_INTTYPES_H 1 #endif /* Define to 1 if you have the 'dgc' library (-ldgc). */ /* #undef HAVE_LIBDGC */ /* Define to 1 if you have the 'kstat' library (-lkstat). */ /* #undef HAVE_LIBKSTAT */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* bird: differs */ /* Define to 1 if you have the 'lstat' function. */ /* #undef HAVE_LSTAT */ /* Define to 1 if you have the header file. */ /* #undef HAVE_MACH_MACH_H */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the 'mkstemp' function. */ /* #undef HAVE_MKSTEMP */ /* Define to 1 if you have the 'mktemp' function. */ #define HAVE_MKTEMP 1 /* Define to 1 if you have the header file, and it defines 'DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NLIST_H */ /* Define to 1 if you have the 'pipe' function. */ /* #undef HAVE_PIPE */ /* Define to 1 if you have the 'pstat_getdynamic' function. */ /* #undef HAVE_PSTAT_GETDYNAMIC */ /* Define to 1 if you have the 'readlink' function. */ /* #undef HAVE_READLINK */ /* Define to 1 if you have the 'realpath' function. */ /* #undef HAVE_REALPATH */ /* Define to 1 if defines the SA_RESTART constant. */ /* #undef HAVE_SA_RESTART */ /* Define to 1 if you have the 'setegid' function. */ /* #undef HAVE_SETEGID */ /* Define to 1 if you have the 'seteuid' function. */ /* #undef HAVE_SETEUID */ /* Define to 1 if you have the 'setlinebuf' function. */ /* #undef HAVE_SETLINEBUF */ /* Define to 1 if you have the 'setlocale' function. */ /*#define HAVE_SETLOCALE 1*/ /* Define to 1 if you have the 'setregid' function. */ /* #undef HAVE_SETREGID */ /* Define to 1 if you have the 'setreuid' function. */ /* #undef HAVE_SETREUID */ /* Define to 1 if you have the 'setrlimit' function. */ /* #undef HAVE_SETRLIMIT */ /* Define to 1 if you have the 'setvbuf' function. */ #define HAVE_SETVBUF 1 /* Define to 1 if you have the 'sigaction' function. */ /* #undef HAVE_SIGACTION */ /* Define to 1 if you have the 'sigsetmask' function. */ /* #undef HAVE_SIGSETMASK */ /* Define to 1 if you have the 'socket' function. */ /* #undef HAVE_SOCKET */ /* Define to 1 if you have the header file. */ #if defined(__MINGW32__) || _MSC_VER >= 1600 /* bird: added latter */ # define HAVE_STDINT_H 1 #endif /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the 'strcasecmp' function. */ #ifdef __MINGW32__ #define HAVE_STRCASECMP 1 #endif /* Define to 1 if you have the 'strcmpi' function. */ #define HAVE_STRCMPI 1 /* Define to 1 if you have the 'strcoll' function and it is properly defined. */ #define HAVE_STRCOLL 1 /* Define to 1 if you have the 'strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the 'strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the 'stricmp' function. */ #define HAVE_STRICMP 1 /* Define to 1 if you have the header file. */ /* #define HAVE_STRINGS_H 1 */ /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the 'strncasecmp' function. */ #ifdef __MINGW32__ #define HAVE_STRNCASECMP 1 #endif /* Define to 1 if you have the 'strncmpi' function. */ /* #undef HAVE_STRNCMPI */ /* Define to 1 if you have the 'strndup' function. */ /* #undef HAVE_STRNDUP */ /* Define to 1 if you have the 'strnicmp' function. */ /*#ifdef __MINGW32__ - bird */ #define HAVE_STRNICMP 1 /* #endif - bird */ /* Define to 1 if you have the 'strsignal' function. */ /* #undef HAVE_STRSIGNAL */ /* Define to 1 if you have the `isatty' function. */ #define HAVE_ISATTY 1 /* Define to 1 if you have the `ttyname' function. */ #define HAVE_TTYNAME 1 char *ttyname (int); /* Define to 1 if 'n_un.n_name' is a member of 'struct nlist'. */ /* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* 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, and it defines 'DIR'. */ /* #undef HAVE_SYS_NDIR_H */ /* Define to 1 if you have the header file. */ #ifdef __MINGW32__ #define HAVE_SYS_PARAM_H 1 #endif /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_RESOURCE_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIMEB_H 1 /* Define to 1 if you have the header file. */ #ifdef __MINGW32__ #define HAVE_SYS_TIME_H 1 #endif /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_WAIT_H */ /* Define to 1 if you have the \'union wait' type in . */ /* #undef HAVE_UNION_WAIT */ /* Define to 1 if you have the header file. */ #ifdef __MINGW32__ #define HAVE_UNISTD_H 1 #endif /* Define to 1 if you have the 'wait3' function. */ /* #undef HAVE_WAIT3 */ /* Define to 1 if you have the 'waitpid' function. */ /* #undef HAVE_WAITPID */ /* Build host information. (not used by kmk) */ #define MAKE_HOST "Windows32" /* Define to 1 to enable job server support in GNU make. */ #define MAKE_JOBSERVER 1 /* Define to 1 to enable 'load' support in GNU make. */ #define MAKE_LOAD 1 /* Define to 1 to enable symbolic link timestamp checking. */ /* #undef MAKE_SYMLINKS */ /* Define to 1 if your 'struct nlist' has an 'n_un' member. Obsolete, depend on 'HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* #undef NLIST_NAME_UNION */ /* Define to 1 if struct nlist.n_name is a pointer rather than an array. */ /* #undef NLIST_STRUCT */ /* Define to 1 if your C compiler doesn't accept -c and -o together. */ /* #undef NO_MINUS_C_MINUS_O */ /* Name of this package (needed by automake) */ #define PACKAGE "make" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bug-make@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "kmk" /* Define to the home page for this package. */ #define PACKAGE_URL "http://kbuild.org/" /* Define to the version of this package. */ #define PACKAGE_VERSION "4.2.1" /* Define to the character that separates directories in PATH. */ #define PATH_SEPARATOR_CHAR ';' /* Define as the return type of signal handlers ('int' or 'void'). */ #define RETSIGTYPE void /* Define to the name of the SCCS 'get' command. */ #define SCCS_GET "echo no sccs get" /* Define this if the SCCS 'get' command understands the '-G' option. */ /* #undef SCCS_GET_MINUS_G */ /* Define to 1 if the 'setvbuf' function takes the buffering type as its second argument and the buffer pointer as the third, as on System V before release 3. */ /* #undef SETVBUF_REVERSED */ /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if the 'S_IS*' macros in do not work properly. */ /* #undef STAT_MACROS_BROKEN */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define if struct stat contains a nanoseconds field */ #define ST_MTIM_NSEC st_mtim.tv_nsec /* bird */ #define ST_ATIM_NSEC st_atim.tv_nsec /* bird */ /* Define to 1 on System V Release 4. */ /* #undef SVR4 */ /* Define to 1 if you can safely include both and . */ #ifdef __MINGW32__ #define TIME_WITH_SYS_TIME 1 #endif /* Define to 1 for Encore UMAX. */ /* #undef UMAX */ /* Define to 1 for Encore UMAX 4.3 that has instead of . */ /* #undef UMAX4_3 */ /* Version number of package */ #define VERSION "4.2.1" /* Define if using the dmalloc debugging malloc package */ /* #undef WITH_DMALLOC */ /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* # undef _ALL_SOURCE */ #endif /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for 'stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Define to empty if 'const' does not conform to ANSI C. */ /* #undef const */ /* Define to 'int' if doesn't define. */ #define gid_t int /* Define to 'int' if does not define. */ /* Note (bird)! sub_proc.c needs this to be pointer sized. */ #define pid_t intptr_t /* Define to 'int' if doesn't define. */ #define uid_t int /* Define uintmax_t if not defined in or . */ #if !HAVE_STDINT_H && !HAVE_INTTYPES_H # if 0 # define uintmax_t unsigned long # else # define uintmax_t unsigned __int64 # endif #endif /* Define if you have that is POSIX.1 compatible. */ /* #undef HAVE_SYS_WAIT_H */ /* Define to the installation directory for locales. */ #define LOCALEDIR "" /* * Refer to README.W32 for info on the following settings */ /* * If you have a shell that does not grok 'sh -c quoted-command-line' * correctly, you need this setting. Please see below for specific * shell support. */ /*#define BATCH_MODE_ONLY_SHELL 1 */ /* * Define if you have the Cygnus "Cygwin" GNU Windows32 tool set. * Do NOT define BATCH_MODE_ONLY_SHELL if you define HAVE_CYGWIN_SHELL */ /*#define HAVE_CYGWIN_SHELL 1 */ /* * Define if you have the MKS tool set or shell. Do NOT define * BATCH_MODE_ONLY_SHELL if you define HAVE_MKS_SHELL */ /*#define HAVE_MKS_SHELL 1 */ /* * Enforce the mutual exclusivity restriction. */ #ifdef HAVE_MKS_SHELL #undef BATCH_MODE_ONLY_SHELL #endif #ifdef HAVE_CYGWIN_SHELL #undef BATCH_MODE_ONLY_SHELL #endif /* bird stat hacks. */ #include #include #include "nt/ntstat.h" /* bird dirent hack. */ #define _DIRENT_H /* see w32/dirent.h */ #include "nt/ntdir.h" #define _DIRENT_HAVE_D_NAMLEN 1 #define _DIRENT_HAVE_D_TYPE 1 /* bird: Not sure if this is necessary any more... */ #define BATCH_MODE_ONLY_SHELL #include "inlined_memchr.h" /* bird: Include mscfakes.h to make sure we have all it's tricks applied. */ #ifndef ___mscfakes_h # include "kmkbuiltin/mscfakes.h" #endif /* * Map posixfcn.c stuff to non-conflicting names. */ #include #include #define tmpfile posixfcn_tmpfile FILE *posixfcn_tmpfile(void); #define isatty posixfcn_isatty int posixfcn_isatty(int fd); #endif /* bird */ kbuild-3686/src/kmk/testcase-lazy-deps-vars.kmk0000664000175000017500000000451215053010075021461 0ustar locutuslocutus# $Id: testcase-lazy-deps-vars.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild - testcase for the lazy dependency lists. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild 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 3 of the License, or # (at your option) any later version. # # kBuild 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 kBuild. If not, see # # DEPTH = ../.. include $(PATH_KBUILD)/header.kmk ifneq ($(not 1),) $(error The 'not' function is missing) endif ifneq ($(eq 1,1),1) $(error The 'eq' function is missing) endif all: simple_1 simple_1: variable.c variable.h variable.c variable.c variable.h function.c | variable.h read.c @$(ECHO) "testcase-lazy-deps-vars.kmk::$@: TESTING..." @$(ECHO) "pluss: $+" $(if $(eq $+,variable.c variable.h variable.c variable.c variable.h function.c),,exit 1) $(if $(eq $(deps-all $@,1),variable.c),,exit 1) $(if $(eq $(deps-all $@,2),variable.h),,exit 2) $(if $(eq $(deps-all $@,3),variable.c),,exit 3) $(if $(eq $(deps-all $@,4),variable.c),,exit 4) $(if $(eq $(deps-all $@,5),variable.h),,exit 5) $(if $(eq $(deps-all $@,6),function.c),,exit 6) $(if $(eq $(deps-all $@,7),),,exit 7) @$(ECHO) "caret: $^" $(if $(eq $^,variable.c variable.h function.c),,exit 1) $(if $(eq $(deps $@,1),variable.c),,exit 1) $(if $(eq $(deps $@,2),variable.h),,exit 2) $(if $(eq $(deps $@,3),function.c),,exit 3) $(if $(eq $(deps $@,4),),,exit 4) @$(ECHO) "qmark: $?" $(if $(eq $?,variable.c variable.h function.c),,exit 1) $(if $(eq $(deps-newer $@,1),variable.c),,exit 1) $(if $(eq $(deps-newer $@,2),variable.h),,exit 2) $(if $(eq $(deps-newer $@,3),function.c),,exit 3) $(if $(eq $(deps-newer $@,4),),,exit 4) @$(ECHO) " bar: $|" $(if $(eq $|,read.c),,exit 1) $(if $(eq $(deps-oo $@,1),read.c),,exit 1) $(if $(eq $(deps-oo $@,2),),,exit 2) @$(ECHO) "testcase-lazy-deps-vars.kmk::simple_1: SUCCESS" kbuild-3686/src/kmk/alloca.c0000664000175000017500000003362715053010075015673 0ustar locutuslocutus/* alloca.c -- allocate automatically reclaimed memory (Mostly) portable public-domain implementation -- D A Gwyn This implementation of the PWB library alloca function, which is used to allocate space off the run-time stack so that it is automatically reclaimed upon procedure exit, was inspired by discussions with J. Q. Johnson of Cornell. J.Otto Tennant contributed the Cray support. There are some preprocessor constants that can be defined when compiling for your specific system, for improved efficiency; however, the defaults should be okay. The general concept of this implementation is to keep track of all alloca-allocated blocks, and reclaim any that are found to be deeper in the stack than the current invocation. This heuristic does not reclaim storage as soon as it becomes invalid, but it will do so eventually. As a special case, alloca(0) reclaims storage without allocating any. It is a good idea to use alloca(0) in your main control loop, etc. to force garbage collection. */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef emacs #include "blockinput.h" #endif /* If compiling with GCC 2, this file's not needed. */ #if !defined (__GNUC__) || __GNUC__ < 2 /* If someone has defined alloca as a macro, there must be some other way alloca is supposed to work. */ #ifndef alloca #ifdef emacs #ifdef static /* actually, only want this if static is defined as "" -- this is for usg, in which emacs must undefine static in order to make unexec workable */ #ifndef STACK_DIRECTION you lose -- must know STACK_DIRECTION at compile-time #endif /* STACK_DIRECTION undefined */ #endif /* static */ #endif /* emacs */ /* If your stack is a linked list of frames, you have to provide an "address metric" ADDRESS_FUNCTION macro. */ #if defined (CRAY) && defined (CRAY_STACKSEG_END) long i00afunc (); #define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) #else #define ADDRESS_FUNCTION(arg) &(arg) #endif #if __STDC__ typedef void *pointer; #else typedef char *pointer; #endif #ifndef NULL #define NULL 0 #endif /* Different portions of Emacs need to call different versions of malloc. The Emacs executable needs alloca to call xmalloc, because ordinary malloc isn't protected from input signals. On the other hand, the utilities in lib-src need alloca to call malloc; some of them are very simple, and don't have an xmalloc routine. Non-Emacs programs expect this to call use xmalloc. Callers below should use malloc. */ #ifndef emacs #define malloc xmalloc #endif extern pointer malloc (); /* Define STACK_DIRECTION if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ #ifndef STACK_DIRECTION #define STACK_DIRECTION 0 /* Direction unknown. */ #endif #if STACK_DIRECTION != 0 #define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ #else /* STACK_DIRECTION == 0; need run-time code. */ static int stack_dir; /* 1 or -1 once known. */ #define STACK_DIR stack_dir static void find_stack_direction (void) { static char *addr = NULL; /* Address of first 'dummy', once known. */ auto char dummy; /* To get stack address. */ if (addr == NULL) { /* Initial entry. */ addr = ADDRESS_FUNCTION (dummy); find_stack_direction (); /* Recurse once. */ } else { /* Second entry. */ if (ADDRESS_FUNCTION (dummy) > addr) stack_dir = 1; /* Stack grew upward. */ else stack_dir = -1; /* Stack grew downward. */ } } #endif /* STACK_DIRECTION == 0 */ /* An "alloca header" is used to: (a) chain together all alloca'ed blocks; (b) keep track of stack depth. It is very important that sizeof(header) agree with malloc alignment chunk size. The following default should work okay. */ #ifndef ALIGN_SIZE #define ALIGN_SIZE sizeof(double) #endif typedef union hdr { char align[ALIGN_SIZE]; /* To force sizeof(header). */ struct { union hdr *next; /* For chaining headers. */ char *deep; /* For stack depth measure. */ } h; } header; static header *last_alloca_header = NULL; /* -> last alloca header. */ /* Return a pointer to at least SIZE bytes of storage, which will be automatically reclaimed upon exit from the procedure that called alloca. Originally, this space was supposed to be taken from the current stack frame of the caller, but that method cannot be made to work for some implementations of C, for example under Gould's UTX/32. */ pointer alloca (unsigned size) { auto char probe; /* Probes stack depth: */ register char *depth = ADDRESS_FUNCTION (probe); #if STACK_DIRECTION == 0 if (STACK_DIR == 0) /* Unknown growth direction. */ find_stack_direction (); #endif /* Reclaim garbage, defined as all alloca'd storage that was allocated from deeper in the stack than currently. */ { register header *hp; /* Traverses linked list. */ #ifdef emacs BLOCK_INPUT; #endif for (hp = last_alloca_header; hp != NULL;) if ((STACK_DIR > 0 && hp->h.deep > depth) || (STACK_DIR < 0 && hp->h.deep < depth)) { register header *np = hp->h.next; free ((pointer) hp); /* Collect garbage. */ hp = np; /* -> next header. */ } else break; /* Rest are not deeper. */ last_alloca_header = hp; /* -> last valid storage. */ #ifdef emacs UNBLOCK_INPUT; #endif } if (size == 0) return NULL; /* No allocation required. */ /* Allocate combined header + user data storage. */ { register pointer new = malloc (sizeof (header) + size); /* Address of header. */ if (new == 0) abort(); ((header *) new)->h.next = last_alloca_header; ((header *) new)->h.deep = depth; last_alloca_header = (header *) new; /* User storage begins just after header. */ return (pointer) ((char *) new + sizeof (header)); } } #if defined (CRAY) && defined (CRAY_STACKSEG_END) #ifdef DEBUG_I00AFUNC #include #endif #ifndef CRAY_STACK #define CRAY_STACK #ifndef CRAY2 /* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ struct stack_control_header { long shgrow:32; /* Number of times stack has grown. */ long shaseg:32; /* Size of increments to stack. */ long shhwm:32; /* High water mark of stack. */ long shsize:32; /* Current size of stack (all segments). */ }; /* The stack segment linkage control information occurs at the high-address end of a stack segment. (The stack grows from low addresses to high addresses.) The initial part of the stack segment linkage control information is 0200 (octal) words. This provides for register storage for the routine which overflows the stack. */ struct stack_segment_linkage { long ss[0200]; /* 0200 overflow words. */ long sssize:32; /* Number of words in this segment. */ long ssbase:32; /* Offset to stack base. */ long:32; long sspseg:32; /* Offset to linkage control of previous segment of stack. */ long:32; long sstcpt:32; /* Pointer to task common address block. */ long sscsnm; /* Private control structure number for microtasking. */ long ssusr1; /* Reserved for user. */ long ssusr2; /* Reserved for user. */ long sstpid; /* Process ID for pid based multi-tasking. */ long ssgvup; /* Pointer to multitasking thread giveup. */ long sscray[7]; /* Reserved for Cray Research. */ long ssa0; long ssa1; long ssa2; long ssa3; long ssa4; long ssa5; long ssa6; long ssa7; long sss0; long sss1; long sss2; long sss3; long sss4; long sss5; long sss6; long sss7; }; #else /* CRAY2 */ /* The following structure defines the vector of words returned by the STKSTAT library routine. */ struct stk_stat { long now; /* Current total stack size. */ long maxc; /* Amount of contiguous space which would be required to satisfy the maximum stack demand to date. */ long high_water; /* Stack high-water mark. */ long overflows; /* Number of stack overflow ($STKOFEN) calls. */ long hits; /* Number of internal buffer hits. */ long extends; /* Number of block extensions. */ long stko_mallocs; /* Block allocations by $STKOFEN. */ long underflows; /* Number of stack underflow calls ($STKRETN). */ long stko_free; /* Number of deallocations by $STKRETN. */ long stkm_free; /* Number of deallocations by $STKMRET. */ long segments; /* Current number of stack segments. */ long maxs; /* Maximum number of stack segments so far. */ long pad_size; /* Stack pad size. */ long current_address; /* Current stack segment address. */ long current_size; /* Current stack segment size. This number is actually corrupted by STKSTAT to include the fifteen word trailer area. */ long initial_address; /* Address of initial segment. */ long initial_size; /* Size of initial segment. */ }; /* The following structure describes the data structure which trails any stack segment. I think that the description in 'asdef' is out of date. I only describe the parts that I am sure about. */ struct stk_trailer { long this_address; /* Address of this block. */ long this_size; /* Size of this block (does not include this trailer). */ long unknown2; long unknown3; long link; /* Address of trailer block of previous segment. */ long unknown5; long unknown6; long unknown7; long unknown8; long unknown9; long unknown10; long unknown11; long unknown12; long unknown13; long unknown14; }; #endif /* CRAY2 */ #endif /* not CRAY_STACK */ #ifdef CRAY2 /* Determine a "stack measure" for an arbitrary ADDRESS. I doubt that "lint" will like this much. */ static long i00afunc (long *address) { struct stk_stat status; struct stk_trailer *trailer; long *block, size; long result = 0; /* We want to iterate through all of the segments. The first step is to get the stack status structure. We could do this more quickly and more directly, perhaps, by referencing the $LM00 common block, but I know that this works. */ STKSTAT (&status); /* Set up the iteration. */ trailer = (struct stk_trailer *) (status.current_address + status.current_size - 15); /* There must be at least one stack segment. Therefore it is a fatal error if "trailer" is null. */ if (trailer == 0) abort (); /* Discard segments that do not contain our argument address. */ while (trailer != 0) { block = (long *) trailer->this_address; size = trailer->this_size; if (block == 0 || size == 0) abort (); trailer = (struct stk_trailer *) trailer->link; if ((block <= address) && (address < (block + size))) break; } /* Set the result to the offset in this segment and add the sizes of all predecessor segments. */ result = address - block; if (trailer == 0) { return result; } do { if (trailer->this_size <= 0) abort (); result += trailer->this_size; trailer = (struct stk_trailer *) trailer->link; } while (trailer != 0); /* We are done. Note that if you present a bogus address (one not in any segment), you will get a different number back, formed from subtracting the address of the first block. This is probably not what you want. */ return (result); } #else /* not CRAY2 */ /* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. Determine the number of the cell within the stack, given the address of the cell. The purpose of this routine is to linearize, in some sense, stack addresses for alloca. */ static long i00afunc (long address) { long stkl = 0; long size, pseg, this_segment, stack; long result = 0; struct stack_segment_linkage *ssptr; /* Register B67 contains the address of the end of the current stack segment. If you (as a subprogram) store your registers on the stack and find that you are past the contents of B67, you have overflowed the segment. B67 also points to the stack segment linkage control area, which is what we are really interested in. */ stkl = CRAY_STACKSEG_END (); ssptr = (struct stack_segment_linkage *) stkl; /* If one subtracts 'size' from the end of the segment, one has the address of the first word of the segment. If this is not the first segment, 'pseg' will be nonzero. */ pseg = ssptr->sspseg; size = ssptr->sssize; this_segment = stkl - size; /* It is possible that calling this routine itself caused a stack overflow. Discard stack segments which do not contain the target address. */ while (!(this_segment <= address && address <= stkl)) { #ifdef DEBUG_I00AFUNC fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); #endif if (pseg == 0) break; stkl = stkl - pseg; ssptr = (struct stack_segment_linkage *) stkl; size = ssptr->sssize; pseg = ssptr->sspseg; this_segment = stkl - size; } result = address - this_segment; /* If you subtract pseg from the current end of the stack, you get the address of the previous stack segment's end. This seems a little convoluted to me, but I'll bet you save a cycle somewhere. */ while (pseg != 0) { #ifdef DEBUG_I00AFUNC fprintf (stderr, "%011o %011o\n", pseg, size); #endif stkl = stkl - pseg; ssptr = (struct stack_segment_linkage *) stkl; size = ssptr->sssize; pseg = ssptr->sspseg; result += size; } return (result); } #endif /* not CRAY2 */ #endif /* CRAY */ #endif /* no alloca */ #endif /* not GCC version 2 */ kbuild-3686/src/kmk/config/0000775000175000017500000000000015053010075015526 5ustar locutuslocutuskbuild-3686/src/kmk/config/Makefile.am0000664000175000017500000000145215053010075017564 0ustar locutuslocutus# -*-Makefile-*-, or close enough # Copyright (C) 2002-2016 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) # any later version. # # GNU Make 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, see . # Autoconf / automake know how to handle this directory. kbuild-3686/src/kmk/config/.gitignore0000664000175000017500000000016615053010075017521 0ustar locutuslocutusar-lib compile config.guess config.rpath config.sub depcomp install-sh mdate-sh missing texinfo.tex *.m4 !dospaths.m4 kbuild-3686/src/kmk/config/dospaths.m40000664000175000017500000000261515053010075017621 0ustar locutuslocutus# Test if the system uses DOS-style pathnames (drive specs and backslashes) # By Paul Smith . Based on dos.m4 by Jim Meyering. # # Copyright (C) 1993-2016 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make 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 3 of the License, or (at your option) any later # version. # # GNU Make 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, see . AC_DEFUN([pds_AC_DOS_PATHS], [ AC_CACHE_CHECK([whether system uses MSDOS-style paths], [ac_cv_dos_paths], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if !defined _WIN32 && !defined __WIN32__ && !defined __MSDOS__ && !defined __EMX__ && !defined __MSYS__ && !defined __CYGWIN__ neither MSDOS nor Windows nor OS2 #endif ]])], [ac_cv_dos_paths=yes], [ac_cv_dos_paths=no])]) AS_IF([test x"$ac_cv_dos_paths" = xyes], [ AC_DEFINE_UNQUOTED([HAVE_DOS_PATHS], 1, [Define if the system uses DOS-style pathnames.])]) ]) kbuild-3686/src/kmk/config/ChangeLog.10000664000175000017500000000352215053010075017441 0ustar locutuslocutus2012-01-15 Paul Smith * dospaths.m4: Use AC_LANG_PROGRAM to encapsulate the test code. Fixes Savannah bug #35256. Patch from Sebastian Pipping. 2006-03-09 Paul Smith * dospaths.m4: Add MSYS to the list of targets allowing DOS-style pathnames. Reported by David Ergo . 2005-07-01 Paul D. Smith * Makefile.am (EXTRA_DIST): Added more M4 files to EXTRA_DIST, so users can re-run aclocal. 2003-04-30 Paul D. Smith * dospaths.m4: New macro to test for DOS-style pathnames, based on coreutils 5.0 "dos.m4" by Jim Meyering. 2002-04-21 gettextize * codeset.m4: New file, from gettext-0.11.1. * gettext.m4: New file, from gettext-0.11.1. * glibc21.m4: New file, from gettext-0.11.1. * iconv.m4: New file, from gettext-0.11.1. * isc-posix.m4: New file, from gettext-0.11.1. * lcmessage.m4: New file, from gettext-0.11.1. * lib-ld.m4: New file, from gettext-0.11.1. * lib-link.m4: New file, from gettext-0.11.1. * lib-prefix.m4: New file, from gettext-0.11.1. * progtest.m4: New file, from gettext-0.11.1. * Makefile.am: New file. Copyright (C) 2002-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make 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 3 of the License, or (at your option) any later version. GNU Make 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, see . kbuild-3686/src/kmk/testcase-kBuild-define.kmk0000664000175000017500000001215215053010075021241 0ustar locutuslocutus# $Id: testcase-kBuild-define.kmk 2720 2014-01-01 22:59:50Z bird $ ## @file # kBuild - testcase for the kBuild-define-* directives. # # # Copyright (c) 2011-2013 knut st. osmundsen # # This file is part of kBuild. # # kBuild 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 3 of the License, or # (at your option) any later version. # # kBuild 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 kBuild. If not, see # # #DEPTH = ../.. #include $(PATH_KBUILD)/header.kmk ## # Test if $($1) == $2 and raises an error if it isn't. # # @param 1 Something to apply '$' to. # @param 2 The expected value. TEST_EQ = $(if-expr "$($1)" == "$2",,$(error $1 is '$($1)' not '$2')) if 0 # object definition syntax: # kobject [extends [by <||>]] [object specific args...] # kendobj [ [name]] kobject kb-target MyTarget .TOOL = GCC .SOURCES = file.c kendobj else # Target definition. # kBuild-define-target [extends [by <||>]] [using