pkg-config-0.29.1/ 0000775 0001750 0001750 00000000000 12665370350 010641 5 0000000 0000000 pkg-config-0.29.1/config.guess 0000755 0001750 0001750 00000123672 12601774033 013106 0000000 0000000 #! /bin/sh
# Attempt to guess a canonical system name.
# Copyright 1992-2015 Free Software Foundation, Inc.
timestamp='2015-01-01'
# 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 3 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, see .
#
# 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 Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
#
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
#
# Please send patches to .
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 1992-2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help" >&2
exit 1 ;;
* )
break ;;
esac
done
if test $# != 0; then
echo "$me: too many arguments$help" >&2
exit 1
fi
trap 'exit 1' 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 "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
dummy=$tmp/dummy ;
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
case $CC_FOR_BUILD,$HOST_CC,$CC in
,,) echo "int x;" > $dummy.c ;
for c in cc gcc c89 c99 ; do
if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
CC_FOR_BUILD="$c"; break ;
fi ;
done ;
if test x"$CC_FOR_BUILD" = x ; then
CC_FOR_BUILD=no_compiler_found ;
fi
;;
,,*) CC_FOR_BUILD=$CC ;;
,*,*) CC_FOR_BUILD=$HOST_CC ;;
esac ; set_cc_for_build= ;'
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "${UNAME_SYSTEM}" in
Linux|GNU|GNU/*)
# If the system lacks a compiler, then just pick glibc.
# We could probably try harder.
LIBC=gnu
eval $set_cc_for_build
cat <<-EOF > $dummy.c
#include
#if defined(__UCLIBC__)
LIBC=uclibc
#elif defined(__dietlibc__)
LIBC=dietlibc
#else
LIBC=gnu
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
;;
esac
# 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 tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
# compatibility and a consistent mechanism for selecting the
# object file format.
#
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
sysctl="sysctl -n hw.machine_arch"
UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
/usr/sbin/$sysctl 2>/dev/null || echo unknown)`
case "${UNAME_MACHINE_ARCH}" in
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
esac
# The Operating System including object format, if it has switched
# to ELF recently, or will in the future.
case "${UNAME_MACHINE_ARCH}" in
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
eval $set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ELF__
then
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
# Return netbsd for either. FIX?
os=netbsd
else
os=netbsdelf
fi
;;
*)
os=netbsd
;;
esac
# The OS release
# Debian GNU/NetBSD machines have a different userland, and
# thus, need a distinct triplet. However, they do not need
# kernel version information, so it can be replaced with a
# suitable tag, in the style of linux-gnu.
case "${UNAME_VERSION}" in
Debian*)
release='-gnu'
;;
*)
release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
echo "${machine}-${os}${release}"
exit ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
exit ;;
*:ekkoBSD:*:*)
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
exit ;;
*:SolidBSD:*:*)
echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
exit ;;
macppc:MirBSD:*:*)
echo powerpc-unknown-mirbsd${UNAME_RELEASE}
exit ;;
*:MirBSD:*:*)
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
exit ;;
alpha:OSF1:*:*)
case $UNAME_RELEASE in
*4.0)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;;
*5.*)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU
# types through head -n 1, so we only detect the type of CPU 0.
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
case "$ALPHA_CPU_TYPE" in
"EV4 (21064)")
UNAME_MACHINE="alpha" ;;
"EV4.5 (21064)")
UNAME_MACHINE="alpha" ;;
"LCA4 (21066/21068)")
UNAME_MACHINE="alpha" ;;
"EV5 (21164)")
UNAME_MACHINE="alphaev5" ;;
"EV5.6 (21164A)")
UNAME_MACHINE="alphaev56" ;;
"EV5.6 (21164PC)")
UNAME_MACHINE="alphapca56" ;;
"EV5.7 (21164PC)")
UNAME_MACHINE="alphapca57" ;;
"EV6 (21264)")
UNAME_MACHINE="alphaev6" ;;
"EV6.7 (21264A)")
UNAME_MACHINE="alphaev67" ;;
"EV6.8CB (21264C)")
UNAME_MACHINE="alphaev68" ;;
"EV6.8AL (21264B)")
UNAME_MACHINE="alphaev68" ;;
"EV6.8CX (21264D)")
UNAME_MACHINE="alphaev68" ;;
"EV6.9A (21264/EV69A)")
UNAME_MACHINE="alphaev69" ;;
"EV7 (21364)")
UNAME_MACHINE="alphaev7" ;;
"EV7.9 (21364A)")
UNAME_MACHINE="alphaev79" ;;
esac
# A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
exitcode=$?
trap '' 0
exit $exitcode ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# Should we change UNAME_MACHINE based on the output of uname instead
# of the specific Alpha model?
echo alpha-pc-interix
exit ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
exit ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-unknown-sysv4
exit ;;
*:[Aa]miga[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-amigaos
exit ;;
*:[Mm]orph[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-morphos
exit ;;
*:OS/390:*:*)
echo i370-ibm-openedition
exit ;;
*:z/VM:*:*)
echo s390-ibm-zvmoe
exit ;;
*:OS400:*:*)
echo powerpc-ibm-os400
exit ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit ;;
arm*:riscos:*:*|arm*:RISCOS:*:*)
echo arm-unknown-riscos
exit ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
echo hppa1.1-hitachi-hiuxmpp
exit ;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "`(/bin/universe) 2>/dev/null`" = att ; then
echo pyramid-pyramid-sysv3
else
echo pyramid-pyramid-bsd
fi
exit ;;
NILE*:*:*:dcosx)
echo pyramid-pyramid-svr4
exit ;;
DRS?6000:unix:4.0:6*)
echo sparc-icl-nx6
exit ;;
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
case `/usr/bin/uname -p` in
sparc) echo sparc-icl-nx7; exit ;;
esac ;;
s390x:SunOS:*:*)
echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4H:SunOS:5.*:*)
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
echo i386-pc-auroraux${UNAME_RELEASE}
exit ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
eval $set_cc_for_build
SUN_ARCH="i386"
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
SUN_ARCH="x86_64"
fi
fi
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
exit ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
exit ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
case "`/bin/arch`" in
sun3)
echo m68k-sun-sunos${UNAME_RELEASE}
;;
sun4)
echo sparc-sun-sunos${UNAME_RELEASE}
;;
esac
exit ;;
aushp:SunOS:*:*)
echo sparc-auspex-sunos${UNAME_RELEASE}
exit ;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
# "atarist" or "atariste" at least should have a processor
# > m68000). The system name ranges from "MiNT" over "FreeMiNT"
# to the lowercase version "mint" (or "freemint"). Finally
# the system name "TOS" denotes a system which is actually not
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
echo m68k-milan-mint${UNAME_RELEASE}
exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
echo m68k-hades-mint${UNAME_RELEASE}
exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
echo m68k-unknown-mint${UNAME_RELEASE}
exit ;;
m68k:machten:*:*)
echo m68k-apple-machten${UNAME_RELEASE}
exit ;;
powerpc:machten:*:*)
echo powerpc-apple-machten${UNAME_RELEASE}
exit ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
exit ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
exit ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
exit ;;
2020:CLIX:*:* | 2430:CLIX:*:*)
echo clipper-intergraph-clix${UNAME_RELEASE}
exit ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#ifdef __cplusplus
#include /* for printf() prototype */
int main (int argc, char *argv[]) {
#else
int main (argc, argv) int argc; char *argv[]; {
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
$CC_FOR_BUILD -o $dummy $dummy.c &&
dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
SYSTEM_NAME=`$dummy $dummyarg` &&
{ echo "$SYSTEM_NAME"; exit; }
echo mips-mips-riscos${UNAME_RELEASE}
exit ;;
Motorola:PowerMAX_OS:*:*)
echo powerpc-motorola-powermax
exit ;;
Motorola:*:4.3:PL8-*)
echo powerpc-harris-powermax
exit ;;
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
echo powerpc-harris-powermax
exit ;;
Night_Hawk:Power_UNIX:*:*)
echo powerpc-harris-powerunix
exit ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
exit ;;
m88k:*:4*:R4*)
echo m88k-motorola-sysv4
exit ;;
m88k:*:3*:R3*)
echo m88k-motorola-sysv3
exit ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
[ ${TARGET_BINARY_INTERFACE}x = x ]
then
echo m88k-dg-dgux${UNAME_RELEASE}
else
echo m88k-dg-dguxbcs${UNAME_RELEASE}
fi
else
echo i586-dg-dgux${UNAME_RELEASE}
fi
exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
echo m88k-motorola-sysv3
exit ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
echo m88k-tektronix-sysv3
exit ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
echo m68k-tektronix-bsd
exit ;;
*:IRIX*:*:*)
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
exit ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*)
echo i386-ibm-aix
exit ;;
ia64:AIX:*:*)
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
exit ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#include
main()
{
if (!__power_pc())
exit(1);
puts("powerpc-ibm-aix3.2.5");
exit(0);
}
EOF
if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
then
echo "$SYSTEM_NAME"
else
echo rs6000-ibm-aix3.2.5
fi
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
else
echo rs6000-ibm-aix3.2
fi
exit ;;
*:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if [ -x /usr/bin/lslpp ] ; then
IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
exit ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
echo romp-ibm-bsd4.4
exit ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
exit ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
exit ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
exit ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
exit ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit ;;
9000/[34678]??:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "${sc_cpu_version}" in
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "${sc_kernel_bits}" in
32) HP_ARCH="hppa2.0n" ;;
64) HP_ARCH="hppa2.0w" ;;
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
esac ;;
esac
fi
if [ "${HP_ARCH}" = "" ]; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#define _HPUX_SOURCE
#include
#include
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
EOF
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
if [ ${HP_ARCH} = "hppa2.0w" ]
then
eval $set_cc_for_build
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
# generating 64-bit code. GNU and HP use different nomenclature:
#
# $ CC_FOR_BUILD=cc ./config.guess
# => hppa2.0w-hp-hpux11.23
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
# => hppa64-hp-hpux11.23
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
grep -q __LP64__
then
HP_ARCH="hppa2.0w"
else
HP_ARCH="hppa64"
fi
fi
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
exit ;;
ia64:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ia64-hp-hpux${HPUX_REV}
exit ;;
3050*:HI-UX:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#include
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
{ echo "$SYSTEM_NAME"; exit; }
echo unknown-hitachi-hiuxwe2
exit ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
exit ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit ;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
echo hppa1.0-hp-mpeix
exit ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
exit ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit ;;
i*86:OSF1:*:*)
if [ -x /usr/sbin/sysversion ] ; then
echo ${UNAME_MACHINE}-unknown-osf1mk
else
echo ${UNAME_MACHINE}-unknown-osf1
fi
exit ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*[A-Z]90:*:*:*)
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*T3E:*:*:*)
echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*SV1:*:*:*)
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
*:UNICOS/mp:*:*)
echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
exit ;;
sparc*:BSD/OS:*:*)
echo sparc-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:FreeBSD:*:*)
UNAME_PROCESSOR=`/usr/bin/uname -p`
case ${UNAME_PROCESSOR} in
amd64)
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
*)
echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
esac
exit ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
exit ;;
*:MINGW64*:*)
echo ${UNAME_MACHINE}-pc-mingw64
exit ;;
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
*:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32
exit ;;
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
*:Interix*:*)
case ${UNAME_MACHINE} in
x86)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
authenticamd | genuineintel | EM64T)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
IA64)
echo ia64-unknown-interix${UNAME_RELEASE}
exit ;;
esac ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
exit ;;
8664:Windows_NT:*)
echo x86_64-pc-mks
exit ;;
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
# UNAME_MACHINE based on the output of uname instead of i386?
echo i586-pc-interix
exit ;;
i*:UWIN*:*)
echo ${UNAME_MACHINE}-pc-uwin
exit ;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
echo x86_64-unknown-cygwin
exit ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin
exit ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
*:GNU:*:*)
# the GNU system
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
exit ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit ;;
aarch64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
PCA57) UNAME_MACHINE=alphapca56 ;;
EV6) UNAME_MACHINE=alphaev6 ;;
EV67) UNAME_MACHINE=alphaev67 ;;
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arc:Linux:*:* | arceb:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arm*:Linux:*:*)
eval $set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
else
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
cris:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
crisv32:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
frv:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
hexagon:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:Linux:*:*)
echo ${UNAME_MACHINE}-pc-linux-${LIBC}
exit ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
mips:Linux:*:* | mips64:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
#undef ${UNAME_MACHINE}
#undef ${UNAME_MACHINE}el
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
CPU=${UNAME_MACHINE}el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
CPU=${UNAME_MACHINE}
#else
CPU=
#endif
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
openrisc*:Linux:*:*)
echo or1k-unknown-linux-${LIBC}
exit ;;
or32:Linux:*:* | or1k*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-${LIBC}
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-${LIBC}
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
*) echo hppa-unknown-linux-${LIBC} ;;
esac
exit ;;
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-${LIBC}
exit ;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-${LIBC}
exit ;;
ppc64le:Linux:*:*)
echo powerpc64le-unknown-linux-${LIBC}
exit ;;
ppcle:Linux:*:*)
echo powerpcle-unknown-linux-${LIBC}
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
exit ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
tile*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
vax:Linux:*:*)
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
exit ;;
x86_64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
# sysname and nodename.
echo i386-sequent-sysv4
exit ;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
exit ;;
i*86:OS/2:*:*)
# If we were able to find `uname', then EMX Unix compatibility
# is probably installed.
echo ${UNAME_MACHINE}-pc-os2-emx
exit ;;
i*86:XTS-300:*:STOP)
echo ${UNAME_MACHINE}-unknown-stop
exit ;;
i*86:atheos:*:*)
echo ${UNAME_MACHINE}-unknown-atheos
exit ;;
i*86:syllable:*:*)
echo ${UNAME_MACHINE}-pc-syllable
exit ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
exit ;;
i*86:*DOS:*:*)
echo ${UNAME_MACHINE}-pc-msdosdjgpp
exit ;;
i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
else
echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
fi
exit ;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
exit ;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
&& UNAME_MACHINE=i686
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
&& UNAME_MACHINE=i686
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
else
echo ${UNAME_MACHINE}-pc-sysv32
fi
exit ;;
pc:*:*:*)
# Left here for compatibility:
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
# prints for the "djgpp" host, or else GDB configury will decide that
# this is a cross-build.
echo i586-pc-msdosdjgpp
exit ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit ;;
paragon:*:*:*)
echo i860-intel-osf1
exit ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
fi
exit ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
echo m68010-convergent-sysv
exit ;;
mc68k:UNIX:SYSTEM5:3.51m)
echo m68k-convergent-sysv
exit ;;
M680?0:D-NIX:5.3:*)
echo m68k-diab-dnix
exit ;;
M68*:*:R3V[5678]*:*)
test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
OS_REL='.3'
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
echo m68k-unknown-lynxos${UNAME_RELEASE}
exit ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit ;;
TSUNAMI:LynxOS:2.*:*)
echo sparc-unknown-lynxos${UNAME_RELEASE}
exit ;;
rs6000:LynxOS:2.*:*)
echo rs6000-unknown-lynxos${UNAME_RELEASE}
exit ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
echo powerpc-unknown-lynxos${UNAME_RELEASE}
exit ;;
SM[BE]S:UNIX_SV:*:*)
echo mips-dde-sysv${UNAME_RELEASE}
exit ;;
RM*:ReliantUNIX-*:*:*)
echo mips-sni-sysv4
exit ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
exit ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
echo ${UNAME_MACHINE}-sni-sysv4
else
echo ns32k-sni-sysv
fi
exit ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says
echo i586-unisys-sysv4
exit ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes .
# How about differentiating between stratus architectures? -djm
echo hppa1.1-stratus-sysv4
exit ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
echo i860-stratus-sysv4
exit ;;
i*86:VOS:*:*)
# From Paul.Green@stratus.com.
echo ${UNAME_MACHINE}-stratus-vos
exit ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
echo hppa1.1-stratus-vos
exit ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
exit ;;
news*:NEWS-OS:6*:*)
echo mips-sony-newsos6
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
exit ;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
echo powerpc-apple-beos
exit ;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
exit ;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
echo i586-pc-haiku
exit ;;
x86_64:Haiku:*:*)
echo x86_64-unknown-haiku
exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
exit ;;
SX-5:SUPER-UX:*:*)
echo sx5-nec-superux${UNAME_RELEASE}
exit ;;
SX-6:SUPER-UX:*:*)
echo sx6-nec-superux${UNAME_RELEASE}
exit ;;
SX-7:SUPER-UX:*:*)
echo sx7-nec-superux${UNAME_RELEASE}
exit ;;
SX-8:SUPER-UX:*:*)
echo sx8-nec-superux${UNAME_RELEASE}
exit ;;
SX-8R:SUPER-UX:*:*)
echo sx8r-nec-superux${UNAME_RELEASE}
exit ;;
Power*:Rhapsody:*:*)
echo powerpc-apple-rhapsody${UNAME_RELEASE}
exit ;;
*:Rhapsody:*:*)
echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
exit ;;
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
eval $set_cc_for_build
if test "$UNAME_PROCESSOR" = unknown ; then
UNAME_PROCESSOR=powerpc
fi
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
case $UNAME_PROCESSOR in
i386) UNAME_PROCESSOR=x86_64 ;;
powerpc) UNAME_PROCESSOR=powerpc64 ;;
esac
fi
fi
elif test "$UNAME_PROCESSOR" = i386 ; then
# Avoid executing cc on OS X 10.9, as it ships with a stub
# that puts up a graphical alert prompting to install
# developer tools. Any system running Mac OS X 10.7 or
# later (Darwin 11 and later) is required to have a 64-bit
# processor. This is not true of the ARM version of Darwin
# that Apple uses in portable devices.
UNAME_PROCESSOR=x86_64
fi
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
if test "$UNAME_PROCESSOR" = "x86"; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
exit ;;
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
NEO-?:NONSTOP_KERNEL:*:*)
echo neo-tandem-nsk${UNAME_RELEASE}
exit ;;
NSE-*:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk${UNAME_RELEASE}
exit ;;
NSR-?:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit ;;
*:NonStop-UX:*:*)
echo mips-compaq-nonstopux
exit ;;
BS2000:POSIX*:*:*)
echo bs2000-siemens-sysv
exit ;;
DS/*:UNIX_System_V:*:*)
echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
exit ;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
if test "$cputype" = "386"; then
UNAME_MACHINE=i386
else
UNAME_MACHINE="$cputype"
fi
echo ${UNAME_MACHINE}-unknown-plan9
exit ;;
*:TOPS-10:*:*)
echo pdp10-unknown-tops10
exit ;;
*:TENEX:*:*)
echo pdp10-unknown-tenex
exit ;;
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
echo pdp10-dec-tops20
exit ;;
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
echo pdp10-xkl-tops20
exit ;;
*:TOPS-20:*:*)
echo pdp10-unknown-tops20
exit ;;
*:ITS:*:*)
echo pdp10-unknown-its
exit ;;
SEI:*:*:SEIUX)
echo mips-sei-seiux${UNAME_RELEASE}
exit ;;
*:DragonFly:*:*)
echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit ;;
*:*VMS:*:*)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
case "${UNAME_MACHINE}" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
V*) echo vax-dec-vms ; exit ;;
esac ;;
*:XENIX:*:SysV)
echo i386-pc-xenix
exit ;;
i*86:skyos:*:*)
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
exit ;;
i*86:rdos:*:*)
echo ${UNAME_MACHINE}-pc-rdos
exit ;;
i*86:AROS:*:*)
echo ${UNAME_MACHINE}-pc-aros
exit ;;
x86_64:VMkernel:*:*)
echo ${UNAME_MACHINE}-unknown-esx
exit ;;
esac
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:
pkg-config-0.29.1/depcomp 0000755 0001750 0001750 00000056016 12601774033 012140 0000000 0000000 #! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999-2014 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, see .
# 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 outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to .
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
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"
# Avoid interferences from the environment.
gccflag= dashmflag=
# 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
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
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.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## 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). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - 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 -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# 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.
## 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. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -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 -ne 0; then
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 ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# 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
;;
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.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
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"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
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.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# 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
;;
#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 "X$1" != 'X--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|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| 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 "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
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.
-arch)
eat=yes ;;
-*|$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"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| 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 "X$1" != 'X--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 -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [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.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# 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
;;
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-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
pkg-config-0.29.1/aclocal.m4 0000664 0001750 0001750 00001327442 12665370324 012437 0000000 0000000 # generated automatically by aclocal 1.15 -*- Autoconf -*-
# Copyright (C) 1996-2014 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.
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
[m4_warning([this file was generated for autoconf 2.69.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
#
# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc.
# Written by Gordon Matzigkeit, 1996
#
# 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.
m4_define([_LT_COPYING], [dnl
# Copyright (C) 2014 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.
# GNU Libtool 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 of the License, or
# (at your option) any later version.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program or library that is built
# using GNU Libtool, you may include this file under the same
# distribution terms that you use for the rest of that program.
#
# GNU Libtool 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 .
])
# serial 58 LT_INIT
# LT_PREREQ(VERSION)
# ------------------
# Complain and exit if this libtool version is less that VERSION.
m4_defun([LT_PREREQ],
[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
[m4_default([$3],
[m4_fatal([Libtool version $1 or higher is required],
63)])],
[$2])])
# _LT_CHECK_BUILDDIR
# ------------------
# Complain if the absolute build directory name contains unusual characters
m4_defun([_LT_CHECK_BUILDDIR],
[case `pwd` in
*\ * | *\ *)
AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
esac
])
# LT_INIT([OPTIONS])
# ------------------
AC_DEFUN([LT_INIT],
[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK
AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
AC_BEFORE([$0], [LT_LANG])dnl
AC_BEFORE([$0], [LT_OUTPUT])dnl
AC_BEFORE([$0], [LTDL_INIT])dnl
m4_require([_LT_CHECK_BUILDDIR])dnl
dnl Autoconf doesn't catch unexpanded LT_ macros by default:
m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
dnl unless we require an AC_DEFUNed macro:
AC_REQUIRE([LTOPTIONS_VERSION])dnl
AC_REQUIRE([LTSUGAR_VERSION])dnl
AC_REQUIRE([LTVERSION_VERSION])dnl
AC_REQUIRE([LTOBSOLETE_VERSION])dnl
m4_require([_LT_PROG_LTMAIN])dnl
_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
dnl Parse OPTIONS
_LT_SET_OPTIONS([$0], [$1])
# This can be used to rebuild libtool when needed
LIBTOOL_DEPS=$ltmain
# Always use our own libtool.
LIBTOOL='$(SHELL) $(top_builddir)/libtool'
AC_SUBST(LIBTOOL)dnl
_LT_SETUP
# Only expand once:
m4_define([LT_INIT])
])# LT_INIT
# Old names:
AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
# _LT_PREPARE_CC_BASENAME
# -----------------------
m4_defun([_LT_PREPARE_CC_BASENAME], [
# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
func_cc_basename ()
{
for cc_temp in @S|@*""; do
case $cc_temp in
compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
\-*) ;;
*) break;;
esac
done
func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
}
])# _LT_PREPARE_CC_BASENAME
# _LT_CC_BASENAME(CC)
# -------------------
# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME,
# but that macro is also expanded into generated libtool script, which
# arranges for $SED and $ECHO to be set by different means.
m4_defun([_LT_CC_BASENAME],
[m4_require([_LT_PREPARE_CC_BASENAME])dnl
AC_REQUIRE([_LT_DECL_SED])dnl
AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
func_cc_basename $1
cc_basename=$func_cc_basename_result
])
# _LT_FILEUTILS_DEFAULTS
# ----------------------
# It is okay to use these file commands and assume they have been set
# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'.
m4_defun([_LT_FILEUTILS_DEFAULTS],
[: ${CP="cp -f"}
: ${MV="mv -f"}
: ${RM="rm -f"}
])# _LT_FILEUTILS_DEFAULTS
# _LT_SETUP
# ---------
m4_defun([_LT_SETUP],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
dnl
_LT_DECL([], [host_alias], [0], [The host system])dnl
_LT_DECL([], [host], [0])dnl
_LT_DECL([], [host_os], [0])dnl
dnl
_LT_DECL([], [build_alias], [0], [The build system])dnl
_LT_DECL([], [build], [0])dnl
_LT_DECL([], [build_os], [0])dnl
dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([LT_PATH_LD])dnl
AC_REQUIRE([LT_PATH_NM])dnl
dnl
AC_REQUIRE([AC_PROG_LN_S])dnl
test -z "$LN_S" && LN_S="ln -s"
_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
dnl
AC_REQUIRE([LT_CMD_MAX_LEN])dnl
_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_CHECK_SHELL_FEATURES])dnl
m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
m4_require([_LT_CMD_RELOAD])dnl
m4_require([_LT_CHECK_MAGIC_METHOD])dnl
m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
m4_require([_LT_CMD_OLD_ARCHIVE])dnl
m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
m4_require([_LT_WITH_SYSROOT])dnl
m4_require([_LT_CMD_TRUNCATE])dnl
_LT_CONFIG_LIBTOOL_INIT([
# See if we are running on zsh, and set the options that allow our
# commands through without removal of \ escapes INIT.
if test -n "\${ZSH_VERSION+set}"; then
setopt NO_GLOB_SUBST
fi
])
if test -n "${ZSH_VERSION+set}"; then
setopt NO_GLOB_SUBST
fi
_LT_CHECK_OBJDIR
m4_require([_LT_TAG_COMPILER])dnl
case $host_os in
aix3*)
# AIX sometimes has problems with the GCC collect2 program. For some
# reason, if we set the COLLECT_NAMES environment variable, the problems
# vanish in a puff of smoke.
if test set != "${COLLECT_NAMES+set}"; then
COLLECT_NAMES=
export COLLECT_NAMES
fi
;;
esac
# Global variables:
ofile=libtool
can_build_shared=yes
# All known linkers require a '.a' archive for static linking (except MSVC,
# which needs '.lib').
libext=a
with_gnu_ld=$lt_cv_prog_gnu_ld
old_CC=$CC
old_CFLAGS=$CFLAGS
# Set sane defaults for various variables
test -z "$CC" && CC=cc
test -z "$LTCC" && LTCC=$CC
test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
test -z "$LD" && LD=ld
test -z "$ac_objext" && ac_objext=o
_LT_CC_BASENAME([$compiler])
# Only perform the check for file, if the check method requires it
test -z "$MAGIC_CMD" && MAGIC_CMD=file
case $deplibs_check_method in
file_magic*)
if test "$file_magic_cmd" = '$MAGIC_CMD'; then
_LT_PATH_MAGIC
fi
;;
esac
# Use C for the default configuration in the libtool script
LT_SUPPORTED_TAG([CC])
_LT_LANG_C_CONFIG
_LT_LANG_DEFAULT_CONFIG
_LT_CONFIG_COMMANDS
])# _LT_SETUP
# _LT_PREPARE_SED_QUOTE_VARS
# --------------------------
# Define a few sed substitution that help us do robust quoting.
m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
[# Backslashify metacharacters that are still active within
# double-quoted strings.
sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
# Same as above, but do not quote variable references.
double_quote_subst='s/\([["`\\]]\)/\\\1/g'
# Sed substitution to delay expansion of an escaped shell variable in a
# double_quote_subst'ed string.
delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
# Sed substitution to delay expansion of an escaped single quote.
delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
# Sed substitution to avoid accidental globbing in evaled expressions
no_glob_subst='s/\*/\\\*/g'
])
# _LT_PROG_LTMAIN
# ---------------
# Note that this code is called both from 'configure', and 'config.status'
# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably,
# 'config.status' has no value for ac_aux_dir unless we are using Automake,
# so we pass a copy along to make sure it has a sensible value anyway.
m4_defun([_LT_PROG_LTMAIN],
[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
ltmain=$ac_aux_dir/ltmain.sh
])# _LT_PROG_LTMAIN
# So that we can recreate a full libtool script including additional
# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
# in macros and then make a single call at the end using the 'libtool'
# label.
# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
# ----------------------------------------
# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
m4_define([_LT_CONFIG_LIBTOOL_INIT],
[m4_ifval([$1],
[m4_append([_LT_OUTPUT_LIBTOOL_INIT],
[$1
])])])
# Initialize.
m4_define([_LT_OUTPUT_LIBTOOL_INIT])
# _LT_CONFIG_LIBTOOL([COMMANDS])
# ------------------------------
# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
m4_define([_LT_CONFIG_LIBTOOL],
[m4_ifval([$1],
[m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
[$1
])])])
# Initialize.
m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
# -----------------------------------------------------
m4_defun([_LT_CONFIG_SAVE_COMMANDS],
[_LT_CONFIG_LIBTOOL([$1])
_LT_CONFIG_LIBTOOL_INIT([$2])
])
# _LT_FORMAT_COMMENT([COMMENT])
# -----------------------------
# Add leading comment marks to the start of each line, and a trailing
# full-stop to the whole comment if one is not present already.
m4_define([_LT_FORMAT_COMMENT],
[m4_ifval([$1], [
m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
[['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
)])
# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
# -------------------------------------------------------------------
# CONFIGNAME is the name given to the value in the libtool script.
# VARNAME is the (base) name used in the configure script.
# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
# VARNAME. Any other value will be used directly.
m4_define([_LT_DECL],
[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
[lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
[m4_ifval([$1], [$1], [$2])])
lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
m4_ifval([$4],
[lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
lt_dict_add_subkey([lt_decl_dict], [$2],
[tagged?], [m4_ifval([$5], [yes], [no])])])
])
# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
# --------------------------------------------------------
m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
# ------------------------------------------------
m4_define([lt_decl_tag_varnames],
[_lt_decl_filter([tagged?], [yes], $@)])
# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
# ---------------------------------------------------------
m4_define([_lt_decl_filter],
[m4_case([$#],
[0], [m4_fatal([$0: too few arguments: $#])],
[1], [m4_fatal([$0: too few arguments: $#: $1])],
[2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
[3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
[lt_dict_filter([lt_decl_dict], $@)])[]dnl
])
# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
# --------------------------------------------------
m4_define([lt_decl_quote_varnames],
[_lt_decl_filter([value], [1], $@)])
# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
# ---------------------------------------------------
m4_define([lt_decl_dquote_varnames],
[_lt_decl_filter([value], [2], $@)])
# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
# ---------------------------------------------------
m4_define([lt_decl_varnames_tagged],
[m4_assert([$# <= 2])dnl
_$0(m4_quote(m4_default([$1], [[, ]])),
m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
m4_define([_lt_decl_varnames_tagged],
[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
# ------------------------------------------------
m4_define([lt_decl_all_varnames],
[_$0(m4_quote(m4_default([$1], [[, ]])),
m4_if([$2], [],
m4_quote(lt_decl_varnames),
m4_quote(m4_shift($@))))[]dnl
])
m4_define([_lt_decl_all_varnames],
[lt_join($@, lt_decl_varnames_tagged([$1],
lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
])
# _LT_CONFIG_STATUS_DECLARE([VARNAME])
# ------------------------------------
# Quote a variable value, and forward it to 'config.status' so that its
# declaration there will have the same value as in 'configure'. VARNAME
# must have a single quote delimited value for this to work.
m4_define([_LT_CONFIG_STATUS_DECLARE],
[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
# _LT_CONFIG_STATUS_DECLARATIONS
# ------------------------------
# We delimit libtool config variables with single quotes, so when
# we write them to config.status, we have to be sure to quote all
# embedded single quotes properly. In configure, this macro expands
# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
#
# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`'
m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
[m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
# _LT_LIBTOOL_TAGS
# ----------------
# Output comment and list of tags supported by the script
m4_defun([_LT_LIBTOOL_TAGS],
[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
available_tags='_LT_TAGS'dnl
])
# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
# -----------------------------------
# Extract the dictionary values for VARNAME (optionally with TAG) and
# expand to a commented shell variable setting:
#
# # Some comment about what VAR is for.
# visible_name=$lt_internal_name
m4_define([_LT_LIBTOOL_DECLARE],
[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
[description])))[]dnl
m4_pushdef([_libtool_name],
m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
[0], [_libtool_name=[$]$1],
[1], [_libtool_name=$lt_[]$1],
[2], [_libtool_name=$lt_[]$1],
[_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
])
# _LT_LIBTOOL_CONFIG_VARS
# -----------------------
# Produce commented declarations of non-tagged libtool config variables
# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool'
# script. Tagged libtool config variables (even for the LIBTOOL CONFIG
# section) are produced by _LT_LIBTOOL_TAG_VARS.
m4_defun([_LT_LIBTOOL_CONFIG_VARS],
[m4_foreach([_lt_var],
m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
[m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
# _LT_LIBTOOL_TAG_VARS(TAG)
# -------------------------
m4_define([_LT_LIBTOOL_TAG_VARS],
[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
[m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
# _LT_TAGVAR(VARNAME, [TAGNAME])
# ------------------------------
m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
# _LT_CONFIG_COMMANDS
# -------------------
# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of
# variables for single and double quote escaping we saved from calls
# to _LT_DECL, we can put quote escaped variables declarations
# into 'config.status', and then the shell code to quote escape them in
# for loops in 'config.status'. Finally, any additional code accumulated
# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
m4_defun([_LT_CONFIG_COMMANDS],
[AC_PROVIDE_IFELSE([LT_OUTPUT],
dnl If the libtool generation code has been placed in $CONFIG_LT,
dnl instead of duplicating it all over again into config.status,
dnl then we will have config.status run $CONFIG_LT later, so it
dnl needs to know what name is stored there:
[AC_CONFIG_COMMANDS([libtool],
[$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
dnl If the libtool generation code is destined for config.status,
dnl expand the accumulated commands and init code now:
[AC_CONFIG_COMMANDS([libtool],
[_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
])#_LT_CONFIG_COMMANDS
# Initialize.
m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
[
# The HP-UX ksh and POSIX shell print the target directory to stdout
# if CDPATH is set.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
sed_quote_subst='$sed_quote_subst'
double_quote_subst='$double_quote_subst'
delay_variable_subst='$delay_variable_subst'
_LT_CONFIG_STATUS_DECLARATIONS
LTCC='$LTCC'
LTCFLAGS='$LTCFLAGS'
compiler='$compiler_DEFAULT'
# A function that is used when there is no print builtin or printf.
func_fallback_echo ()
{
eval 'cat <<_LTECHO_EOF
\$[]1
_LTECHO_EOF'
}
# Quote evaled strings.
for var in lt_decl_all_varnames([[ \
]], lt_decl_quote_varnames); do
case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
*[[\\\\\\\`\\"\\\$]]*)
eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
;;
*)
eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
;;
esac
done
# Double-quote double-evaled strings.
for var in lt_decl_all_varnames([[ \
]], lt_decl_dquote_varnames); do
case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
*[[\\\\\\\`\\"\\\$]]*)
eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
;;
*)
eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
;;
esac
done
_LT_OUTPUT_LIBTOOL_INIT
])
# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
# ------------------------------------
# Generate a child script FILE with all initialization necessary to
# reuse the environment learned by the parent script, and make the
# file executable. If COMMENT is supplied, it is inserted after the
# '#!' sequence but before initialization text begins. After this
# macro, additional text can be appended to FILE to form the body of
# the child script. The macro ends with non-zero status if the
# file could not be fully written (such as if the disk is full).
m4_ifdef([AS_INIT_GENERATED],
[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
[m4_defun([_LT_GENERATED_FILE_INIT],
[m4_require([AS_PREPARE])]dnl
[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
[lt_write_fail=0
cat >$1 <<_ASEOF || lt_write_fail=1
#! $SHELL
# Generated by $as_me.
$2
SHELL=\${CONFIG_SHELL-$SHELL}
export SHELL
_ASEOF
cat >>$1 <<\_ASEOF || lt_write_fail=1
AS_SHELL_SANITIZE
_AS_PREPARE
exec AS_MESSAGE_FD>&1
_ASEOF
test 0 = "$lt_write_fail" && chmod +x $1[]dnl
m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
# LT_OUTPUT
# ---------
# This macro allows early generation of the libtool script (before
# AC_OUTPUT is called), incase it is used in configure for compilation
# tests.
AC_DEFUN([LT_OUTPUT],
[: ${CONFIG_LT=./config.lt}
AC_MSG_NOTICE([creating $CONFIG_LT])
_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
[# Run this file to recreate a libtool stub with the current configuration.])
cat >>"$CONFIG_LT" <<\_LTEOF
lt_cl_silent=false
exec AS_MESSAGE_LOG_FD>>config.log
{
echo
AS_BOX([Running $as_me.])
} >&AS_MESSAGE_LOG_FD
lt_cl_help="\
'$as_me' creates a local libtool stub from the current configuration,
for use in further configure time tests before the real libtool is
generated.
Usage: $[0] [[OPTIONS]]
-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
Report bugs to ."
lt_cl_version="\
m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
configured by $[0], generated by m4_PACKAGE_STRING.
Copyright (C) 2011 Free Software Foundation, Inc.
This config.lt script is free software; the Free Software Foundation
gives unlimited permision to copy, distribute and modify it."
while test 0 != $[#]
do
case $[1] in
--version | --v* | -V )
echo "$lt_cl_version"; exit 0 ;;
--help | --h* | -h )
echo "$lt_cl_help"; exit 0 ;;
--debug | --d* | -d )
debug=: ;;
--quiet | --q* | --silent | --s* | -q )
lt_cl_silent=: ;;
-*) AC_MSG_ERROR([unrecognized option: $[1]
Try '$[0] --help' for more information.]) ;;
*) AC_MSG_ERROR([unrecognized argument: $[1]
Try '$[0] --help' for more information.]) ;;
esac
shift
done
if $lt_cl_silent; then
exec AS_MESSAGE_FD>/dev/null
fi
_LTEOF
cat >>"$CONFIG_LT" <<_LTEOF
_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
_LTEOF
cat >>"$CONFIG_LT" <<\_LTEOF
AC_MSG_NOTICE([creating $ofile])
_LT_OUTPUT_LIBTOOL_COMMANDS
AS_EXIT(0)
_LTEOF
chmod +x "$CONFIG_LT"
# configure is writing to config.log, but config.lt does its own redirection,
# appending to config.log, which fails on DOS, as config.log is still kept
# open by configure. Here we exec the FD to /dev/null, effectively closing
# config.log, so it can be properly (re)opened and appended to by config.lt.
lt_cl_success=:
test yes = "$silent" &&
lt_config_lt_args="$lt_config_lt_args --quiet"
exec AS_MESSAGE_LOG_FD>/dev/null
$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
exec AS_MESSAGE_LOG_FD>>config.log
$lt_cl_success || AS_EXIT(1)
])# LT_OUTPUT
# _LT_CONFIG(TAG)
# ---------------
# If TAG is the built-in tag, create an initial libtool script with a
# default configuration from the untagged config vars. Otherwise add code
# to config.status for appending the configuration named by TAG from the
# matching tagged config vars.
m4_defun([_LT_CONFIG],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
_LT_CONFIG_SAVE_COMMANDS([
m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
m4_if(_LT_TAG, [C], [
# See if we are running on zsh, and set the options that allow our
# commands through without removal of \ escapes.
if test -n "${ZSH_VERSION+set}"; then
setopt NO_GLOB_SUBST
fi
cfgfile=${ofile}T
trap "$RM \"$cfgfile\"; exit 1" 1 2 15
$RM "$cfgfile"
cat <<_LT_EOF >> "$cfgfile"
#! $SHELL
# Generated automatically by $as_me ($PACKAGE) $VERSION
# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
# Provide generalized library-building support services.
# Written by Gordon Matzigkeit, 1996
_LT_COPYING
_LT_LIBTOOL_TAGS
# Configured defaults for sys_lib_dlsearch_path munging.
: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
# ### BEGIN LIBTOOL CONFIG
_LT_LIBTOOL_CONFIG_VARS
_LT_LIBTOOL_TAG_VARS
# ### END LIBTOOL CONFIG
_LT_EOF
cat <<'_LT_EOF' >> "$cfgfile"
# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
_LT_PREPARE_MUNGE_PATH_LIST
_LT_PREPARE_CC_BASENAME
# ### END FUNCTIONS SHARED WITH CONFIGURE
_LT_EOF
case $host_os in
aix3*)
cat <<\_LT_EOF >> "$cfgfile"
# AIX sometimes has problems with the GCC collect2 program. For some
# reason, if we set the COLLECT_NAMES environment variable, the problems
# vanish in a puff of smoke.
if test set != "${COLLECT_NAMES+set}"; then
COLLECT_NAMES=
export COLLECT_NAMES
fi
_LT_EOF
;;
esac
_LT_PROG_LTMAIN
# We use sed instead of cat because bash on DJGPP gets confused if
# if finds mixed CR/LF and LF-only lines. Since sed operates in
# text mode, it properly converts lines to CR/LF. This bash problem
# is reportedly fixed, but why not run on old versions too?
sed '$q' "$ltmain" >> "$cfgfile" \
|| (rm -f "$cfgfile"; exit 1)
mv -f "$cfgfile" "$ofile" ||
(rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
chmod +x "$ofile"
],
[cat <<_LT_EOF >> "$ofile"
dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
dnl in a comment (ie after a #).
# ### BEGIN LIBTOOL TAG CONFIG: $1
_LT_LIBTOOL_TAG_VARS(_LT_TAG)
# ### END LIBTOOL TAG CONFIG: $1
_LT_EOF
])dnl /m4_if
],
[m4_if([$1], [], [
PACKAGE='$PACKAGE'
VERSION='$VERSION'
RM='$RM'
ofile='$ofile'], [])
])dnl /_LT_CONFIG_SAVE_COMMANDS
])# _LT_CONFIG
# LT_SUPPORTED_TAG(TAG)
# ---------------------
# Trace this macro to discover what tags are supported by the libtool
# --tag option, using:
# autoconf --trace 'LT_SUPPORTED_TAG:$1'
AC_DEFUN([LT_SUPPORTED_TAG], [])
# C support is built-in for now
m4_define([_LT_LANG_C_enabled], [])
m4_define([_LT_TAGS], [])
# LT_LANG(LANG)
# -------------
# Enable libtool support for the given language if not already enabled.
AC_DEFUN([LT_LANG],
[AC_BEFORE([$0], [LT_OUTPUT])dnl
m4_case([$1],
[C], [_LT_LANG(C)],
[C++], [_LT_LANG(CXX)],
[Go], [_LT_LANG(GO)],
[Java], [_LT_LANG(GCJ)],
[Fortran 77], [_LT_LANG(F77)],
[Fortran], [_LT_LANG(FC)],
[Windows Resource], [_LT_LANG(RC)],
[m4_ifdef([_LT_LANG_]$1[_CONFIG],
[_LT_LANG($1)],
[m4_fatal([$0: unsupported language: "$1"])])])dnl
])# LT_LANG
# _LT_LANG(LANGNAME)
# ------------------
m4_defun([_LT_LANG],
[m4_ifdef([_LT_LANG_]$1[_enabled], [],
[LT_SUPPORTED_TAG([$1])dnl
m4_append([_LT_TAGS], [$1 ])dnl
m4_define([_LT_LANG_]$1[_enabled], [])dnl
_LT_LANG_$1_CONFIG($1)])dnl
])# _LT_LANG
m4_ifndef([AC_PROG_GO], [
# NOTE: This macro has been submitted for inclusion into #
# GNU Autoconf as AC_PROG_GO. When it is available in #
# a released version of Autoconf we should remove this #
# macro and use it instead. #
m4_defun([AC_PROG_GO],
[AC_LANG_PUSH(Go)dnl
AC_ARG_VAR([GOC], [Go compiler command])dnl
AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
_AC_ARG_VAR_LDFLAGS()dnl
AC_CHECK_TOOL(GOC, gccgo)
if test -z "$GOC"; then
if test -n "$ac_tool_prefix"; then
AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
fi
fi
if test -z "$GOC"; then
AC_CHECK_PROG(GOC, gccgo, gccgo, false)
fi
])#m4_defun
])#m4_ifndef
# _LT_LANG_DEFAULT_CONFIG
# -----------------------
m4_defun([_LT_LANG_DEFAULT_CONFIG],
[AC_PROVIDE_IFELSE([AC_PROG_CXX],
[LT_LANG(CXX)],
[m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
AC_PROVIDE_IFELSE([AC_PROG_F77],
[LT_LANG(F77)],
[m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
AC_PROVIDE_IFELSE([AC_PROG_FC],
[LT_LANG(FC)],
[m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
dnl pulling things in needlessly.
AC_PROVIDE_IFELSE([AC_PROG_GCJ],
[LT_LANG(GCJ)],
[AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
[LT_LANG(GCJ)],
[AC_PROVIDE_IFELSE([LT_PROG_GCJ],
[LT_LANG(GCJ)],
[m4_ifdef([AC_PROG_GCJ],
[m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
m4_ifdef([A][M_PROG_GCJ],
[m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
m4_ifdef([LT_PROG_GCJ],
[m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
AC_PROVIDE_IFELSE([AC_PROG_GO],
[LT_LANG(GO)],
[m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
AC_PROVIDE_IFELSE([LT_PROG_RC],
[LT_LANG(RC)],
[m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
])# _LT_LANG_DEFAULT_CONFIG
# Obsolete macros:
AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
dnl AC_DEFUN([AC_LIBTOOL_F77], [])
dnl AC_DEFUN([AC_LIBTOOL_FC], [])
dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
dnl AC_DEFUN([AC_LIBTOOL_RC], [])
# _LT_TAG_COMPILER
# ----------------
m4_defun([_LT_TAG_COMPILER],
[AC_REQUIRE([AC_PROG_CC])dnl
_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
# If no C compiler was specified, use CC.
LTCC=${LTCC-"$CC"}
# If no C compiler flags were specified, use CFLAGS.
LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
# Allow CC to be a program name with arguments.
compiler=$CC
])# _LT_TAG_COMPILER
# _LT_COMPILER_BOILERPLATE
# ------------------------
# Check for compiler boilerplate output or warnings with
# the simple compiler test code.
m4_defun([_LT_COMPILER_BOILERPLATE],
[m4_require([_LT_DECL_SED])dnl
ac_outfile=conftest.$ac_objext
echo "$lt_simple_compile_test_code" >conftest.$ac_ext
eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
_lt_compiler_boilerplate=`cat conftest.err`
$RM conftest*
])# _LT_COMPILER_BOILERPLATE
# _LT_LINKER_BOILERPLATE
# ----------------------
# Check for linker boilerplate output or warnings with
# the simple link test code.
m4_defun([_LT_LINKER_BOILERPLATE],
[m4_require([_LT_DECL_SED])dnl
ac_outfile=conftest.$ac_objext
echo "$lt_simple_link_test_code" >conftest.$ac_ext
eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
_lt_linker_boilerplate=`cat conftest.err`
$RM -r conftest*
])# _LT_LINKER_BOILERPLATE
# _LT_REQUIRED_DARWIN_CHECKS
# -------------------------
m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
case $host_os in
rhapsody* | darwin*)
AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
AC_CHECK_TOOL([LIPO], [lipo], [:])
AC_CHECK_TOOL([OTOOL], [otool], [:])
AC_CHECK_TOOL([OTOOL64], [otool64], [:])
_LT_DECL([], [DSYMUTIL], [1],
[Tool to manipulate archived DWARF debug symbol files on Mac OS X])
_LT_DECL([], [NMEDIT], [1],
[Tool to change global to local symbols on Mac OS X])
_LT_DECL([], [LIPO], [1],
[Tool to manipulate fat objects and archives on Mac OS X])
_LT_DECL([], [OTOOL], [1],
[ldd/readelf like tool for Mach-O binaries on Mac OS X])
_LT_DECL([], [OTOOL64], [1],
[ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
[lt_cv_apple_cc_single_mod=no
if test -z "$LT_MULTI_MODULE"; then
# By default we will add the -single_module flag. You can override
# by either setting the environment variable LT_MULTI_MODULE
# non-empty at configure time, or by adding -multi_module to the
# link flags.
rm -rf libconftest.dylib*
echo "int foo(void){return 1;}" > conftest.c
echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
-dynamiclib -Wl,-single_module conftest.c 2>conftest.err
_lt_result=$?
# If there is a non-empty error log, and "single_module"
# appears in it, assume the flag caused a linker warning
if test -s conftest.err && $GREP single_module conftest.err; then
cat conftest.err >&AS_MESSAGE_LOG_FD
# Otherwise, if the output was created with a 0 exit code from
# the compiler, it worked.
elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
lt_cv_apple_cc_single_mod=yes
else
cat conftest.err >&AS_MESSAGE_LOG_FD
fi
rm -rf libconftest.dylib*
rm -f conftest.*
fi])
AC_CACHE_CHECK([for -exported_symbols_list linker flag],
[lt_cv_ld_exported_symbols_list],
[lt_cv_ld_exported_symbols_list=no
save_LDFLAGS=$LDFLAGS
echo "_main" > conftest.sym
LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
[lt_cv_ld_exported_symbols_list=yes],
[lt_cv_ld_exported_symbols_list=no])
LDFLAGS=$save_LDFLAGS
])
AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
[lt_cv_ld_force_load=no
cat > conftest.c << _LT_EOF
int forced_loaded() { return 2;}
_LT_EOF
echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
$LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
$AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
$RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
cat > conftest.c << _LT_EOF
int main() { return 0;}
_LT_EOF
echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
_lt_result=$?
if test -s conftest.err && $GREP force_load conftest.err; then
cat conftest.err >&AS_MESSAGE_LOG_FD
elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
lt_cv_ld_force_load=yes
else
cat conftest.err >&AS_MESSAGE_LOG_FD
fi
rm -f conftest.err libconftest.a conftest conftest.c
rm -rf conftest.dSYM
])
case $host_os in
rhapsody* | darwin1.[[012]])
_lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
darwin1.*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
darwin*) # darwin 5.x on
# if running on 10.5 or later, the deployment target defaults
# to the OS version, if on x86, and 10.4, the deployment
# target defaults to 10.4. Don't you love it?
case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
10.[[012]][[,.]]*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
10.*)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
esac
;;
esac
if test yes = "$lt_cv_apple_cc_single_mod"; then
_lt_dar_single_mod='$single_module'
fi
if test yes = "$lt_cv_ld_exported_symbols_list"; then
_lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
else
_lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
fi
if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
_lt_dsymutil='~$DSYMUTIL $lib || :'
else
_lt_dsymutil=
fi
;;
esac
])
# _LT_DARWIN_LINKER_FEATURES([TAG])
# ---------------------------------
# Checks for linker and compiler features on darwin
m4_defun([_LT_DARWIN_LINKER_FEATURES],
[
m4_require([_LT_REQUIRED_DARWIN_CHECKS])
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_automatic, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
if test yes = "$lt_cv_ld_force_load"; then
_LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
[FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes])
else
_LT_TAGVAR(whole_archive_flag_spec, $1)=''
fi
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined
case $cc_basename in
ifort*|nagfor*) _lt_dar_can_shared=yes ;;
*) _lt_dar_can_shared=$GCC ;;
esac
if test yes = "$_lt_dar_can_shared"; then
output_verbose_link_cmd=func_echo_all
_LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
_LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
_LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
_LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
m4_if([$1], [CXX],
[ if test yes != "$lt_cv_apple_cc_single_mod"; then
_LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
_LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
fi
],[])
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
])
# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
# ----------------------------------
# Links a minimal program and checks the executable
# for the system default hardcoded library path. In most cases,
# this is /usr/lib:/lib, but when the MPI compilers are used
# the location of the communication and MPI libs are included too.
# If we don't find anything, use the default library path according
# to the aix ld manual.
# Store the results from the different compilers for each TAGNAME.
# Allow to override them for all tags through lt_cv_aix_libpath.
m4_defun([_LT_SYS_MODULE_PATH_AIX],
[m4_require([_LT_DECL_SED])dnl
if test set = "${lt_cv_aix_libpath+set}"; then
aix_libpath=$lt_cv_aix_libpath
else
AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
[AC_LINK_IFELSE([AC_LANG_PROGRAM],[
lt_aix_libpath_sed='[
/Import File Strings/,/^$/ {
/^0/ {
s/^0 *\([^ ]*\) *$/\1/
p
}
}]'
_LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
# Check for a 64-bit object if we didn't find anything.
if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
_LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
fi],[])
if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
_LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib
fi
])
aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
fi
])# _LT_SYS_MODULE_PATH_AIX
# _LT_SHELL_INIT(ARG)
# -------------------
m4_define([_LT_SHELL_INIT],
[m4_divert_text([M4SH-INIT], [$1
])])# _LT_SHELL_INIT
# _LT_PROG_ECHO_BACKSLASH
# -----------------------
# Find how we can fake an echo command that does not interpret backslash.
# In particular, with Autoconf 2.60 or later we add some code to the start
# of the generated configure script that will find a shell with a builtin
# printf (that we can use as an echo command).
m4_defun([_LT_PROG_ECHO_BACKSLASH],
[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
AC_MSG_CHECKING([how to print strings])
# Test print first, because it will be a builtin if present.
if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
ECHO='print -r --'
elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
ECHO='printf %s\n'
else
# Use this function as a fallback that always works.
func_fallback_echo ()
{
eval 'cat <<_LTECHO_EOF
$[]1
_LTECHO_EOF'
}
ECHO='func_fallback_echo'
fi
# func_echo_all arg...
# Invoke $ECHO with all args, space-separated.
func_echo_all ()
{
$ECHO "$*"
}
case $ECHO in
printf*) AC_MSG_RESULT([printf]) ;;
print*) AC_MSG_RESULT([print -r]) ;;
*) AC_MSG_RESULT([cat]) ;;
esac
m4_ifdef([_AS_DETECT_SUGGESTED],
[_AS_DETECT_SUGGESTED([
test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
PATH=/empty FPATH=/empty; export PATH FPATH
test "X`printf %s $ECHO`" = "X$ECHO" \
|| test "X`print -r -- $ECHO`" = "X$ECHO" )])])
_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
])# _LT_PROG_ECHO_BACKSLASH
# _LT_WITH_SYSROOT
# ----------------
AC_DEFUN([_LT_WITH_SYSROOT],
[AC_MSG_CHECKING([for sysroot])
AC_ARG_WITH([sysroot],
[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
[Search for dependent libraries within DIR (or the compiler's sysroot
if not specified).])],
[], [with_sysroot=no])
dnl lt_sysroot will always be passed unquoted. We quote it here
dnl in case the user passed a directory name.
lt_sysroot=
case $with_sysroot in #(
yes)
if test yes = "$GCC"; then
lt_sysroot=`$CC --print-sysroot 2>/dev/null`
fi
;; #(
/*)
lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
;; #(
no|'')
;; #(
*)
AC_MSG_RESULT([$with_sysroot])
AC_MSG_ERROR([The sysroot must be an absolute path.])
;;
esac
AC_MSG_RESULT([${lt_sysroot:-no}])
_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
[dependent libraries, and where our libraries should be installed.])])
# _LT_ENABLE_LOCK
# ---------------
m4_defun([_LT_ENABLE_LOCK],
[AC_ARG_ENABLE([libtool-lock],
[AS_HELP_STRING([--disable-libtool-lock],
[avoid locking (might break parallel builds)])])
test no = "$enable_libtool_lock" || enable_libtool_lock=yes
# Some flags need to be propagated to the compiler or linker for good
# libtool support.
case $host in
ia64-*-hpux*)
# Find out what ABI is being produced by ac_compile, and set mode
# options accordingly.
echo 'int i;' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
case `/usr/bin/file conftest.$ac_objext` in
*ELF-32*)
HPUX_IA64_MODE=32
;;
*ELF-64*)
HPUX_IA64_MODE=64
;;
esac
fi
rm -rf conftest*
;;
*-*-irix6*)
# Find out what ABI is being produced by ac_compile, and set linker
# options accordingly.
echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
if test yes = "$lt_cv_prog_gnu_ld"; then
case `/usr/bin/file conftest.$ac_objext` in
*32-bit*)
LD="${LD-ld} -melf32bsmip"
;;
*N32*)
LD="${LD-ld} -melf32bmipn32"
;;
*64-bit*)
LD="${LD-ld} -melf64bmip"
;;
esac
else
case `/usr/bin/file conftest.$ac_objext` in
*32-bit*)
LD="${LD-ld} -32"
;;
*N32*)
LD="${LD-ld} -n32"
;;
*64-bit*)
LD="${LD-ld} -64"
;;
esac
fi
fi
rm -rf conftest*
;;
mips64*-*linux*)
# Find out what ABI is being produced by ac_compile, and set linker
# options accordingly.
echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
emul=elf
case `/usr/bin/file conftest.$ac_objext` in
*32-bit*)
emul="${emul}32"
;;
*64-bit*)
emul="${emul}64"
;;
esac
case `/usr/bin/file conftest.$ac_objext` in
*MSB*)
emul="${emul}btsmip"
;;
*LSB*)
emul="${emul}ltsmip"
;;
esac
case `/usr/bin/file conftest.$ac_objext` in
*N32*)
emul="${emul}n32"
;;
esac
LD="${LD-ld} -m $emul"
fi
rm -rf conftest*
;;
x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
# Find out what ABI is being produced by ac_compile, and set linker
# options accordingly. Note that the listed cases only cover the
# situations where additional linker options are needed (such as when
# doing 32-bit compilation for a host where ld defaults to 64-bit, or
# vice versa); the common cases where no linker options are needed do
# not appear in the list.
echo 'int i;' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
case `/usr/bin/file conftest.o` in
*32-bit*)
case $host in
x86_64-*kfreebsd*-gnu)
LD="${LD-ld} -m elf_i386_fbsd"
;;
x86_64-*linux*)
case `/usr/bin/file conftest.o` in
*x86-64*)
LD="${LD-ld} -m elf32_x86_64"
;;
*)
LD="${LD-ld} -m elf_i386"
;;
esac
;;
powerpc64le-*linux*)
LD="${LD-ld} -m elf32lppclinux"
;;
powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
LD="${LD-ld} -m elf_s390"
;;
sparc64-*linux*)
LD="${LD-ld} -m elf32_sparc"
;;
esac
;;
*64-bit*)
case $host in
x86_64-*kfreebsd*-gnu)
LD="${LD-ld} -m elf_x86_64_fbsd"
;;
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
powerpcle-*linux*)
LD="${LD-ld} -m elf64lppc"
;;
powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
LD="${LD-ld} -m elf64_s390"
;;
sparc*-*linux*)
LD="${LD-ld} -m elf64_sparc"
;;
esac
;;
esac
fi
rm -rf conftest*
;;
*-*-sco3.2v5*)
# On SCO OpenServer 5, we need -belf to get full-featured binaries.
SAVE_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS -belf"
AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
[AC_LANG_PUSH(C)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
AC_LANG_POP])
if test yes != "$lt_cv_cc_needs_belf"; then
# this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
CFLAGS=$SAVE_CFLAGS
fi
;;
*-*solaris*)
# Find out what ABI is being produced by ac_compile, and set linker
# options accordingly.
echo 'int i;' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
case `/usr/bin/file conftest.o` in
*64-bit*)
case $lt_cv_prog_gnu_ld in
yes*)
case $host in
i?86-*-solaris*|x86_64-*-solaris*)
LD="${LD-ld} -m elf_x86_64"
;;
sparc*-*-solaris*)
LD="${LD-ld} -m elf64_sparc"
;;
esac
# GNU ld 2.21 introduced _sol2 emulations. Use them if available.
if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
LD=${LD-ld}_sol2
fi
;;
*)
if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
LD="${LD-ld} -64"
fi
;;
esac
;;
esac
fi
rm -rf conftest*
;;
esac
need_locks=$enable_libtool_lock
])# _LT_ENABLE_LOCK
# _LT_PROG_AR
# -----------
m4_defun([_LT_PROG_AR],
[AC_CHECK_TOOLS(AR, [ar], false)
: ${AR=ar}
: ${AR_FLAGS=cru}
_LT_DECL([], [AR], [1], [The archiver])
_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])
AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
[lt_cv_ar_at_file=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
[echo conftest.$ac_objext > conftest.lst
lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
AC_TRY_EVAL([lt_ar_try])
if test 0 -eq "$ac_status"; then
# Ensure the archiver fails upon bogus file names.
rm -f conftest.$ac_objext libconftest.a
AC_TRY_EVAL([lt_ar_try])
if test 0 -ne "$ac_status"; then
lt_cv_ar_at_file=@
fi
fi
rm -f conftest.* libconftest.a
])
])
if test no = "$lt_cv_ar_at_file"; then
archiver_list_spec=
else
archiver_list_spec=$lt_cv_ar_at_file
fi
_LT_DECL([], [archiver_list_spec], [1],
[How to feed a file listing to the archiver])
])# _LT_PROG_AR
# _LT_CMD_OLD_ARCHIVE
# -------------------
m4_defun([_LT_CMD_OLD_ARCHIVE],
[_LT_PROG_AR
AC_CHECK_TOOL(STRIP, strip, :)
test -z "$STRIP" && STRIP=:
_LT_DECL([], [STRIP], [1], [A symbol stripping program])
AC_CHECK_TOOL(RANLIB, ranlib, :)
test -z "$RANLIB" && RANLIB=:
_LT_DECL([], [RANLIB], [1],
[Commands used to install an old-style archive])
# Determine commands to create old-style static archives.
old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
old_postinstall_cmds='chmod 644 $oldlib'
old_postuninstall_cmds=
if test -n "$RANLIB"; then
case $host_os in
bitrig* | openbsd*)
old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
;;
*)
old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
;;
esac
old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
fi
case $host_os in
darwin*)
lock_old_archive_extraction=yes ;;
*)
lock_old_archive_extraction=no ;;
esac
_LT_DECL([], [old_postinstall_cmds], [2])
_LT_DECL([], [old_postuninstall_cmds], [2])
_LT_TAGDECL([], [old_archive_cmds], [2],
[Commands used to build an old-style archive])
_LT_DECL([], [lock_old_archive_extraction], [0],
[Whether to use a lock for old archive extraction])
])# _LT_CMD_OLD_ARCHIVE
# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
# ----------------------------------------------------------------
# Check whether the given compiler option works
AC_DEFUN([_LT_COMPILER_OPTION],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_SED])dnl
AC_CACHE_CHECK([$1], [$2],
[$2=no
m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment
# Insert the option either (1) after the last *FLAGS variable, or
# (2) before a word containing "conftest.", or (3) at the end.
# Note that $ac_compile itself does not contain backslashes and begins
# with a dollar sign (not a hyphen), so the echo should work correctly.
# The option is referenced via a variable to avoid confusing sed.
lt_compile=`echo "$ac_compile" | $SED \
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&AS_MESSAGE_LOG_FD
echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
$ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
$SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
$2=yes
fi
fi
$RM conftest*
])
if test yes = "[$]$2"; then
m4_if([$5], , :, [$5])
else
m4_if([$6], , :, [$6])
fi
])# _LT_COMPILER_OPTION
# Old name:
AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
# [ACTION-SUCCESS], [ACTION-FAILURE])
# ----------------------------------------------------
# Check whether the given linker option works
AC_DEFUN([_LT_LINKER_OPTION],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_SED])dnl
AC_CACHE_CHECK([$1], [$2],
[$2=no
save_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS $3"
echo "$lt_simple_link_test_code" > conftest.$ac_ext
if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
# The linker can only warn and ignore the option if not recognized
# So say no if there are warnings
if test -s conftest.err; then
# Append any errors to the config.log.
cat conftest.err 1>&AS_MESSAGE_LOG_FD
$ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
$SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
if diff conftest.exp conftest.er2 >/dev/null; then
$2=yes
fi
else
$2=yes
fi
fi
$RM -r conftest*
LDFLAGS=$save_LDFLAGS
])
if test yes = "[$]$2"; then
m4_if([$4], , :, [$4])
else
m4_if([$5], , :, [$5])
fi
])# _LT_LINKER_OPTION
# Old name:
AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
# LT_CMD_MAX_LEN
#---------------
AC_DEFUN([LT_CMD_MAX_LEN],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
# find the maximum length of command line arguments
AC_MSG_CHECKING([the maximum length of command line arguments])
AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
i=0
teststring=ABCD
case $build_os in
msdosdjgpp*)
# On DJGPP, this test can blow up pretty badly due to problems in libc
# (any single argument exceeding 2000 bytes causes a buffer overrun
# during glob expansion). Even if it were fixed, the result of this
# check would be larger than it should be.
lt_cv_sys_max_cmd_len=12288; # 12K is about right
;;
gnu*)
# Under GNU Hurd, this test is not required because there is
# no limit to the length of command line arguments.
# Libtool will interpret -1 as no limit whatsoever
lt_cv_sys_max_cmd_len=-1;
;;
cygwin* | mingw* | cegcc*)
# On Win9x/ME, this test blows up -- it succeeds, but takes
# about 5 minutes as the teststring grows exponentially.
# Worse, since 9x/ME are not pre-emptively multitasking,
# you end up with a "frozen" computer, even though with patience
# the test eventually succeeds (with a max line length of 256k).
# Instead, let's just punt: use the minimum linelength reported by
# all of the supported platforms: 8192 (on NT/2K/XP).
lt_cv_sys_max_cmd_len=8192;
;;
mint*)
# On MiNT this can take a long time and run out of memory.
lt_cv_sys_max_cmd_len=8192;
;;
amigaos*)
# On AmigaOS with pdksh, this test takes hours, literally.
# So we just punt and use a minimum line length of 8192.
lt_cv_sys_max_cmd_len=8192;
;;
bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
# This has been around since 386BSD, at least. Likely further.
if test -x /sbin/sysctl; then
lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
elif test -x /usr/sbin/sysctl; then
lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
else
lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
fi
# And add a safety zone
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
;;
interix*)
# We know the value 262144 and hardcode it with a safety zone (like BSD)
lt_cv_sys_max_cmd_len=196608
;;
os2*)
# The test takes a long time on OS/2.
lt_cv_sys_max_cmd_len=8192
;;
osf*)
# Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
# due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
# nice to cause kernel panics so lets avoid the loop below.
# First set a reasonable default.
lt_cv_sys_max_cmd_len=16384
#
if test -x /sbin/sysconfig; then
case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
*1*) lt_cv_sys_max_cmd_len=-1 ;;
esac
fi
;;
sco3.2v5*)
lt_cv_sys_max_cmd_len=102400
;;
sysv5* | sco5v6* | sysv4.2uw2*)
kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
if test -n "$kargmax"; then
lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
else
lt_cv_sys_max_cmd_len=32768
fi
;;
*)
lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
if test -n "$lt_cv_sys_max_cmd_len" && \
test undefined != "$lt_cv_sys_max_cmd_len"; then
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
else
# Make teststring a little bigger before we do anything with it.
# a 1K string should be a reasonable start.
for i in 1 2 3 4 5 6 7 8; do
teststring=$teststring$teststring
done
SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
# If test is not a shell built-in, we'll probably end up computing a
# maximum length that is only half of the actual maximum length, but
# we can't tell.
while { test X`env echo "$teststring$teststring" 2>/dev/null` \
= "X$teststring$teststring"; } >/dev/null 2>&1 &&
test 17 != "$i" # 1/2 MB should be enough
do
i=`expr $i + 1`
teststring=$teststring$teststring
done
# Only check the string length outside the loop.
lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
teststring=
# Add a significant safety factor because C++ compilers can tack on
# massive amounts of additional arguments before passing them to the
# linker. It appears as though 1/2 is a usable value.
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
fi
;;
esac
])
if test -n "$lt_cv_sys_max_cmd_len"; then
AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
else
AC_MSG_RESULT(none)
fi
max_cmd_len=$lt_cv_sys_max_cmd_len
_LT_DECL([], [max_cmd_len], [0],
[What is the maximum length of a command?])
])# LT_CMD_MAX_LEN
# Old name:
AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
# _LT_HEADER_DLFCN
# ----------------
m4_defun([_LT_HEADER_DLFCN],
[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
])# _LT_HEADER_DLFCN
# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
# ----------------------------------------------------------------
m4_defun([_LT_TRY_DLOPEN_SELF],
[m4_require([_LT_HEADER_DLFCN])dnl
if test yes = "$cross_compiling"; then :
[$4]
else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
[#line $LINENO "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
#include
#endif
#include
#ifdef RTLD_GLOBAL
# define LT_DLGLOBAL RTLD_GLOBAL
#else
# ifdef DL_GLOBAL
# define LT_DLGLOBAL DL_GLOBAL
# else
# define LT_DLGLOBAL 0
# endif
#endif
/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
find out it does not work in some platform. */
#ifndef LT_DLLAZY_OR_NOW
# ifdef RTLD_LAZY
# define LT_DLLAZY_OR_NOW RTLD_LAZY
# else
# ifdef DL_LAZY
# define LT_DLLAZY_OR_NOW DL_LAZY
# else
# ifdef RTLD_NOW
# define LT_DLLAZY_OR_NOW RTLD_NOW
# else
# ifdef DL_NOW
# define LT_DLLAZY_OR_NOW DL_NOW
# else
# define LT_DLLAZY_OR_NOW 0
# endif
# endif
# endif
# endif
#endif
/* When -fvisibility=hidden is used, assume the code has been annotated
correspondingly for the symbols needed. */
#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
int fnord () __attribute__((visibility("default")));
#endif
int fnord () { return 42; }
int main ()
{
void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
int status = $lt_dlunknown;
if (self)
{
if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
else
{
if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
else puts (dlerror ());
}
/* dlclose (self); */
}
else
puts (dlerror ());
return status;
}]
_LT_EOF
if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then
(./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
lt_status=$?
case x$lt_status in
x$lt_dlno_uscore) $1 ;;
x$lt_dlneed_uscore) $2 ;;
x$lt_dlunknown|x*) $3 ;;
esac
else :
# compilation failed
$3
fi
fi
rm -fr conftest*
])# _LT_TRY_DLOPEN_SELF
# LT_SYS_DLOPEN_SELF
# ------------------
AC_DEFUN([LT_SYS_DLOPEN_SELF],
[m4_require([_LT_HEADER_DLFCN])dnl
if test yes != "$enable_dlopen"; then
enable_dlopen=unknown
enable_dlopen_self=unknown
enable_dlopen_self_static=unknown
else
lt_cv_dlopen=no
lt_cv_dlopen_libs=
case $host_os in
beos*)
lt_cv_dlopen=load_add_on
lt_cv_dlopen_libs=
lt_cv_dlopen_self=yes
;;
mingw* | pw32* | cegcc*)
lt_cv_dlopen=LoadLibrary
lt_cv_dlopen_libs=
;;
cygwin*)
lt_cv_dlopen=dlopen
lt_cv_dlopen_libs=
;;
darwin*)
# if libdl is installed we need to link against it
AC_CHECK_LIB([dl], [dlopen],
[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[
lt_cv_dlopen=dyld
lt_cv_dlopen_libs=
lt_cv_dlopen_self=yes
])
;;
tpf*)
# Don't try to run any link tests for TPF. We know it's impossible
# because TPF is a cross-compiler, and we know how we open DSOs.
lt_cv_dlopen=dlopen
lt_cv_dlopen_libs=
lt_cv_dlopen_self=no
;;
*)
AC_CHECK_FUNC([shl_load],
[lt_cv_dlopen=shl_load],
[AC_CHECK_LIB([dld], [shl_load],
[lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld],
[AC_CHECK_FUNC([dlopen],
[lt_cv_dlopen=dlopen],
[AC_CHECK_LIB([dl], [dlopen],
[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],
[AC_CHECK_LIB([svld], [dlopen],
[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld],
[AC_CHECK_LIB([dld], [dld_link],
[lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld])
])
])
])
])
])
;;
esac
if test no = "$lt_cv_dlopen"; then
enable_dlopen=no
else
enable_dlopen=yes
fi
case $lt_cv_dlopen in
dlopen)
save_CPPFLAGS=$CPPFLAGS
test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
save_LDFLAGS=$LDFLAGS
wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
save_LIBS=$LIBS
LIBS="$lt_cv_dlopen_libs $LIBS"
AC_CACHE_CHECK([whether a program can dlopen itself],
lt_cv_dlopen_self, [dnl
_LT_TRY_DLOPEN_SELF(
lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
])
if test yes = "$lt_cv_dlopen_self"; then
wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
lt_cv_dlopen_self_static, [dnl
_LT_TRY_DLOPEN_SELF(
lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
])
fi
CPPFLAGS=$save_CPPFLAGS
LDFLAGS=$save_LDFLAGS
LIBS=$save_LIBS
;;
esac
case $lt_cv_dlopen_self in
yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
*) enable_dlopen_self=unknown ;;
esac
case $lt_cv_dlopen_self_static in
yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
*) enable_dlopen_self_static=unknown ;;
esac
fi
_LT_DECL([dlopen_support], [enable_dlopen], [0],
[Whether dlopen is supported])
_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
[Whether dlopen of programs is supported])
_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
[Whether dlopen of statically linked programs is supported])
])# LT_SYS_DLOPEN_SELF
# Old name:
AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
# _LT_COMPILER_C_O([TAGNAME])
# ---------------------------
# Check to see if options -c and -o are simultaneously supported by compiler.
# This macro does not hard code the compiler like AC_PROG_CC_C_O.
m4_defun([_LT_COMPILER_C_O],
[m4_require([_LT_DECL_SED])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_TAG_COMPILER])dnl
AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
[_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
[_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
$RM -r conftest 2>/dev/null
mkdir conftest
cd conftest
mkdir out
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
lt_compiler_flag="-o out/conftest2.$ac_objext"
# Insert the option either (1) after the last *FLAGS variable, or
# (2) before a word containing "conftest.", or (3) at the end.
# Note that $ac_compile itself does not contain backslashes and begins
# with a dollar sign (not a hyphen), so the echo should work correctly.
lt_compile=`echo "$ac_compile" | $SED \
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&AS_MESSAGE_LOG_FD
echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
$ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
$SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
fi
fi
chmod u+w . 2>&AS_MESSAGE_LOG_FD
$RM conftest*
# SGI C++ compiler will create directory out/ii_files/ for
# template instantiation
test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
$RM out/* && rmdir out
cd ..
$RM -r conftest
$RM conftest*
])
_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
[Does compiler simultaneously support -c and -o options?])
])# _LT_COMPILER_C_O
# _LT_COMPILER_FILE_LOCKS([TAGNAME])
# ----------------------------------
# Check to see if we can do hard links to lock some files if needed
m4_defun([_LT_COMPILER_FILE_LOCKS],
[m4_require([_LT_ENABLE_LOCK])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
_LT_COMPILER_C_O([$1])
hard_links=nottested
if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then
# do not overwrite the value of need_locks provided by the user
AC_MSG_CHECKING([if we can lock with hard links])
hard_links=yes
$RM conftest*
ln conftest.a conftest.b 2>/dev/null && hard_links=no
touch conftest.a
ln conftest.a conftest.b 2>&5 || hard_links=no
ln conftest.a conftest.b 2>/dev/null && hard_links=no
AC_MSG_RESULT([$hard_links])
if test no = "$hard_links"; then
AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe])
need_locks=warn
fi
else
need_locks=no
fi
_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
])# _LT_COMPILER_FILE_LOCKS
# _LT_CHECK_OBJDIR
# ----------------
m4_defun([_LT_CHECK_OBJDIR],
[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
[rm -f .libs 2>/dev/null
mkdir .libs 2>/dev/null
if test -d .libs; then
lt_cv_objdir=.libs
else
# MS-DOS does not allow filenames that begin with a dot.
lt_cv_objdir=_libs
fi
rmdir .libs 2>/dev/null])
objdir=$lt_cv_objdir
_LT_DECL([], [objdir], [0],
[The name of the directory that contains temporary libtool files])dnl
m4_pattern_allow([LT_OBJDIR])dnl
AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/",
[Define to the sub-directory where libtool stores uninstalled libraries.])
])# _LT_CHECK_OBJDIR
# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
# --------------------------------------
# Check hardcoding attributes.
m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
[AC_MSG_CHECKING([how to hardcode library paths into programs])
_LT_TAGVAR(hardcode_action, $1)=
if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
test -n "$_LT_TAGVAR(runpath_var, $1)" ||
test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then
# We can hardcode non-existent directories.
if test no != "$_LT_TAGVAR(hardcode_direct, $1)" &&
# If the only mechanism to avoid hardcoding is shlibpath_var, we
# have to relink, otherwise we might link with an installed library
# when we should be linking with a yet-to-be-installed one
## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" &&
test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then
# Linking always hardcodes the temporary library directory.
_LT_TAGVAR(hardcode_action, $1)=relink
else
# We can link without hardcoding, and we can hardcode nonexisting dirs.
_LT_TAGVAR(hardcode_action, $1)=immediate
fi
else
# We cannot hardcode anything, or else we can only hardcode existing
# directories.
_LT_TAGVAR(hardcode_action, $1)=unsupported
fi
AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
if test relink = "$_LT_TAGVAR(hardcode_action, $1)" ||
test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then
# Fast installation is not supported
enable_fast_install=no
elif test yes = "$shlibpath_overrides_runpath" ||
test no = "$enable_shared"; then
# Fast installation is not necessary
enable_fast_install=needless
fi
_LT_TAGDECL([], [hardcode_action], [0],
[How to hardcode a shared library path into an executable])
])# _LT_LINKER_HARDCODE_LIBPATH
# _LT_CMD_STRIPLIB
# ----------------
m4_defun([_LT_CMD_STRIPLIB],
[m4_require([_LT_DECL_EGREP])
striplib=
old_striplib=
AC_MSG_CHECKING([whether stripping libraries is possible])
if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
test -z "$striplib" && striplib="$STRIP --strip-unneeded"
AC_MSG_RESULT([yes])
else
# FIXME - insert some real tests, host_os isn't really good enough
case $host_os in
darwin*)
if test -n "$STRIP"; then
striplib="$STRIP -x"
old_striplib="$STRIP -S"
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
;;
*)
AC_MSG_RESULT([no])
;;
esac
fi
_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
_LT_DECL([], [striplib], [1])
])# _LT_CMD_STRIPLIB
# _LT_PREPARE_MUNGE_PATH_LIST
# ---------------------------
# Make sure func_munge_path_list() is defined correctly.
m4_defun([_LT_PREPARE_MUNGE_PATH_LIST],
[[# func_munge_path_list VARIABLE PATH
# -----------------------------------
# VARIABLE is name of variable containing _space_ separated list of
# directories to be munged by the contents of PATH, which is string
# having a format:
# "DIR[:DIR]:"
# string "DIR[ DIR]" will be prepended to VARIABLE
# ":DIR[:DIR]"
# string "DIR[ DIR]" will be appended to VARIABLE
# "DIRP[:DIRP]::[DIRA:]DIRA"
# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
# "DIRA[ DIRA]" will be appended to VARIABLE
# "DIR[:DIR]"
# VARIABLE will be replaced by "DIR[ DIR]"
func_munge_path_list ()
{
case x@S|@2 in
x)
;;
*:)
eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\"
;;
x:*)
eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\"
;;
*::*)
eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\"
;;
*)
eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\"
;;
esac
}
]])# _LT_PREPARE_PATH_LIST
# _LT_SYS_DYNAMIC_LINKER([TAG])
# -----------------------------
# PORTME Fill in your ld.so characteristics
m4_defun([_LT_SYS_DYNAMIC_LINKER],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_OBJDUMP])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_CHECK_SHELL_FEATURES])dnl
m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl
AC_MSG_CHECKING([dynamic linker characteristics])
m4_if([$1],
[], [
if test yes = "$GCC"; then
case $host_os in
darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
*) lt_awk_arg='/^libraries:/' ;;
esac
case $host_os in
mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;;
*) lt_sed_strip_eq='s|=/|/|g' ;;
esac
lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
case $lt_search_path_spec in
*\;*)
# if the path contains ";" then we assume it to be the separator
# otherwise default to the standard path separator (i.e. ":") - it is
# assumed that no part of a normal pathname contains ";" but that should
# okay in the real world where ";" in dirpaths is itself problematic.
lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
;;
*)
lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
;;
esac
# Ok, now we have the path, separated by spaces, we can step through it
# and add multilib dir if necessary...
lt_tmp_lt_search_path_spec=
lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
# ...but if some path component already ends with the multilib dir we assume
# that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
case "$lt_multi_os_dir; $lt_search_path_spec " in
"/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
lt_multi_os_dir=
;;
esac
for lt_sys_path in $lt_search_path_spec; do
if test -d "$lt_sys_path$lt_multi_os_dir"; then
lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
elif test -n "$lt_multi_os_dir"; then
test -d "$lt_sys_path" && \
lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
fi
done
lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
BEGIN {RS = " "; FS = "/|\n";} {
lt_foo = "";
lt_count = 0;
for (lt_i = NF; lt_i > 0; lt_i--) {
if ($lt_i != "" && $lt_i != ".") {
if ($lt_i == "..") {
lt_count++;
} else {
if (lt_count == 0) {
lt_foo = "/" $lt_i lt_foo;
} else {
lt_count--;
}
}
}
}
if (lt_foo != "") { lt_freq[[lt_foo]]++; }
if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
}'`
# AWK program above erroneously prepends '/' to C:/dos/paths
# for these hosts.
case $host_os in
mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
$SED 's|/\([[A-Za-z]]:\)|\1|g'` ;;
esac
sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
else
sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
fi])
library_names_spec=
libname_spec='lib$name'
soname_spec=
shrext_cmds=.so
postinstall_cmds=
postuninstall_cmds=
finish_cmds=
finish_eval=
shlibpath_var=
shlibpath_overrides_runpath=unknown
version_type=none
dynamic_linker="$host_os ld.so"
sys_lib_dlsearch_path_spec="/lib /usr/lib"
need_lib_prefix=unknown
hardcode_into_libs=no
# when you set need_version to no, make sure it does not cause -set_version
# flags to be left without arguments
need_version=unknown
AC_ARG_VAR([LT_SYS_LIBRARY_PATH],
[User-defined run-time library search path.])
case $host_os in
aix3*)
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
shlibpath_var=LIBPATH
# AIX 3 has no versioning support, so we append a major version to the name.
soname_spec='$libname$release$shared_ext$major'
;;
aix[[4-9]]*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
hardcode_into_libs=yes
if test ia64 = "$host_cpu"; then
# AIX 5 supports IA64
library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
shlibpath_var=LD_LIBRARY_PATH
else
# With GCC up to 2.95.x, collect2 would create an import file
# for dependence libraries. The import file would start with
# the line '#! .'. This would cause the generated library to
# depend on '.', always an invalid library. This was fixed in
# development snapshots of GCC prior to 3.0.
case $host_os in
aix4 | aix4.[[01]] | aix4.[[01]].*)
if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
echo ' yes '
echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
:
else
can_build_shared=no
fi
;;
esac
# Using Import Files as archive members, it is possible to support
# filename-based versioning of shared library archives on AIX. While
# this would work for both with and without runtime linking, it will
# prevent static linking of such archives. So we do filename-based
# shared library versioning with .so extension only, which is used
# when both runtime linking and shared linking is enabled.
# Unfortunately, runtime linking may impact performance, so we do
# not want this to be the default eventually. Also, we use the
# versioned .so libs for executables only if there is the -brtl
# linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
# To allow for filename-based versioning support, we need to create
# libNAME.so.V as an archive file, containing:
# *) an Import File, referring to the versioned filename of the
# archive as well as the shared archive member, telling the
# bitwidth (32 or 64) of that shared object, and providing the
# list of exported symbols of that shared object, eventually
# decorated with the 'weak' keyword
# *) the shared object with the F_LOADONLY flag set, to really avoid
# it being seen by the linker.
# At run time we better use the real file rather than another symlink,
# but for link time we create the symlink libNAME.so -> libNAME.so.V
case $with_aix_soname,$aix_use_runtimelinking in
# AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
# soname into executable. Probably we can add versioning support to
# collect2, so additional links can be useful in future.
aix,yes) # traditional libtool
dynamic_linker='AIX unversionable lib.so'
# If using run time linking (on AIX 4.2 or later) use lib.so
# instead of lib.a to let people know that these are not
# typical AIX shared libraries.
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
;;
aix,no) # traditional AIX only
dynamic_linker='AIX lib.a[(]lib.so.V[)]'
# We preserve .a as extension for shared libraries through AIX4.2
# and later when we are not doing run time linking.
library_names_spec='$libname$release.a $libname.a'
soname_spec='$libname$release$shared_ext$major'
;;
svr4,*) # full svr4 only
dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]"
library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
# We do not specify a path in Import Files, so LIBPATH fires.
shlibpath_overrides_runpath=yes
;;
*,yes) # both, prefer svr4
dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]"
library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
# unpreferred sharedlib libNAME.a needs extra handling
postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
# We do not specify a path in Import Files, so LIBPATH fires.
shlibpath_overrides_runpath=yes
;;
*,no) # both, prefer aix
dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]"
library_names_spec='$libname$release.a $libname.a'
soname_spec='$libname$release$shared_ext$major'
# unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
;;
esac
shlibpath_var=LIBPATH
fi
;;
amigaos*)
case $host_cpu in
powerpc)
# Since July 2007 AmigaOS4 officially supports .so libraries.
# When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
;;
m68k)
library_names_spec='$libname.ixlibrary $libname.a'
# Create ${libname}_ixlibrary.a entries in /sys/libs.
finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
;;
esac
;;
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"
shlibpath_var=LIBRARY_PATH
;;
bsdi[[45]]*)
version_type=linux # correct to gnu/linux during the next big refactor
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
shlibpath_var=LD_LIBRARY_PATH
sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
# the default ld.so.conf also contains /usr/contrib/lib and
# /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
# libtool to hard-code these into programs
;;
cygwin* | mingw* | pw32* | cegcc*)
version_type=windows
shrext_cmds=.dll
need_version=no
need_lib_prefix=no
case $GCC,$cc_basename in
yes,*)
# gcc
library_names_spec='$libname.dll.a'
# DLL is installed to $(libdir)/../bin by postinstall_cmds
postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~
test -d \$dldir || mkdir -p \$dldir~
$install_prog $dir/$dlname \$dldir/$dlname~
chmod a+x \$dldir/$dlname~
if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
fi'
postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
dlpath=$dir/\$dldll~
$RM \$dlpath'
shlibpath_overrides_runpath=yes
case $host_os in
cygwin*)
# Cygwin DLLs use 'cyg' prefix rather than 'lib'
soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
m4_if([$1], [],[
sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
;;
mingw* | cegcc*)
# MinGW DLLs use traditional 'lib' prefix
soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
;;
pw32*)
# pw32 DLLs use 'pw' prefix rather than 'lib'
library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
;;
esac
dynamic_linker='Win32 ld.exe'
;;
*,cl*)
# Native MSVC
libname_spec='$name'
soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
library_names_spec='$libname.dll.lib'
case $build_os in
mingw*)
sys_lib_search_path_spec=
lt_save_ifs=$IFS
IFS=';'
for lt_path in $LIB
do
IFS=$lt_save_ifs
# Let DOS variable expansion print the short 8.3 style file name.
lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
done
IFS=$lt_save_ifs
# Convert to MSYS style.
sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
;;
cygwin*)
# Convert to unix form, then to dos form, then back to unix form
# but this time dos style (no spaces!) so that the unix form looks
# like /cygdrive/c/PROGRA~1:/cygdr...
sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
;;
*)
sys_lib_search_path_spec=$LIB
if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
# It is most probably a Windows format PATH.
sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
else
sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
fi
# FIXME: find the short name or the path components, as spaces are
# common. (e.g. "Program Files" -> "PROGRA~1")
;;
esac
# DLL is installed to $(libdir)/../bin by postinstall_cmds
postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~
test -d \$dldir || mkdir -p \$dldir~
$install_prog $dir/$dlname \$dldir/$dlname'
postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
dlpath=$dir/\$dldll~
$RM \$dlpath'
shlibpath_overrides_runpath=yes
dynamic_linker='Win32 link.exe'
;;
*)
# Assume MSVC wrapper
library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
dynamic_linker='Win32 ld.exe'
;;
esac
# FIXME: first we should search . and the directory the executable is in
shlibpath_var=PATH
;;
darwin* | rhapsody*)
dynamic_linker="$host_os dyld"
version_type=darwin
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
soname_spec='$libname$release$major$shared_ext'
shlibpath_overrides_runpath=yes
shlibpath_var=DYLD_LIBRARY_PATH
shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
m4_if([$1], [],[
sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
;;
dgux*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
;;
freebsd* | dragonfly*)
# DragonFly does not have aout. When/if they implement a new
# versioning mechanism, adjust this.
if test -x /usr/bin/objformat; then
objformat=`/usr/bin/objformat`
else
case $host_os in
freebsd[[23]].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
version_type=freebsd-$objformat
case $version_type in
freebsd-elf*)
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
need_version=no
need_lib_prefix=no
;;
freebsd-*)
library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
need_version=yes
;;
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[[01]]* | freebsdelf3.[[01]]*)
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
;;
freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
;;
*) # from 4.6 on, and DragonFly
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
;;
esac
;;
haiku*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
dynamic_linker="$host_os runtime_loader"
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LIBRARY_PATH
shlibpath_overrides_runpath=no
sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
hardcode_into_libs=yes
;;
hpux9* | hpux10* | hpux11*)
# Give a soname corresponding to the major version so that dld.sl refuses to
# link against other versions.
version_type=sunos
need_lib_prefix=no
need_version=no
case $host_cpu in
ia64*)
shrext_cmds='.so'
hardcode_into_libs=yes
dynamic_linker="$host_os dld.so"
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
if test 32 = "$HPUX_IA64_MODE"; then
sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
sys_lib_dlsearch_path_spec=/usr/lib/hpux32
else
sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
sys_lib_dlsearch_path_spec=/usr/lib/hpux64
fi
;;
hppa*64*)
shrext_cmds='.sl'
hardcode_into_libs=yes
dynamic_linker="$host_os dld.sl"
shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
;;
*)
shrext_cmds='.sl'
dynamic_linker="$host_os dld.sl"
shlibpath_var=SHLIB_PATH
shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
;;
esac
# HP-UX runs *really* slowly unless shared libraries are mode 555, ...
postinstall_cmds='chmod 555 $lib'
# or fails outright, so override atomically:
install_override_mode=555
;;
interix[[3-9]]*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
;;
irix5* | irix6* | nonstopux*)
case $host_os in
nonstopux*) version_type=nonstopux ;;
*)
if test yes = "$lt_cv_prog_gnu_ld"; then
version_type=linux # correct to gnu/linux during the next big refactor
else
version_type=irix
fi ;;
esac
need_lib_prefix=no
need_version=no
soname_spec='$libname$release$shared_ext$major'
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
case $host_os in
irix5* | nonstopux*)
libsuff= shlibsuff=
;;
*)
case $LD in # libtool.m4 will add one of these switches to LD
*-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
libsuff= shlibsuff= libmagic=32-bit;;
*-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
libsuff=32 shlibsuff=N32 libmagic=N32;;
*-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
libsuff=64 shlibsuff=64 libmagic=64-bit;;
*) libsuff= shlibsuff= libmagic=never-match;;
esac
;;
esac
shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
shlibpath_overrides_runpath=no
sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
hardcode_into_libs=yes
;;
# No shared lib support for Linux oldld, aout, or coff.
linux*oldld* | linux*aout* | linux*coff*)
dynamic_linker=no
;;
linux*android*)
version_type=none # Android doesn't support versioned libraries.
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext'
soname_spec='$libname$release$shared_ext'
finish_cmds=
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
# This implies no fast_install, which is unacceptable.
# Some rework will be needed to allow for fast_install
# before this can be enabled.
hardcode_into_libs=yes
dynamic_linker='Android linker'
# Don't embed -rpath directories since the linker doesn't support them.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
;;
# This must be glibc/ELF.
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
# Some binutils ld are patched to set DT_RUNPATH
AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
[lt_cv_shlibpath_overrides_runpath=no
save_LDFLAGS=$LDFLAGS
save_libdir=$libdir
eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
[AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
[lt_cv_shlibpath_overrides_runpath=yes])])
LDFLAGS=$save_LDFLAGS
libdir=$save_libdir
])
shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
# This implies no fast_install, which is unacceptable.
# Some rework will be needed to allow for fast_install
# before this can be enabled.
hardcode_into_libs=yes
# Add ABI-specific directories to the system library path.
sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
# Ideally, we could use ldconfig to report *all* directores which are
# searched for libraries, however this is still not possible. Aside from not
# being certain /sbin/ldconfig is available, command
# 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
# even though it is searched at run-time. Try to do the best guess by
# appending ld.so.conf contents (and includes) to the search path.
if test -f /etc/ld.so.conf; then
lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
fi
# We used to test for /lib/ld.so.1 and disable shared libraries on
# powerpc, because MkLinux only supported shared libraries with the
# GNU dynamic linker. Since this was broken with cross compilers,
# most powerpc-linux boxes support dynamic linking these days and
# people can always --disable-shared, the test was removed, and we
# assume the GNU/Linux dynamic linker is in use.
dynamic_linker='GNU/Linux ld.so'
;;
netbsd*)
version_type=sunos
need_lib_prefix=no
need_version=no
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
dynamic_linker='NetBSD (a.out) ld.so'
else
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
dynamic_linker='NetBSD ld.elf_so'
fi
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
;;
newsos6)
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
;;
*nto* | *qnx*)
version_type=qnx
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
dynamic_linker='ldqnx.so'
;;
openbsd* | bitrig*)
version_type=sunos
sys_lib_dlsearch_path_spec=/usr/lib
need_lib_prefix=no
if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
need_version=no
else
need_version=yes
fi
library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
;;
os2*)
libname_spec='$name'
version_type=windows
shrext_cmds=.dll
need_version=no
need_lib_prefix=no
# OS/2 can only load a DLL with a base name of 8 characters or less.
soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
v=$($ECHO $release$versuffix | tr -d .-);
n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
$ECHO $n$v`$shared_ext'
library_names_spec='${libname}_dll.$libext'
dynamic_linker='OS/2 ld.exe'
shlibpath_var=BEGINLIBPATH
sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~
test -d \$dldir || mkdir -p \$dldir~
$install_prog $dir/$dlname \$dldir/$dlname~
chmod a+x \$dldir/$dlname~
if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
fi'
postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
dlpath=$dir/\$dldll~
$RM \$dlpath'
;;
osf3* | osf4* | osf5*)
version_type=osf
need_lib_prefix=no
need_version=no
soname_spec='$libname$release$shared_ext$major'
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
shlibpath_var=LD_LIBRARY_PATH
sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
;;
rdos*)
dynamic_linker=no
;;
solaris*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
# ldd complains unless libraries are executable
postinstall_cmds='chmod +x $lib'
;;
sunos4*)
version_type=sunos
library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
if test yes = "$with_gnu_ld"; then
need_lib_prefix=no
fi
need_version=yes
;;
sysv4 | sysv4.3*)
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
case $host_vendor in
sni)
shlibpath_overrides_runpath=no
need_lib_prefix=no
runpath_var=LD_RUN_PATH
;;
siemens)
need_lib_prefix=no
;;
motorola)
need_lib_prefix=no
need_version=no
shlibpath_overrides_runpath=no
sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
;;
esac
;;
sysv4*MP*)
if test -d /usr/nec; then
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
soname_spec='$libname$shared_ext.$major'
shlibpath_var=LD_LIBRARY_PATH
fi
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
version_type=sco
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
if test yes = "$with_gnu_ld"; then
sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
else
sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
case $host_os in
sco3.2v5*)
sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
;;
esac
fi
sys_lib_dlsearch_path_spec='/usr/lib'
;;
tpf*)
# TPF is a cross-target only. Preferred cross-host = GNU/Linux.
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
;;
uts4*)
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
;;
*)
dynamic_linker=no
;;
esac
AC_MSG_RESULT([$dynamic_linker])
test no = "$dynamic_linker" && can_build_shared=no
variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
if test yes = "$GCC"; then
variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
fi
if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
fi
if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
fi
# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
_LT_DECL([], [variables_saved_for_relink], [1],
[Variables whose values should be saved in libtool wrapper scripts and
restored at link time])
_LT_DECL([], [need_lib_prefix], [0],
[Do we need the "lib" prefix for modules?])
_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
_LT_DECL([], [version_type], [0], [Library versioning type])
_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable])
_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
_LT_DECL([], [shlibpath_overrides_runpath], [0],
[Is shlibpath searched before the hard-coded library search path?])
_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
_LT_DECL([], [library_names_spec], [1],
[[List of archive names. First name is the real one, the rest are links.
The last name is the one that the linker finds with -lNAME]])
_LT_DECL([], [soname_spec], [1],
[[The coded name of the library, if different from the real name]])
_LT_DECL([], [install_override_mode], [1],
[Permission mode override for installation of shared libraries])
_LT_DECL([], [postinstall_cmds], [2],
[Command to use after installation of a shared archive])
_LT_DECL([], [postuninstall_cmds], [2],
[Command to use after uninstallation of a shared archive])
_LT_DECL([], [finish_cmds], [2],
[Commands used to finish a libtool library installation in a directory])
_LT_DECL([], [finish_eval], [1],
[[As "finish_cmds", except a single script fragment to be evaled but
not shown]])
_LT_DECL([], [hardcode_into_libs], [0],
[Whether we should hardcode library paths into libraries])
_LT_DECL([], [sys_lib_search_path_spec], [2],
[Compile-time system search path for libraries])
_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2],
[Detected run-time system search path for libraries])
_LT_DECL([], [configure_time_lt_sys_library_path], [2],
[Explicit LT_SYS_LIBRARY_PATH set during ./configure time])
])# _LT_SYS_DYNAMIC_LINKER
# _LT_PATH_TOOL_PREFIX(TOOL)
# --------------------------
# find a file program that can recognize shared library
AC_DEFUN([_LT_PATH_TOOL_PREFIX],
[m4_require([_LT_DECL_EGREP])dnl
AC_MSG_CHECKING([for $1])
AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
[case $MAGIC_CMD in
[[\\/*] | ?:[\\/]*])
lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
;;
*)
lt_save_MAGIC_CMD=$MAGIC_CMD
lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
dnl $ac_dummy forces splitting on constant user-supplied paths.
dnl POSIX.2 word splitting is done only on the output of word expansions,
dnl not every word. This closes a longstanding sh security hole.
ac_dummy="m4_if([$2], , $PATH, [$2])"
for ac_dir in $ac_dummy; do
IFS=$lt_save_ifs
test -z "$ac_dir" && ac_dir=.
if test -f "$ac_dir/$1"; then
lt_cv_path_MAGIC_CMD=$ac_dir/"$1"
if test -n "$file_magic_test_file"; then
case $deplibs_check_method in
"file_magic "*)
file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
MAGIC_CMD=$lt_cv_path_MAGIC_CMD
if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
$EGREP "$file_magic_regex" > /dev/null; then
:
else
cat <<_LT_EOF 1>&2
*** Warning: the command libtool uses to detect shared libraries,
*** $file_magic_cmd, produces output that libtool cannot recognize.
*** The result is that libtool may fail to recognize shared libraries
*** as such. This will affect the creation of libtool libraries that
*** depend on shared libraries, but programs linked with such libtool
*** libraries will work regardless of this problem. Nevertheless, you
*** may want to report the problem to your system manager and/or to
*** bug-libtool@gnu.org
_LT_EOF
fi ;;
esac
fi
break
fi
done
IFS=$lt_save_ifs
MAGIC_CMD=$lt_save_MAGIC_CMD
;;
esac])
MAGIC_CMD=$lt_cv_path_MAGIC_CMD
if test -n "$MAGIC_CMD"; then
AC_MSG_RESULT($MAGIC_CMD)
else
AC_MSG_RESULT(no)
fi
_LT_DECL([], [MAGIC_CMD], [0],
[Used to examine libraries when file_magic_cmd begins with "file"])dnl
])# _LT_PATH_TOOL_PREFIX
# Old name:
AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
# _LT_PATH_MAGIC
# --------------
# find a file program that can recognize a shared library
m4_defun([_LT_PATH_MAGIC],
[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
if test -z "$lt_cv_path_MAGIC_CMD"; then
if test -n "$ac_tool_prefix"; then
_LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
else
MAGIC_CMD=:
fi
fi
])# _LT_PATH_MAGIC
# LT_PATH_LD
# ----------
# find the pathname to the GNU or non-GNU linker
AC_DEFUN([LT_PATH_LD],
[AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
AC_ARG_WITH([gnu-ld],
[AS_HELP_STRING([--with-gnu-ld],
[assume the C compiler uses GNU ld @<:@default=no@:>@])],
[test no = "$withval" || with_gnu_ld=yes],
[with_gnu_ld=no])dnl
ac_prog=ld
if test yes = "$GCC"; then
# Check if gcc -print-prog-name=ld gives a path.
AC_MSG_CHECKING([for ld used by $CC])
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.
[[\\/]]* | ?:[[\\/]]*)
re_direlt='/[[^/]][[^/]]*/\.\./'
# Canonicalize the pathname 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 yes = "$with_gnu_ld"; then
AC_MSG_CHECKING([for GNU ld])
else
AC_MSG_CHECKING([for non-GNU ld])
fi
AC_CACHE_VAL(lt_cv_path_LD,
[if test -z "$LD"; then
lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
for ac_dir in $PATH; do
IFS=$lt_save_ifs
test -z "$ac_dir" && ac_dir=.
if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
lt_cv_path_LD=$ac_dir/$ac_prog
# Check to see if the program is GNU ld. I'd rather use --version,
# but apparently some variants of GNU ld only accept -v.
# Break only if it was the GNU/non-GNU ld that we prefer.
case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i
cat conftest.i conftest.i >conftest2.i
: ${lt_DD:=$DD}
AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd],
[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
cmp -s conftest.i conftest.out \
&& ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
fi])
rm -f conftest.i conftest2.i conftest.out])
])# _LT_PATH_DD
# _LT_CMD_TRUNCATE
# ----------------
# find command to truncate a binary pipe
m4_defun([_LT_CMD_TRUNCATE],
[m4_require([_LT_PATH_DD])
AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin],
[printf 0123456789abcdef0123456789abcdef >conftest.i
cat conftest.i conftest.i >conftest2.i
lt_cv_truncate_bin=
if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
cmp -s conftest.i conftest.out \
&& lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
fi
rm -f conftest.i conftest2.i conftest.out
test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"])
_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1],
[Command to truncate a binary pipe])
])# _LT_CMD_TRUNCATE
# _LT_CHECK_MAGIC_METHOD
# ----------------------
# how to check for library dependencies
# -- PORTME fill in with the dynamic library characteristics
m4_defun([_LT_CHECK_MAGIC_METHOD],
[m4_require([_LT_DECL_EGREP])
m4_require([_LT_DECL_OBJDUMP])
AC_CACHE_CHECK([how to recognize dependent libraries],
lt_cv_deplibs_check_method,
[lt_cv_file_magic_cmd='$MAGIC_CMD'
lt_cv_file_magic_test_file=
lt_cv_deplibs_check_method='unknown'
# Need to set the preceding variable on all platforms that support
# interlibrary dependencies.
# 'none' -- dependencies not supported.
# 'unknown' -- same as none, but documents that we really don't know.
# 'pass_all' -- all dependencies passed with no checks.
# 'test_compile' -- check by making test program.
# 'file_magic [[regex]]' -- check by looking for files in library path
# that responds to the $file_magic_cmd with a given extended regex.
# If you have 'file' or equivalent on your system and you're not sure
# whether 'pass_all' will *always* work, you probably want this one.
case $host_os in
aix[[4-9]]*)
lt_cv_deplibs_check_method=pass_all
;;
beos*)
lt_cv_deplibs_check_method=pass_all
;;
bsdi[[45]]*)
lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
lt_cv_file_magic_cmd='/usr/bin/file -L'
lt_cv_file_magic_test_file=/shlib/libc.so
;;
cygwin*)
# func_win32_libid is a shell function defined in ltmain.sh
lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
lt_cv_file_magic_cmd='func_win32_libid'
;;
mingw* | pw32*)
# Base MSYS/MinGW do not provide the 'file' command needed by
# func_win32_libid shell function, so use a weaker test based on 'objdump',
# unless we find 'file', for example because we are cross-compiling.
if ( file / ) >/dev/null 2>&1; then
lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
lt_cv_file_magic_cmd='func_win32_libid'
else
# Keep this pattern in sync with the one in func_win32_libid.
lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
lt_cv_file_magic_cmd='$OBJDUMP -f'
fi
;;
cegcc*)
# use the weaker test based on 'objdump'. See mingw*.
lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
lt_cv_file_magic_cmd='$OBJDUMP -f'
;;
darwin* | rhapsody*)
lt_cv_deplibs_check_method=pass_all
;;
freebsd* | dragonfly*)
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
case $host_cpu in
i*86 )
# Not sure whether the presence of OpenBSD here was a mistake.
# Let's accept both of them until this is cleared up.
lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
lt_cv_file_magic_cmd=/usr/bin/file
lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
;;
esac
else
lt_cv_deplibs_check_method=pass_all
fi
;;
haiku*)
lt_cv_deplibs_check_method=pass_all
;;
hpux10.20* | hpux11*)
lt_cv_file_magic_cmd=/usr/bin/file
case $host_cpu in
ia64*)
lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
;;
hppa*64*)
[lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
;;
*)
lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
lt_cv_file_magic_test_file=/usr/lib/libc.sl
;;
esac
;;
interix[[3-9]]*)
# PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
;;
irix5* | irix6* | nonstopux*)
case $LD in
*-32|*"-32 ") libmagic=32-bit;;
*-n32|*"-n32 ") libmagic=N32;;
*-64|*"-64 ") libmagic=64-bit;;
*) libmagic=never-match;;
esac
lt_cv_deplibs_check_method=pass_all
;;
# This must be glibc/ELF.
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
lt_cv_deplibs_check_method=pass_all
;;
netbsd*)
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
else
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
fi
;;
newos6*)
lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
lt_cv_file_magic_cmd=/usr/bin/file
lt_cv_file_magic_test_file=/usr/lib/libnls.so
;;
*nto* | *qnx*)
lt_cv_deplibs_check_method=pass_all
;;
openbsd* | bitrig*)
if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
else
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
fi
;;
osf3* | osf4* | osf5*)
lt_cv_deplibs_check_method=pass_all
;;
rdos*)
lt_cv_deplibs_check_method=pass_all
;;
solaris*)
lt_cv_deplibs_check_method=pass_all
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
lt_cv_deplibs_check_method=pass_all
;;
sysv4 | sysv4.3*)
case $host_vendor in
motorola)
lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
;;
ncr)
lt_cv_deplibs_check_method=pass_all
;;
sequent)
lt_cv_file_magic_cmd='/bin/file'
lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
;;
sni)
lt_cv_file_magic_cmd='/bin/file'
lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
lt_cv_file_magic_test_file=/lib/libc.so
;;
siemens)
lt_cv_deplibs_check_method=pass_all
;;
pc)
lt_cv_deplibs_check_method=pass_all
;;
esac
;;
tpf*)
lt_cv_deplibs_check_method=pass_all
;;
os2*)
lt_cv_deplibs_check_method=pass_all
;;
esac
])
file_magic_glob=
want_nocaseglob=no
if test "$build" = "$host"; then
case $host_os in
mingw* | pw32*)
if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
want_nocaseglob=yes
else
file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
fi
;;
esac
fi
file_magic_cmd=$lt_cv_file_magic_cmd
deplibs_check_method=$lt_cv_deplibs_check_method
test -z "$deplibs_check_method" && deplibs_check_method=unknown
_LT_DECL([], [deplibs_check_method], [1],
[Method to check whether dependent libraries are shared objects])
_LT_DECL([], [file_magic_cmd], [1],
[Command to use when deplibs_check_method = "file_magic"])
_LT_DECL([], [file_magic_glob], [1],
[How to find potential files when deplibs_check_method = "file_magic"])
_LT_DECL([], [want_nocaseglob], [1],
[Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
])# _LT_CHECK_MAGIC_METHOD
# LT_PATH_NM
# ----------
# find the pathname to a BSD- or MS-compatible name lister
AC_DEFUN([LT_PATH_NM],
[AC_REQUIRE([AC_PROG_CC])dnl
AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
[if test -n "$NM"; then
# Let the user override the test.
lt_cv_path_NM=$NM
else
lt_nm_to_check=${ac_tool_prefix}nm
if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
lt_nm_to_check="$lt_nm_to_check nm"
fi
for lt_tmp_nm in $lt_nm_to_check; do
lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
IFS=$lt_save_ifs
test -z "$ac_dir" && ac_dir=.
tmp_nm=$ac_dir/$lt_tmp_nm
if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
# Check to see if the nm accepts a BSD-compat flag.
# Adding the 'sed 1q' prevents false positives on HP-UX, which says:
# nm: unknown option "B" ignored
# Tru64's nm complains that /dev/null is an invalid object file
# MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
case $build_os in
mingw*) lt_bad_file=conftest.nm/nofile ;;
*) lt_bad_file=/dev/null ;;
esac
case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
*$lt_bad_file* | *'Invalid file or object type'*)
lt_cv_path_NM="$tmp_nm -B"
break 2
;;
*)
case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
*/dev/null*)
lt_cv_path_NM="$tmp_nm -p"
break 2
;;
*)
lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
continue # so that we can try to find one that supports BSD flags
;;
esac
;;
esac
fi
done
IFS=$lt_save_ifs
done
: ${lt_cv_path_NM=no}
fi])
if test no != "$lt_cv_path_NM"; then
NM=$lt_cv_path_NM
else
# Didn't find any BSD compatible name lister, look for dumpbin.
if test -n "$DUMPBIN"; then :
# Let the user override the test.
else
AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in
*COFF*)
DUMPBIN="$DUMPBIN -symbols -headers"
;;
*)
DUMPBIN=:
;;
esac
fi
AC_SUBST([DUMPBIN])
if test : != "$DUMPBIN"; then
NM=$DUMPBIN
fi
fi
test -z "$NM" && NM=nm
AC_SUBST([NM])
_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
[lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&AS_MESSAGE_LOG_FD
(eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&AS_MESSAGE_LOG_FD
(eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
cat conftest.out >&AS_MESSAGE_LOG_FD
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
fi
rm -f conftest*])
])# LT_PATH_NM
# Old names:
AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_PROG_NM], [])
dnl AC_DEFUN([AC_PROG_NM], [])
# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
# --------------------------------
# how to determine the name of the shared library
# associated with a specific link library.
# -- PORTME fill in with the dynamic library characteristics
m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
[m4_require([_LT_DECL_EGREP])
m4_require([_LT_DECL_OBJDUMP])
m4_require([_LT_DECL_DLLTOOL])
AC_CACHE_CHECK([how to associate runtime and link libraries],
lt_cv_sharedlib_from_linklib_cmd,
[lt_cv_sharedlib_from_linklib_cmd='unknown'
case $host_os in
cygwin* | mingw* | pw32* | cegcc*)
# two different shell functions defined in ltmain.sh;
# decide which one to use based on capabilities of $DLLTOOL
case `$DLLTOOL --help 2>&1` in
*--identify-strict*)
lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
;;
*)
lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
;;
esac
;;
*)
# fallback: assume linklib IS sharedlib
lt_cv_sharedlib_from_linklib_cmd=$ECHO
;;
esac
])
sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
[Command to associate shared and link libraries])
])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
# _LT_PATH_MANIFEST_TOOL
# ----------------------
# locate the manifest tool
m4_defun([_LT_PATH_MANIFEST_TOOL],
[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
[lt_cv_path_mainfest_tool=no
echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
$MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
cat conftest.err >&AS_MESSAGE_LOG_FD
if $GREP 'Manifest Tool' conftest.out > /dev/null; then
lt_cv_path_mainfest_tool=yes
fi
rm -f conftest*])
if test yes != "$lt_cv_path_mainfest_tool"; then
MANIFEST_TOOL=:
fi
_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
])# _LT_PATH_MANIFEST_TOOL
# _LT_DLL_DEF_P([FILE])
# ---------------------
# True iff FILE is a Windows DLL '.def' file.
# Keep in sync with func_dll_def_p in the libtool script
AC_DEFUN([_LT_DLL_DEF_P],
[dnl
test DEF = "`$SED -n dnl
-e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace
-e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments
-e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl
-e q dnl Only consider the first "real" line
$1`" dnl
])# _LT_DLL_DEF_P
# LT_LIB_M
# --------
# check for math library
AC_DEFUN([LT_LIB_M],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
LIBM=
case $host in
*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
# These system don't have libm, or don't need it
;;
*-ncr-sysv4.3*)
AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw)
AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
;;
*)
AC_CHECK_LIB(m, cos, LIBM=-lm)
;;
esac
AC_SUBST([LIBM])
])# LT_LIB_M
# Old name:
AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_CHECK_LIBM], [])
# _LT_COMPILER_NO_RTTI([TAGNAME])
# -------------------------------
m4_defun([_LT_COMPILER_NO_RTTI],
[m4_require([_LT_TAG_COMPILER])dnl
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
if test yes = "$GCC"; then
case $cc_basename in
nvcc*)
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
*)
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
esac
_LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
lt_cv_prog_compiler_rtti_exceptions,
[-fno-rtti -fno-exceptions], [],
[_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
fi
_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
[Compiler flag to turn off builtin functions])
])# _LT_COMPILER_NO_RTTI
# _LT_CMD_GLOBAL_SYMBOLS
# ----------------------
m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([LT_PATH_NM])dnl
AC_REQUIRE([LT_PATH_LD])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_TAG_COMPILER])dnl
# Check for command to grab the raw symbol name followed by C symbol from nm.
AC_MSG_CHECKING([command to parse $NM output from $compiler object])
AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
[
# These are sane defaults that work on at least a few old systems.
# [They come from Ultrix. What could be older than Ultrix?!! ;)]
# Character class describing NM global symbol codes.
symcode='[[BCDEGRST]]'
# Regexp to match symbols that can be accessed directly from C.
sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
# Define system-specific variables.
case $host_os in
aix*)
symcode='[[BCDT]]'
;;
cygwin* | mingw* | pw32* | cegcc*)
symcode='[[ABCDGISTW]]'
;;
hpux*)
if test ia64 = "$host_cpu"; then
symcode='[[ABCDEGRST]]'
fi
;;
irix* | nonstopux*)
symcode='[[BCDEGRST]]'
;;
osf*)
symcode='[[BCDEGQRST]]'
;;
solaris*)
symcode='[[BDRT]]'
;;
sco3.2v5*)
symcode='[[DT]]'
;;
sysv4.2uw2*)
symcode='[[DT]]'
;;
sysv5* | sco5v6* | unixware* | OpenUNIX*)
symcode='[[ABDT]]'
;;
sysv4)
symcode='[[DFNSTU]]'
;;
esac
# If we're using GNU nm, then use its standard symbol codes.
case `$NM -V 2>&1` in
*GNU* | *'with BFD'*)
symcode='[[ABCDGIRSTW]]' ;;
esac
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
# Gets list of data symbols to import.
lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
# Adjust the below global symbol transforms to fixup imported variables.
lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'"
lt_c_name_lib_hook="\
-e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\
-e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'"
else
# Disable hooks by default.
lt_cv_sys_global_symbol_to_import=
lt_cdecl_hook=
lt_c_name_hook=
lt_c_name_lib_hook=
fi
# Transform an extracted symbol line into a proper C declaration.
# Some systems (esp. on ia64) link data and code symbols differently,
# so use this general approach.
lt_cv_sys_global_symbol_to_cdecl="sed -n"\
$lt_cdecl_hook\
" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
# Transform an extracted symbol line into symbol name and symbol address
lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
$lt_c_name_hook\
" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'"
# Transform an extracted symbol line into symbol name with lib prefix and
# symbol address.
lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
$lt_c_name_lib_hook\
" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\
" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'"
# Handle CRLF in mingw tool chain
opt_cr=
case $build_os in
mingw*)
opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
;;
esac
# Try without a prefix underscore, then with it.
for ac_symprfx in "" "_"; do
# Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
symxfrm="\\1 $ac_symprfx\\2 \\2"
# Write the raw and C identifiers.
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
# Fake it for dumpbin and say T for any non-static function,
# D for any global variable and I for any imported variable.
# Also find C++ and __fastcall symbols from MSVC++,
# which start with @ or ?.
lt_cv_sys_global_symbol_pipe="$AWK ['"\
" {last_section=section; section=\$ 3};"\
" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
" \$ 0!~/External *\|/{next};"\
" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
" {if(hide[section]) next};"\
" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
" ' prfx=^$ac_symprfx]"
else
lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
fi
lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
# Check to see that the pipe works correctly.
pipe_works=no
rm -f conftest*
cat > conftest.$ac_ext <<_LT_EOF
#ifdef __cplusplus
extern "C" {
#endif
char nm_test_var;
void nm_test_func(void);
void nm_test_func(void){}
#ifdef __cplusplus
}
#endif
int main(){nm_test_var='a';nm_test_func();return(0);}
_LT_EOF
if AC_TRY_EVAL(ac_compile); then
# Now try to grab the symbols.
nlist=conftest.nm
if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
# Try sorting and uniquifying the output.
if sort "$nlist" | uniq > "$nlist"T; then
mv -f "$nlist"T "$nlist"
else
rm -f "$nlist"T
fi
# Make sure that we snagged all the symbols we need.
if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
cat <<_LT_EOF > conftest.$ac_ext
/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
/* DATA imports from DLLs on WIN32 can't be const, because runtime
relocations are performed -- see ld's documentation on pseudo-relocs. */
# define LT@&t@_DLSYM_CONST
#elif defined __osf__
/* This system does not cope well with relocations in const data. */
# define LT@&t@_DLSYM_CONST
#else
# define LT@&t@_DLSYM_CONST const
#endif
#ifdef __cplusplus
extern "C" {
#endif
_LT_EOF
# Now generate the symbol file.
eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
cat <<_LT_EOF >> conftest.$ac_ext
/* The mapping between symbol names and symbols. */
LT@&t@_DLSYM_CONST struct {
const char *name;
void *address;
}
lt__PROGRAM__LTX_preloaded_symbols[[]] =
{
{ "@PROGRAM@", (void *) 0 },
_LT_EOF
$SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
cat <<\_LT_EOF >> conftest.$ac_ext
{0, (void *) 0}
};
/* This works around a problem in FreeBSD linker */
#ifdef FREEBSD_WORKAROUND
static const void *lt_preloaded_setup() {
return lt__PROGRAM__LTX_preloaded_symbols;
}
#endif
#ifdef __cplusplus
}
#endif
_LT_EOF
# Now try linking the two files.
mv conftest.$ac_objext conftstm.$ac_objext
lt_globsym_save_LIBS=$LIBS
lt_globsym_save_CFLAGS=$CFLAGS
LIBS=conftstm.$ac_objext
CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then
pipe_works=yes
fi
LIBS=$lt_globsym_save_LIBS
CFLAGS=$lt_globsym_save_CFLAGS
else
echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
fi
else
echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
fi
else
echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
fi
else
echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
cat conftest.$ac_ext >&5
fi
rm -rf conftest* conftst*
# Do not use the global_symbol_pipe unless it works.
if test yes = "$pipe_works"; then
break
else
lt_cv_sys_global_symbol_pipe=
fi
done
])
if test -z "$lt_cv_sys_global_symbol_pipe"; then
lt_cv_sys_global_symbol_to_cdecl=
fi
if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
AC_MSG_RESULT(failed)
else
AC_MSG_RESULT(ok)
fi
# Response file support.
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
nm_file_list_spec='@'
elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
nm_file_list_spec='@'
fi
_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
[Take the output of nm and produce a listing of raw symbols and C names])
_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
[Transform the output of nm in a proper C declaration])
_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1],
[Transform the output of nm into a list of symbols to manually relocate])
_LT_DECL([global_symbol_to_c_name_address],
[lt_cv_sys_global_symbol_to_c_name_address], [1],
[Transform the output of nm in a C name address pair])
_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
[lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
[Transform the output of nm in a C name address pair when lib prefix is needed])
_LT_DECL([nm_interface], [lt_cv_nm_interface], [1],
[The name lister interface])
_LT_DECL([], [nm_file_list_spec], [1],
[Specify filename containing input files for $NM])
]) # _LT_CMD_GLOBAL_SYMBOLS
# _LT_COMPILER_PIC([TAGNAME])
# ---------------------------
m4_defun([_LT_COMPILER_PIC],
[m4_require([_LT_TAG_COMPILER])dnl
_LT_TAGVAR(lt_prog_compiler_wl, $1)=
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
_LT_TAGVAR(lt_prog_compiler_static, $1)=
m4_if([$1], [CXX], [
# C++ specific cases for pic, static, wl, etc.
if test yes = "$GXX"; then
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
case $host_os in
aix*)
# All AIX code is PIC.
if test ia64 = "$host_cpu"; then
# AIX 5 now supports IA64 processor
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
fi
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
m68k)
# FIXME: we need at least 68020 code to build shared libraries, but
# adding the '-m68020' flag to GCC prevents building anything better,
# like '-m68040'.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
;;
esac
;;
beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
# PIC is the default for these OSes.
;;
mingw* | cygwin* | os2* | pw32* | cegcc*)
# This hack is so that the source file can tell whether it is being
# built for inclusion in a dll (and should export symbols for example).
# Although the cygwin gcc ignores -fPIC, still need this for old-style
# (--disable-auto-import) libraries
m4_if([$1], [GCJ], [],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
case $host_os in
os2*)
_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
;;
esac
;;
darwin* | rhapsody*)
# PIC is the default on this platform
# Common symbols not allowed in MH_DYLIB files
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
;;
*djgpp*)
# DJGPP does not support shared libraries at all
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
;;
haiku*)
# PIC is the default for Haiku.
# The "-static" flag exists, but is broken.
_LT_TAGVAR(lt_prog_compiler_static, $1)=
;;
interix[[3-9]]*)
# Interix 3.x gcc -fpic/-fPIC options generate broken code.
# Instead, we relocate shared libraries at runtime.
;;
sysv4*MP*)
if test -d /usr/nec; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
fi
;;
hpux*)
# PIC is the default for 64-bit PA HP-UX, but not for 32-bit
# PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
# sets the default TLS model and affects inlining.
case $host_cpu in
hppa*64*)
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
esac
;;
*qnx* | *nto*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
esac
else
case $host_os in
aix[[4-9]]*)
# All AIX code is PIC.
if test ia64 = "$host_cpu"; then
# AIX 5 now supports IA64 processor
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
else
_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
fi
;;
chorus*)
case $cc_basename in
cxch68*)
# Green Hills C++ Compiler
# _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
;;
esac
;;
mingw* | cygwin* | os2* | pw32* | cegcc*)
# This hack is so that the source file can tell whether it is being
# built for inclusion in a dll (and should export symbols for example).
m4_if([$1], [GCJ], [],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
;;
dgux*)
case $cc_basename in
ec++*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
;;
ghcx*)
# Green Hills C++ Compiler
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
;;
*)
;;
esac
;;
freebsd* | dragonfly*)
# FreeBSD uses GNU C++
;;
hpux9* | hpux10* | hpux11*)
case $cc_basename in
CC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
if test ia64 != "$host_cpu"; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
fi
;;
aCC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
case $host_cpu in
hppa*64*|ia64*)
# +Z the default
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
;;
esac
;;
*)
;;
esac
;;
interix*)
# This is c89, which is MS Visual C++ (no shared libs)
# Anyone wants to do a port?
;;
irix5* | irix6* | nonstopux*)
case $cc_basename in
CC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
# CC pic flag -KPIC is the default.
;;
*)
;;
esac
;;
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
case $cc_basename in
KCC*)
# KAI C++ Compiler
_LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
ecpc* )
# old Intel C++ for x86_64, which still supported -KPIC.
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
icpc* )
# Intel C++, used to be incompatible with GCC.
# ICC 10 doesn't accept -KPIC any more.
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
pgCC* | pgcpp*)
# Portland Group C++ compiler
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
cxx*)
# Compaq C++
# Make sure the PIC flag is empty. It appears that all Alpha
# Linux and Compaq Tru64 Unix objects are PIC.
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
# IBM XL 8.0, 9.0 on PPC and BlueGene
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
;;
*)
case `$CC -V 2>&1 | sed 5q` in
*Sun\ C*)
# Sun C++ 5.9
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
;;
esac
;;
esac
;;
lynxos*)
;;
m88k*)
;;
mvs*)
case $cc_basename in
cxx*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
;;
*)
;;
esac
;;
netbsd*)
;;
*qnx* | *nto*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
;;
osf3* | osf4* | osf5*)
case $cc_basename in
KCC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
;;
RCC*)
# Rational C++ 2.4.1
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
;;
cxx*)
# Digital/Compaq C++
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# Make sure the PIC flag is empty. It appears that all Alpha
# Linux and Compaq Tru64 Unix objects are PIC.
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
*)
;;
esac
;;
psos*)
;;
solaris*)
case $cc_basename in
CC* | sunCC*)
# Sun C++ 4.2, 5.x and Centerline C++
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
;;
gcx*)
# Green Hills C++ Compiler
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
;;
*)
;;
esac
;;
sunos4*)
case $cc_basename in
CC*)
# Sun C++ 4.x
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
lcc*)
# Lucid
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
;;
*)
;;
esac
;;
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
case $cc_basename in
CC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
esac
;;
tandem*)
case $cc_basename in
NCC*)
# NonStop-UX NCC 3.20
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
;;
*)
;;
esac
;;
vxworks*)
;;
*)
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
;;
esac
fi
],
[
if test yes = "$GCC"; then
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
case $host_os in
aix*)
# All AIX code is PIC.
if test ia64 = "$host_cpu"; then
# AIX 5 now supports IA64 processor
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
fi
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
m68k)
# FIXME: we need at least 68020 code to build shared libraries, but
# adding the '-m68020' flag to GCC prevents building anything better,
# like '-m68040'.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
;;
esac
;;
beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
# PIC is the default for these OSes.
;;
mingw* | cygwin* | pw32* | os2* | cegcc*)
# This hack is so that the source file can tell whether it is being
# built for inclusion in a dll (and should export symbols for example).
# Although the cygwin gcc ignores -fPIC, still need this for old-style
# (--disable-auto-import) libraries
m4_if([$1], [GCJ], [],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
case $host_os in
os2*)
_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
;;
esac
;;
darwin* | rhapsody*)
# PIC is the default on this platform
# Common symbols not allowed in MH_DYLIB files
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
;;
haiku*)
# PIC is the default for Haiku.
# The "-static" flag exists, but is broken.
_LT_TAGVAR(lt_prog_compiler_static, $1)=
;;
hpux*)
# PIC is the default for 64-bit PA HP-UX, but not for 32-bit
# PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
# sets the default TLS model and affects inlining.
case $host_cpu in
hppa*64*)
# +Z the default
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
esac
;;
interix[[3-9]]*)
# Interix 3.x gcc -fpic/-fPIC options generate broken code.
# Instead, we relocate shared libraries at runtime.
;;
msdosdjgpp*)
# Just because we use GCC doesn't mean we suddenly get shared libraries
# on systems that don't support them.
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
enable_shared=no
;;
*nto* | *qnx*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
;;
sysv4*MP*)
if test -d /usr/nec; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
fi
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
esac
case $cc_basename in
nvcc*) # Cuda Compiler Driver 2.2
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
fi
;;
esac
else
# PORTME Check for flag to pass linker flags through the system compiler.
case $host_os in
aix*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
if test ia64 = "$host_cpu"; then
# AIX 5 now supports IA64 processor
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
else
_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
fi
;;
darwin* | rhapsody*)
# PIC is the default on this platform
# Common symbols not allowed in MH_DYLIB files
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
case $cc_basename in
nagfor*)
# NAG Fortran compiler
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
esac
;;
mingw* | cygwin* | pw32* | os2* | cegcc*)
# This hack is so that the source file can tell whether it is being
# built for inclusion in a dll (and should export symbols for example).
m4_if([$1], [GCJ], [],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
case $host_os in
os2*)
_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
;;
esac
;;
hpux9* | hpux10* | hpux11*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
# not for PA HP-UX.
case $host_cpu in
hppa*64*|ia64*)
# +Z the default
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
;;
esac
# Is there a better lt_prog_compiler_static that works with the bundled CC?
_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
;;
irix5* | irix6* | nonstopux*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# PIC (with -KPIC) is the default.
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
case $cc_basename in
# old Intel for x86_64, which still supported -KPIC.
ecc*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
# icc used to be incompatible with GCC.
# ICC 10 doesn't accept -KPIC any more.
icc* | ifort*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
# Lahey Fortran 8.1.
lf95*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
_LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
;;
nagfor*)
# NAG Fortran compiler
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
tcc*)
# Fabrice Bellard et al's Tiny C Compiler
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
# Portland Group compilers (*not* the Pentium gcc compiler,
# which looks to be a dead project)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
ccc*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# All Alpha code is PIC.
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
xl* | bgxl* | bgf* | mpixl*)
# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
;;
*)
case `$CC -V 2>&1 | sed 5q` in
*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
# Sun Fortran 8.3 passes all unrecognized flags to the linker
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)=''
;;
*Sun\ F* | *Sun*Fortran*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
;;
*Sun\ C*)
# Sun C 5.9
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
;;
*Intel*\ [[CF]]*Compiler*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
*Portland\ Group*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
esac
;;
esac
;;
newsos6)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
*nto* | *qnx*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
;;
osf3* | osf4* | osf5*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# All OSF/1 code is PIC.
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
rdos*)
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
solaris*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
case $cc_basename in
f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
esac
;;
sunos4*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
sysv4 | sysv4.2uw2* | sysv4.3*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
sysv4*MP*)
if test -d /usr/nec; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
fi
;;
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
unicos*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
;;
uts4*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
*)
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
;;
esac
fi
])
case $host_os in
# For platforms that do not support PIC, -DPIC is meaningless:
*djgpp*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
;;
esac
AC_CACHE_CHECK([for $compiler option to produce PIC],
[_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
[_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
#
# Check to make sure the PIC flag actually works.
#
if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
_LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
[_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
[$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
[case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
"" | " "*) ;;
*) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
esac],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)=
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
fi
_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
[Additional compiler flags for building library objects])
_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
[How to pass a linker flag through the compiler])
#
# Check to make sure the static flag actually works.
#
wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
_LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
$lt_tmp_static_flag,
[],
[_LT_TAGVAR(lt_prog_compiler_static, $1)=])
_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
[Compiler flag to prevent dynamic linking])
])# _LT_COMPILER_PIC
# _LT_LINKER_SHLIBS([TAGNAME])
# ----------------------------
# See if the linker supports building shared libraries.
m4_defun([_LT_LINKER_SHLIBS],
[AC_REQUIRE([LT_PATH_LD])dnl
AC_REQUIRE([LT_PATH_NM])dnl
m4_require([_LT_PATH_MANIFEST_TOOL])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
m4_require([_LT_TAG_COMPILER])dnl
AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
m4_if([$1], [CXX], [
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
_LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
case $host_os in
aix[[4-9]]*)
# If we're using GNU nm, then we don't want the "-C" option.
# -C means demangle to GNU nm, but means don't demangle to AIX nm.
# Without the "-l" option, or with the "-B" option, AIX nm treats
# weak defined symbols like other global defined symbols, whereas
# GNU nm marks them as "W".
# While the 'weak' keyword is ignored in the Export File, we need
# it in the Import File for the 'aix-soname' feature, so we have
# to replace the "-B" option with "-P" for AIX nm.
if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
_LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
else
_LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
fi
;;
pw32*)
_LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds
;;
cygwin* | mingw* | cegcc*)
case $cc_basename in
cl*)
_LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
;;
*)
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
_LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
;;
esac
;;
*)
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
;;
esac
], [
runpath_var=
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_cmds, $1)=
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(compiler_needs_object, $1)=no
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(old_archive_from_new_cmds, $1)=
_LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
_LT_TAGVAR(thread_safe_flag_spec, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
# include_expsyms should be a list of space-separated symbols to be *always*
# included in the symbol list
_LT_TAGVAR(include_expsyms, $1)=
# exclude_expsyms can be an extended regexp of symbols to exclude
# it will be wrapped by ' (' and ')$', so one must not match beginning or
# end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
# as well as any symbol that contains 'd'.
_LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
# platforms (ab)use it in PIC code, but their linkers get confused if
# the symbol is explicitly referenced. Since portable code cannot
# rely on this symbol name, it's probably fine to never include it in
# preloaded symbol tables.
# Exclude shared library initialization/finalization symbols.
dnl Note also adjust exclude_expsyms for C++ above.
extract_expsyms_cmds=
case $host_os in
cygwin* | mingw* | pw32* | cegcc*)
# 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 yes != "$GCC"; then
with_gnu_ld=no
fi
;;
interix*)
# we just hope/assume this is gcc and not c89 (= MSVC++)
with_gnu_ld=yes
;;
openbsd* | bitrig*)
with_gnu_ld=no
;;
esac
_LT_TAGVAR(ld_shlibs, $1)=yes
# On some targets, GNU ld is compatible enough with the native linker
# that we're better off using the native interface for both.
lt_use_gnu_ld_interface=no
if test yes = "$with_gnu_ld"; then
case $host_os in
aix*)
# The AIX port of GNU ld has always aspired to compatibility
# with the native linker. However, as the warning in the GNU ld
# block says, versions before 2.19.5* couldn't really create working
# shared libraries, regardless of the interface used.
case `$LD -v 2>&1` in
*\ \(GNU\ Binutils\)\ 2.19.5*) ;;
*\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
*\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
*)
lt_use_gnu_ld_interface=yes
;;
esac
;;
*)
lt_use_gnu_ld_interface=yes
;;
esac
fi
if test yes = "$lt_use_gnu_ld_interface"; then
# If archive_cmds runs LD, not CC, wlarc should be empty
wlarc='$wl'
# Set some defaults for GNU ld with shared library support. These
# are reset later if shared libraries are not supported. Putting them
# here allows them to be overridden if necessary.
runpath_var=LD_RUN_PATH
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
# ancient GNU ld didn't support --whole-archive et. al.
if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
_LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
else
_LT_TAGVAR(whole_archive_flag_spec, $1)=
fi
supports_anon_versioning=no
case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
*GNU\ gold*) supports_anon_versioning=yes ;;
*\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
*\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
*\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
*\ 2.11.*) ;; # other 2.11 versions
*) supports_anon_versioning=yes ;;
esac
# See if GNU ld supports shared libraries.
case $host_os in
aix[[3-9]]*)
# On AIX/PPC, the GNU linker is very broken
if test ia64 != "$host_cpu"; then
_LT_TAGVAR(ld_shlibs, $1)=no
cat <<_LT_EOF 1>&2
*** Warning: the GNU linker, at least up to release 2.19, is reported
*** to be unable to reliably create shared libraries on AIX.
*** Therefore, libtool is disabling shared libraries support. If you
*** really care for shared libraries, you may want to install binutils
*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
*** You will then need to restart the configuration process.
_LT_EOF
fi
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)=''
;;
m68k)
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_minus_L, $1)=yes
;;
esac
;;
beos*)
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
# Joseph Beckenbach says some releases of gcc
# support --undefined. This deserves some investigation. FIXME
_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
cygwin* | mingw* | pw32* | cegcc*)
# _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
# as there is no search path for DLLs.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
_LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
# If the export-symbols file already is a .def file, use it as
# is; otherwise, prepend EXPORTS...
_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
cp $export_symbols $output_objdir/$soname.def;
else
echo EXPORTS > $output_objdir/$soname.def;
cat $export_symbols >> $output_objdir/$soname.def;
fi~
$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
haiku*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(link_all_deplibs, $1)=yes
;;
os2*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
shrext_cmds=.dll
_LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
prefix_cmds="$SED"~
if test EXPORTS = "`$SED 1q $export_symbols`"; then
prefix_cmds="$prefix_cmds -e 1d";
fi~
prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
;;
interix[[3-9]]*)
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
# Instead, shared libraries are loaded at an image base (0x10000000 by
# default) and relocated if they conflict, which is a slow very memory
# consuming and fragmenting process. To avoid this, we pick a random,
# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
# time. Moving up from 0x10000000 also allows more sbrk(2) space.
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
;;
gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
tmp_diet=no
if test linux-dietlibc = "$host_os"; then
case $cc_basename in
diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
esac
fi
if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
&& test no = "$tmp_diet"
then
tmp_addflag=' $pic_flag'
tmp_sharedflag='-shared'
case $cc_basename,$host_cpu in
pgcc*) # Portland Group C compiler
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
tmp_addflag=' $pic_flag'
;;
pgf77* | pgf90* | pgf95* | pgfortran*)
# Portland Group f77 and f90 compilers
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
tmp_addflag=' $pic_flag -Mnomain' ;;
ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
tmp_addflag=' -i_dynamic' ;;
efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
tmp_addflag=' -i_dynamic -nofor_main' ;;
ifc* | ifort*) # Intel Fortran compiler
tmp_addflag=' -nofor_main' ;;
lf95*) # Lahey Fortran 8.1
_LT_TAGVAR(whole_archive_flag_spec, $1)=
tmp_sharedflag='--shared' ;;
nagfor*) # NAGFOR 5.3
tmp_sharedflag='-Wl,-shared' ;;
xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
tmp_sharedflag='-qmkshrobj'
tmp_addflag= ;;
nvcc*) # Cuda Compiler Driver 2.2
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
_LT_TAGVAR(compiler_needs_object, $1)=yes
;;
esac
case `$CC -V 2>&1 | sed 5q` in
*Sun\ C*) # Sun C 5.9
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
_LT_TAGVAR(compiler_needs_object, $1)=yes
tmp_sharedflag='-G' ;;
*Sun\ F*) # Sun Fortran 8.3
tmp_sharedflag='-G' ;;
esac
_LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
if test yes = "$supports_anon_versioning"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
fi
case $cc_basename in
tcc*)
_LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
;;
xlf* | bgf* | bgxlf* | mpixlf*)
# IBM XL Fortran 10.1 on PPC cannot create shared libs itself
_LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
if test yes = "$supports_anon_versioning"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
fi
;;
esac
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
netbsd*)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
wlarc=
else
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
fi
;;
solaris*)
if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
_LT_TAGVAR(ld_shlibs, $1)=no
cat <<_LT_EOF 1>&2
*** Warning: The releases 2.8.* of the GNU linker cannot reliably
*** create shared libraries on Solaris systems. Therefore, libtool
*** is disabling shared libraries support. We urge you to upgrade GNU
*** binutils to release 2.9.1 or newer. Another option is to modify
*** your PATH or compiler configuration so that the native linker is
*** used, and then restart.
_LT_EOF
elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
case `$LD -v 2>&1` in
*\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
_LT_TAGVAR(ld_shlibs, $1)=no
cat <<_LT_EOF 1>&2
*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
*** reliably create shared libraries on SCO systems. Therefore, libtool
*** is disabling shared libraries support. We urge you to upgrade GNU
*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
*** your PATH or compiler configuration so that the native linker is
*** used, and then restart.
_LT_EOF
;;
*)
# For security reasons, it is highly recommended that you always
# use absolute paths for naming shared libraries, and exclude the
# DT_RUNPATH tag from executables and libraries. But doing so
# requires that you compile everything twice, which is a pain.
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
sunos4*)
_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
wlarc=
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*)
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then
runpath_var=
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
fi
else
# PORTME fill in a description of your system's linker (not GNU ld)
case $host_os in
aix3*)
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=yes
_LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
# Note: this linker hardcodes the directories in LIBPATH if there
# are no directories specified by -L.
_LT_TAGVAR(hardcode_minus_L, $1)=yes
if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
# Neither direct hardcoding nor static linking is supported with a
# broken collect2.
_LT_TAGVAR(hardcode_direct, $1)=unsupported
fi
;;
aix[[4-9]]*)
if test ia64 = "$host_cpu"; then
# On IA64, the linker does run time linking by default, so we don't
# have to do anything special.
aix_use_runtimelinking=no
exp_sym_flag='-Bexport'
no_entry_flag=
else
# If we're using GNU nm, then we don't want the "-C" option.
# -C means demangle to GNU nm, but means don't demangle to AIX nm.
# Without the "-l" option, or with the "-B" option, AIX nm treats
# weak defined symbols like other global defined symbols, whereas
# GNU nm marks them as "W".
# While the 'weak' keyword is ignored in the Export File, we need
# it in the Import File for the 'aix-soname' feature, so we have
# to replace the "-B" option with "-P" for AIX nm.
if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
_LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
else
_LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
fi
aix_use_runtimelinking=no
# Test if we are trying to use run time linking or normal
# AIX style linking. If -brtl is somewhere in LDFLAGS, we
# have runtime linking enabled, and use it for executables.
# For shared libraries, we enable/disable runtime linking
# depending on the kind of the shared library created -
# when "with_aix_soname,aix_use_runtimelinking" is:
# "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
# "aix,yes" lib.so shared, rtl:yes, for executables
# lib.a static archive
# "both,no" lib.so.V(shr.o) shared, rtl:yes
# lib.a(lib.so.V) shared, rtl:no, for executables
# "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
# lib.a(lib.so.V) shared, rtl:no
# "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
# lib.a static archive
case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
for ld_flag in $LDFLAGS; do
if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
aix_use_runtimelinking=yes
break
fi
done
if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
# With aix-soname=svr4, we create the lib.so.V shared archives only,
# so we don't have lib.a shared libs to link our executables.
# We have to force runtime linking in this case.
aix_use_runtimelinking=yes
LDFLAGS="$LDFLAGS -Wl,-brtl"
fi
;;
esac
exp_sym_flag='-bexport'
no_entry_flag='-bnoentry'
fi
# When large executables or shared objects are built, AIX ld can
# have problems creating the table of contents. If linking a library
# or program results in "error TOC overflow" add -mminimal-toc to
# CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
# enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
_LT_TAGVAR(archive_cmds, $1)=''
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='$wl-f,'
case $with_aix_soname,$aix_use_runtimelinking in
aix,*) ;; # traditional, no import file
svr4,* | *,yes) # use import file
# The Import File defines what to hardcode.
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
;;
esac
if test yes = "$GCC"; then
case $host_os in aix4.[[012]]|aix4.[[012]].*)
# We only want to do this on AIX 4.2 and lower, the check
# below for broken collect2 doesn't work under 4.3+
collect2name=`$CC -print-prog-name=collect2`
if test -f "$collect2name" &&
strings "$collect2name" | $GREP resolve_lib_name >/dev/null
then
# We have reworked collect2
:
else
# We have old collect2
_LT_TAGVAR(hardcode_direct, $1)=unsupported
# It fails to find uninstalled libraries when the uninstalled
# path is not listed in the libpath. Setting hardcode_minus_L
# to unsupported forces relinking
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=
fi
;;
esac
shared_flag='-shared'
if test yes = "$aix_use_runtimelinking"; then
shared_flag="$shared_flag "'$wl-G'
fi
# Need to ensure runtime linking is disabled for the traditional
# shared library, or the linker may eventually find shared libraries
# /with/ Import File - we do not want to mix them.
shared_flag_aix='-shared'
shared_flag_svr4='-shared $wl-G'
else
# not using gcc
if test ia64 = "$host_cpu"; then
# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
# chokes on -Wl,-G. The following line is correct:
shared_flag='-G'
else
if test yes = "$aix_use_runtimelinking"; then
shared_flag='$wl-G'
else
shared_flag='$wl-bM:SRE'
fi
shared_flag_aix='$wl-bM:SRE'
shared_flag_svr4='$wl-G'
fi
fi
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
# It seems that -bexpall does not export symbols beginning with
# underscore (_), so it is better to generate a list of symbols to export.
_LT_TAGVAR(always_export_symbols, $1)=yes
if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
# Warning - without using the other runtime loading flags (-brtl),
# -berok will link without error, but may produce a broken library.
_LT_TAGVAR(allow_undefined_flag, $1)='-berok'
# Determine the default libpath from the value encoded in an
# empty executable.
_LT_SYS_MODULE_PATH_AIX([$1])
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
else
if test ia64 = "$host_cpu"; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
_LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
_LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
else
# Determine the default libpath from the value encoded in an
# empty executable.
_LT_SYS_MODULE_PATH_AIX([$1])
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
# Warning - without using the other run time loading flags,
# -berok will link without error, but may produce a broken library.
_LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
if test yes = "$with_gnu_ld"; then
# We only use this code for GNU lds that support --whole-archive.
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
else
# Exported symbols can be pulled into shared objects from archives
_LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
_LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
# -brtl affects multiple linker settings, -berok does not and is overridden later
compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
if test svr4 != "$with_aix_soname"; then
# This is similar to how AIX traditionally builds its shared libraries.
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
fi
if test aix != "$with_aix_soname"; then
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
else
# used by -dlpreopen to get the symbols
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
fi
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
fi
fi
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)=''
;;
m68k)
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_minus_L, $1)=yes
;;
esac
;;
bsdi[[45]]*)
_LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
;;
cygwin* | mingw* | pw32* | cegcc*)
# 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.
case $cc_basename in
cl*)
# Native MSVC
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
# Tell ltmain to make .lib files, not .a files.
libext=lib
# Tell ltmain to make .dll files, not .so files.
shrext_cmds=.dll
# FIXME: Setting linknames here is a bad hack.
_LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
cp "$export_symbols" "$output_objdir/$soname.def";
echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
else
$SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
fi~
$CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
linknames='
# The linker will not automatically build a static lib if we build a DLL.
# _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
# Don't use ranlib
_LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
_LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
lt_tool_outputfile="@TOOL_OUTPUT@"~
case $lt_outputfile in
*.exe|*.EXE) ;;
*)
lt_outputfile=$lt_outputfile.exe
lt_tool_outputfile=$lt_tool_outputfile.exe
;;
esac~
if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
$MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
$RM "$lt_outputfile.manifest";
fi'
;;
*)
# Assume MSVC wrapper
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
# Tell ltmain to make .lib files, not .a files.
libext=lib
# Tell ltmain to make .dll files, not .so files.
shrext_cmds=.dll
# FIXME: Setting linknames here is a bad hack.
_LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
# The linker will automatically build a .lib file if we build a DLL.
_LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
# FIXME: Should let the user specify the lib program.
_LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
;;
esac
;;
darwin* | rhapsody*)
_LT_DARWIN_LINKER_FEATURES($1)
;;
dgux*)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
# FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
# support. Future versions do this automatically, but an explicit c++rt0.o
# does not break anything, and helps significantly (at the cost of a little
# extra space).
freebsd2.2*)
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
freebsd2.*)
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
# FreeBSD 3 and greater uses gcc -shared to do shared libraries.
freebsd* | dragonfly*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
hpux9*)
if test yes = "$GCC"; then
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
else
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(hardcode_direct, $1)=yes
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
;;
hpux10*)
if test yes,no = "$GCC,$with_gnu_ld"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
else
_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
fi
if test no = "$with_gnu_ld"; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
_LT_TAGVAR(hardcode_minus_L, $1)=yes
fi
;;
hpux11*)
if test yes,no = "$GCC,$with_gnu_ld"; then
case $host_cpu in
hppa*64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
ia64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
;;
esac
else
case $host_cpu in
hppa*64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
ia64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
;;
*)
m4_if($1, [], [
# Older versions of the 11.00 compiler do not understand -b yet
# (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
_LT_LINKER_OPTION([if $CC understands -b],
_LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
[_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
[_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
[_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
;;
esac
fi
if test no = "$with_gnu_ld"; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
case $host_cpu in
hppa*64*|ia64*)
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*)
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
_LT_TAGVAR(hardcode_minus_L, $1)=yes
;;
esac
fi
;;
irix5* | irix6* | nonstopux*)
if test yes = "$GCC"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
# Try to use the -exported_symbol ld option, if it does not
# work, assume that -exports_file does not work either and
# implicitly export all symbols.
# This should be the same for all languages, so no per-tag cache variable.
AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
[lt_cv_irix_exported_symbol],
[save_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
AC_LINK_IFELSE(
[AC_LANG_SOURCE(
[AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
[C++], [[int foo (void) { return 0; }]],
[Fortran 77], [[
subroutine foo
end]],
[Fortran], [[
subroutine foo
end]])])],
[lt_cv_irix_exported_symbol=yes],
[lt_cv_irix_exported_symbol=no])
LDFLAGS=$save_LDFLAGS])
if test yes = "$lt_cv_irix_exported_symbol"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
fi
else
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)='no'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(inherit_rpath, $1)=yes
_LT_TAGVAR(link_all_deplibs, $1)=yes
;;
linux*)
case $cc_basename in
tcc*)
# Fabrice Bellard et al's Tiny C Compiler
_LT_TAGVAR(ld_shlibs, $1)=yes
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
;;
esac
;;
netbsd*)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
else
_LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
newsos6)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*nto* | *qnx*)
;;
openbsd* | bitrig*)
if test -f /usr/libexec/ld.so; then
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
else
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
fi
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
os2*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
shrext_cmds=.dll
_LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
prefix_cmds="$SED"~
if test EXPORTS = "`$SED 1q $export_symbols`"; then
prefix_cmds="$prefix_cmds -e 1d";
fi~
prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
;;
osf3*)
if test yes = "$GCC"; then
_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
else
_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)='no'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
;;
osf4* | osf5*) # as osf3* with the addition of -msym flag
if test yes = "$GCC"; then
_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
else
_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
$CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
# Both c and cxx compiler support -rpath directly
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)='no'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
;;
solaris*)
_LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
if test yes = "$GCC"; then
wlarc='$wl'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
$CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
else
case `$CC -V 2>&1` in
*"Compilers 5.0"*)
wlarc=''
_LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
$LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
;;
*)
wlarc='$wl'
_LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
$CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
;;
esac
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
case $host_os in
solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
*)
# The compiler driver will combine and reorder linker options,
# but understands '-z linker_flag'. GCC discards it without '$wl',
# but is careful enough not to reorder.
# Supported since Solaris 2.6 (maybe 2.5.1?)
if test yes = "$GCC"; then
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
else
_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
fi
;;
esac
_LT_TAGVAR(link_all_deplibs, $1)=yes
;;
sunos4*)
if test sequent = "$host_vendor"; then
# Use $CC to link under sequent, because it throws in some extra .o
# files that make .init and .fini sections work.
_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
else
_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
sysv4)
case $host_vendor in
sni)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
;;
siemens)
## LD is ld it makes a PLAMLIB
## CC just makes a GrossModule.
_LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
_LT_TAGVAR(hardcode_direct, $1)=no
;;
motorola)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
;;
esac
runpath_var='LD_RUN_PATH'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
sysv4.3*)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
;;
sysv4*MP*)
if test -d /usr/nec; then
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
runpath_var=LD_RUN_PATH
hardcode_runpath_var=yes
_LT_TAGVAR(ld_shlibs, $1)=yes
fi
;;
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
_LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
runpath_var='LD_RUN_PATH'
if test yes = "$GCC"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
else
_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
fi
;;
sysv5* | sco3.2v5* | sco5v6*)
# Note: We CANNOT use -z defs as we might desire, because we do not
# link with -lc, and that would cause any symbols used from libc to
# always be unresolved, which means just about no library would
# ever link correctly. If we're not using GNU ld we use -z text
# though, which does catch some bad symbols but isn't as heavy-handed
# as -z defs.
_LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
_LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
runpath_var='LD_RUN_PATH'
if test yes = "$GCC"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
else
_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
fi
;;
uts4*)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*)
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
if test sni = "$host_vendor"; then
case $host in
sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym'
;;
esac
fi
fi
])
AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
_LT_DECL([], [extract_expsyms_cmds], [2],
[The commands to extract the exported symbol list from a shared archive])
#
# Do we need to explicitly link libc?
#
case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
x|xyes)
# Assume -lc should be added
_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
if test yes,yes = "$GCC,$enable_shared"; then
case $_LT_TAGVAR(archive_cmds, $1) in
*'~'*)
# FIXME: we may have to deal with multi-command sequences.
;;
'$CC '*)
# Test whether the compiler implicitly links with -lc since on some
# systems, -lgcc has to come before -lc. If gcc already passes -lc
# to ld, don't add -lc before -lgcc.
AC_CACHE_CHECK([whether -lc should be explicitly linked in],
[lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
[$RM conftest*
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
soname=conftest
lib=conftest
libobjs=conftest.$ac_objext
deplibs=
wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
compiler_flags=-v
linker_flags=-v
verstring=
output_objdir=.
libname=conftest
lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
_LT_TAGVAR(allow_undefined_flag, $1)=
if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
then
lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
else
lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
fi
_LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
else
cat conftest.err 1>&5
fi
$RM conftest*
])
_LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
;;
esac
fi
;;
esac
_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
[Whether or not to add -lc for building shared libraries])
_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
[enable_shared_with_static_runtimes], [0],
[Whether or not to disallow shared libs when runtime libs are static])
_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
[Compiler flag to allow reflexive dlopens])
_LT_TAGDECL([], [whole_archive_flag_spec], [1],
[Compiler flag to generate shared objects directly from archives])
_LT_TAGDECL([], [compiler_needs_object], [1],
[Whether the compiler copes with passing no objects directly])
_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
[Create an old-style archive from a shared archive])
_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
[Create a temporary old-style archive to link instead of a shared archive])
_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
_LT_TAGDECL([], [archive_expsym_cmds], [2])
_LT_TAGDECL([], [module_cmds], [2],
[Commands used to build a loadable module if different from building
a shared archive.])
_LT_TAGDECL([], [module_expsym_cmds], [2])
_LT_TAGDECL([], [with_gnu_ld], [1],
[Whether we are building with GNU ld or not])
_LT_TAGDECL([], [allow_undefined_flag], [1],
[Flag that allows shared libraries with undefined symbols to be built])
_LT_TAGDECL([], [no_undefined_flag], [1],
[Flag that enforces no undefined symbols])
_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
[Flag to hardcode $libdir into a binary during linking.
This must work even if $libdir does not exist])
_LT_TAGDECL([], [hardcode_libdir_separator], [1],
[Whether we need a single "-rpath" flag with a separated argument])
_LT_TAGDECL([], [hardcode_direct], [0],
[Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
DIR into the resulting binary])
_LT_TAGDECL([], [hardcode_direct_absolute], [0],
[Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
DIR into the resulting binary and the resulting library dependency is
"absolute", i.e impossible to change by setting $shlibpath_var if the
library is relocated])
_LT_TAGDECL([], [hardcode_minus_L], [0],
[Set to "yes" if using the -LDIR flag during linking hardcodes DIR
into the resulting binary])
_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
[Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
into the resulting binary])
_LT_TAGDECL([], [hardcode_automatic], [0],
[Set to "yes" if building a shared library automatically hardcodes DIR
into the library and all subsequent libraries and executables linked
against it])
_LT_TAGDECL([], [inherit_rpath], [0],
[Set to yes if linker adds runtime paths of dependent libraries
to runtime path list])
_LT_TAGDECL([], [link_all_deplibs], [0],
[Whether libtool must link a program against all its dependency libraries])
_LT_TAGDECL([], [always_export_symbols], [0],
[Set to "yes" if exported symbols are required])
_LT_TAGDECL([], [export_symbols_cmds], [2],
[The commands to list exported symbols])
_LT_TAGDECL([], [exclude_expsyms], [1],
[Symbols that should not be listed in the preloaded symbols])
_LT_TAGDECL([], [include_expsyms], [1],
[Symbols that must always be exported])
_LT_TAGDECL([], [prelink_cmds], [2],
[Commands necessary for linking programs (against libraries) with templates])
_LT_TAGDECL([], [postlink_cmds], [2],
[Commands necessary for finishing linking programs])
_LT_TAGDECL([], [file_list_spec], [1],
[Specify filename containing input files])
dnl FIXME: Not yet implemented
dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
dnl [Compiler flag to generate thread safe objects])
])# _LT_LINKER_SHLIBS
# _LT_LANG_C_CONFIG([TAG])
# ------------------------
# Ensure that the configuration variables for a C compiler are suitably
# defined. These variables are subsequently used by _LT_CONFIG to write
# the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_C_CONFIG],
[m4_require([_LT_DECL_EGREP])dnl
lt_save_CC=$CC
AC_LANG_PUSH(C)
# Source file extension for C test sources.
ac_ext=c
# Object file extension for compiled C test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code="int some_variable = 0;"
# Code to be used in simple link tests
lt_simple_link_test_code='int main(){return(0);}'
_LT_TAG_COMPILER
# Save the default compiler, since it gets overwritten when the other
# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
compiler_DEFAULT=$CC
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
if test -n "$compiler"; then
_LT_COMPILER_NO_RTTI($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_SYS_DYNAMIC_LINKER($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
LT_SYS_DLOPEN_SELF
_LT_CMD_STRIPLIB
# Report what library types will actually be built
AC_MSG_CHECKING([if libtool supports shared libraries])
AC_MSG_RESULT([$can_build_shared])
AC_MSG_CHECKING([whether to build shared libraries])
test no = "$can_build_shared" && enable_shared=no
# On AIX, shared libraries and static libraries use the same namespace, and
# are all built from PIC.
case $host_os in
aix3*)
test yes = "$enable_shared" && enable_static=no
if test -n "$RANLIB"; then
archive_cmds="$archive_cmds~\$RANLIB \$lib"
postinstall_cmds='$RANLIB $lib'
fi
;;
aix[[4-9]]*)
if test ia64 != "$host_cpu"; then
case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
yes,aix,yes) ;; # shared object as lib.so file only
yes,svr4,*) ;; # shared object as lib.so archive member only
yes,*) enable_static=no ;; # shared object in lib.a archive as well
esac
fi
;;
esac
AC_MSG_RESULT([$enable_shared])
AC_MSG_CHECKING([whether to build static libraries])
# Make sure either enable_shared or enable_static is yes.
test yes = "$enable_shared" || enable_static=yes
AC_MSG_RESULT([$enable_static])
_LT_CONFIG($1)
fi
AC_LANG_POP
CC=$lt_save_CC
])# _LT_LANG_C_CONFIG
# _LT_LANG_CXX_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for a C++ compiler are suitably
# defined. These variables are subsequently used by _LT_CONFIG to write
# the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_CXX_CONFIG],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_PATH_MANIFEST_TOOL])dnl
if test -n "$CXX" && ( test no != "$CXX" &&
( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
(test g++ != "$CXX"))); then
AC_PROG_CXXCPP
else
_lt_caught_CXX_error=yes
fi
AC_LANG_PUSH(C++)
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(compiler_needs_object, $1)=no
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
_LT_TAGVAR(no_undefined_flag, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
# Source file extension for C++ test sources.
ac_ext=cpp
# Object file extension for compiled C++ test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# No sense in running all these tests if we already determined that
# the CXX compiler isn't working. Some variables (like enable_shared)
# are currently assumed to apply to all compilers on this platform,
# and will be corrupted by setting them based on a non-working compiler.
if test yes != "$_lt_caught_CXX_error"; then
# Code to be used in simple compile tests
lt_simple_compile_test_code="int some_variable = 0;"
# Code to be used in simple link tests
lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_LD=$LD
lt_save_GCC=$GCC
GCC=$GXX
lt_save_with_gnu_ld=$with_gnu_ld
lt_save_path_LD=$lt_cv_path_LD
if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
else
$as_unset lt_cv_prog_gnu_ld
fi
if test -n "${lt_cv_path_LDCXX+set}"; then
lt_cv_path_LD=$lt_cv_path_LDCXX
else
$as_unset lt_cv_path_LD
fi
test -z "${LDCXX+set}" || LD=$LDCXX
CC=${CXX-"c++"}
CFLAGS=$CXXFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_CC_BASENAME([$compiler])
if test -n "$compiler"; then
# We don't want -fno-exception when compiling C++ code, so set the
# no_builtin_flag separately
if test yes = "$GXX"; then
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
else
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
fi
if test yes = "$GXX"; then
# Set up default GNU C++ configuration
LT_PATH_LD
# Check if GNU C++ uses GNU ld as the underlying linker, since the
# archiving commands below assume that GNU ld is being used.
if test yes = "$with_gnu_ld"; then
_LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
# If archive_cmds runs LD, not CC, wlarc should be empty
# XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
# investigate it a little bit more. (MM)
wlarc='$wl'
# ancient GNU ld didn't support --whole-archive et. al.
if eval "`$CC -print-prog-name=ld` --help 2>&1" |
$GREP 'no-whole-archive' > /dev/null; then
_LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
else
_LT_TAGVAR(whole_archive_flag_spec, $1)=
fi
else
with_gnu_ld=no
wlarc=
# A generic and very simple default shared library creation
# command for GNU C++ for the case where it uses the native
# linker, instead of GNU ld. If possible, this setting should
# overridden to take advantage of the native linker features on
# the platform it is being used on.
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
fi
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
else
GXX=no
with_gnu_ld=no
wlarc=
fi
# PORTME: fill in a description of your system's C++ link characteristics
AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
_LT_TAGVAR(ld_shlibs, $1)=yes
case $host_os in
aix3*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
aix[[4-9]]*)
if test ia64 = "$host_cpu"; then
# On IA64, the linker does run time linking by default, so we don't
# have to do anything special.
aix_use_runtimelinking=no
exp_sym_flag='-Bexport'
no_entry_flag=
else
aix_use_runtimelinking=no
# Test if we are trying to use run time linking or normal
# AIX style linking. If -brtl is somewhere in LDFLAGS, we
# have runtime linking enabled, and use it for executables.
# For shared libraries, we enable/disable runtime linking
# depending on the kind of the shared library created -
# when "with_aix_soname,aix_use_runtimelinking" is:
# "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
# "aix,yes" lib.so shared, rtl:yes, for executables
# lib.a static archive
# "both,no" lib.so.V(shr.o) shared, rtl:yes
# lib.a(lib.so.V) shared, rtl:no, for executables
# "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
# lib.a(lib.so.V) shared, rtl:no
# "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
# lib.a static archive
case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
for ld_flag in $LDFLAGS; do
case $ld_flag in
*-brtl*)
aix_use_runtimelinking=yes
break
;;
esac
done
if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
# With aix-soname=svr4, we create the lib.so.V shared archives only,
# so we don't have lib.a shared libs to link our executables.
# We have to force runtime linking in this case.
aix_use_runtimelinking=yes
LDFLAGS="$LDFLAGS -Wl,-brtl"
fi
;;
esac
exp_sym_flag='-bexport'
no_entry_flag='-bnoentry'
fi
# When large executables or shared objects are built, AIX ld can
# have problems creating the table of contents. If linking a library
# or program results in "error TOC overflow" add -mminimal-toc to
# CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
# enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
_LT_TAGVAR(archive_cmds, $1)=''
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='$wl-f,'
case $with_aix_soname,$aix_use_runtimelinking in
aix,*) ;; # no import file
svr4,* | *,yes) # use import file
# The Import File defines what to hardcode.
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
;;
esac
if test yes = "$GXX"; then
case $host_os in aix4.[[012]]|aix4.[[012]].*)
# We only want to do this on AIX 4.2 and lower, the check
# below for broken collect2 doesn't work under 4.3+
collect2name=`$CC -print-prog-name=collect2`
if test -f "$collect2name" &&
strings "$collect2name" | $GREP resolve_lib_name >/dev/null
then
# We have reworked collect2
:
else
# We have old collect2
_LT_TAGVAR(hardcode_direct, $1)=unsupported
# It fails to find uninstalled libraries when the uninstalled
# path is not listed in the libpath. Setting hardcode_minus_L
# to unsupported forces relinking
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=
fi
esac
shared_flag='-shared'
if test yes = "$aix_use_runtimelinking"; then
shared_flag=$shared_flag' $wl-G'
fi
# Need to ensure runtime linking is disabled for the traditional
# shared library, or the linker may eventually find shared libraries
# /with/ Import File - we do not want to mix them.
shared_flag_aix='-shared'
shared_flag_svr4='-shared $wl-G'
else
# not using gcc
if test ia64 = "$host_cpu"; then
# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
# chokes on -Wl,-G. The following line is correct:
shared_flag='-G'
else
if test yes = "$aix_use_runtimelinking"; then
shared_flag='$wl-G'
else
shared_flag='$wl-bM:SRE'
fi
shared_flag_aix='$wl-bM:SRE'
shared_flag_svr4='$wl-G'
fi
fi
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
# It seems that -bexpall does not export symbols beginning with
# underscore (_), so it is better to generate a list of symbols to
# export.
_LT_TAGVAR(always_export_symbols, $1)=yes
if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
# Warning - without using the other runtime loading flags (-brtl),
# -berok will link without error, but may produce a broken library.
# The "-G" linker flag allows undefined symbols.
_LT_TAGVAR(no_undefined_flag, $1)='-bernotok'
# Determine the default libpath from the value encoded in an empty
# executable.
_LT_SYS_MODULE_PATH_AIX([$1])
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
else
if test ia64 = "$host_cpu"; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
_LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
_LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
else
# Determine the default libpath from the value encoded in an
# empty executable.
_LT_SYS_MODULE_PATH_AIX([$1])
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
# Warning - without using the other run time loading flags,
# -berok will link without error, but may produce a broken library.
_LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
if test yes = "$with_gnu_ld"; then
# We only use this code for GNU lds that support --whole-archive.
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
else
# Exported symbols can be pulled into shared objects from archives
_LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
_LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
# -brtl affects multiple linker settings, -berok does not and is overridden later
compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
if test svr4 != "$with_aix_soname"; then
# This is similar to how AIX traditionally builds its shared
# libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
fi
if test aix != "$with_aix_soname"; then
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
else
# used by -dlpreopen to get the symbols
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
fi
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
fi
fi
;;
beos*)
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
# Joseph Beckenbach says some releases of gcc
# support --undefined. This deserves some investigation. FIXME
_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
chorus*)
case $cc_basename in
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
cygwin* | mingw* | pw32* | cegcc*)
case $GXX,$cc_basename in
,cl* | no,cl*)
# Native MSVC
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
# Tell ltmain to make .lib files, not .a files.
libext=lib
# Tell ltmain to make .dll files, not .so files.
shrext_cmds=.dll
# FIXME: Setting linknames here is a bad hack.
_LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
cp "$export_symbols" "$output_objdir/$soname.def";
echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
else
$SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
fi~
$CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
linknames='
# The linker will not automatically build a static lib if we build a DLL.
# _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
# Don't use ranlib
_LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
_LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
lt_tool_outputfile="@TOOL_OUTPUT@"~
case $lt_outputfile in
*.exe|*.EXE) ;;
*)
lt_outputfile=$lt_outputfile.exe
lt_tool_outputfile=$lt_tool_outputfile.exe
;;
esac~
func_to_tool_file "$lt_outputfile"~
if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
$MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
$RM "$lt_outputfile.manifest";
fi'
;;
*)
# g++
# _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
# as there is no search path for DLLs.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
# If the export-symbols file already is a .def file, use it as
# is; otherwise, prepend EXPORTS...
_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
cp $export_symbols $output_objdir/$soname.def;
else
echo EXPORTS > $output_objdir/$soname.def;
cat $export_symbols >> $output_objdir/$soname.def;
fi~
$CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
darwin* | rhapsody*)
_LT_DARWIN_LINKER_FEATURES($1)
;;
os2*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
shrext_cmds=.dll
_LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
prefix_cmds="$SED"~
if test EXPORTS = "`$SED 1q $export_symbols`"; then
prefix_cmds="$prefix_cmds -e 1d";
fi~
prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
;;
dgux*)
case $cc_basename in
ec++*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
ghcx*)
# Green Hills C++ Compiler
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
freebsd2.*)
# C++ shared libraries reported to be fairly broken before
# switch to ELF
_LT_TAGVAR(ld_shlibs, $1)=no
;;
freebsd-elf*)
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
;;
freebsd* | dragonfly*)
# FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
# conventions
_LT_TAGVAR(ld_shlibs, $1)=yes
;;
haiku*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(link_all_deplibs, $1)=yes
;;
hpux9*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
# but as the default
# location of the library.
case $cc_basename in
CC*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
aCC*)
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;;
*)
if test yes = "$GXX"; then
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
else
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
hpux10*|hpux11*)
if test no = "$with_gnu_ld"; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
case $host_cpu in
hppa*64*|ia64*)
;;
*)
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
;;
esac
fi
case $host_cpu in
hppa*64*|ia64*)
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*)
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
# but as the default
# location of the library.
;;
esac
case $cc_basename in
CC*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
aCC*)
case $host_cpu in
hppa*64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
ia64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
esac
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;;
*)
if test yes = "$GXX"; then
if test no = "$with_gnu_ld"; then
case $host_cpu in
hppa*64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
ia64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
esac
fi
else
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
interix[[3-9]]*)
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
# Instead, shared libraries are loaded at an image base (0x10000000 by
# default) and relocated if they conflict, which is a slow very memory
# consuming and fragmenting process. To avoid this, we pick a random,
# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
# time. Moving up from 0x10000000 also allows more sbrk(2) space.
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
;;
irix5* | irix6*)
case $cc_basename in
CC*)
# SGI C++
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
# Archives containing C++ object files must be created using
# "CC -ar", where "CC" is the IRIX C++ compiler. This is
# necessary to make sure instantiated templates are included
# in the archive.
_LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
;;
*)
if test yes = "$GXX"; then
if test no = "$with_gnu_ld"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
else
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
fi
fi
_LT_TAGVAR(link_all_deplibs, $1)=yes
;;
esac
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(inherit_rpath, $1)=yes
;;
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
case $cc_basename in
KCC*)
# Kuck and Associates, Inc. (KAI) C++ Compiler
# KCC will only create a shared library if the output file
# ends with ".so" (or ".sl" for HP-UX), so rename the library
# to its proper name (with version) after linking.
_LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
# Archives containing C++ object files must be created using
# "CC -Bstatic", where "CC" is the KAI C++ compiler.
_LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
;;
icpc* | ecpc* )
# Intel C++
with_gnu_ld=yes
# version 8.0 and above of icpc choke on multiply defined symbols
# if we add $predep_objects and $postdep_objects, however 7.1 and
# earlier do not add the objects themselves.
case `$CC -V 2>&1` in
*"Version 7."*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
;;
*) # Version 8.0 or newer
tmp_idyn=
case $host_cpu in
ia64*) tmp_idyn=' -i_dynamic';;
esac
_LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
;;
esac
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
;;
pgCC* | pgcpp*)
# Portland Group C++ compiler
case `$CC -V` in
*pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
_LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
_LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
$RANLIB $oldlib'
_LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
;;
*) # Version 6 and above use weak symbols
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
;;
esac
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
;;
cxx*)
# Compaq C++
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols'
runpath_var=LD_RUN_PATH
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
;;
xl* | mpixl* | bgxl*)
# IBM XL 8.0 on PPC, with GNU ld
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
_LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
if test yes = "$supports_anon_versioning"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
fi
;;
*)
case `$CC -V 2>&1 | sed 5q` in
*Sun\ C*)
# Sun C++ 5.9
_LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
_LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
_LT_TAGVAR(compiler_needs_object, $1)=yes
# Not sure whether something based on
# $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
# would be better.
output_verbose_link_cmd='func_echo_all'
# Archives containing C++ object files must be created using
# "CC -xar", where "CC" is the Sun C++ compiler. This is
# necessary to make sure instantiated templates are included
# in the archive.
_LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
;;
esac
;;
esac
;;
lynxos*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
m88k*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
mvs*)
case $cc_basename in
cxx*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
netbsd*)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
wlarc=
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
fi
# Workaround some broken pre-1.5 toolchains
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
;;
*nto* | *qnx*)
_LT_TAGVAR(ld_shlibs, $1)=yes
;;
openbsd* | bitrig*)
if test -f /usr/libexec/ld.so; then
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
_LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
fi
output_verbose_link_cmd=func_echo_all
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
osf3* | osf4* | osf5*)
case $cc_basename in
KCC*)
# Kuck and Associates, Inc. (KAI) C++ Compiler
# KCC will only create a shared library if the output file
# ends with ".so" (or ".sl" for HP-UX), so rename the library
# to its proper name (with version) after linking.
_LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
# Archives containing C++ object files must be created using
# the KAI C++ compiler.
case $host in
osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
esac
;;
RCC*)
# Rational C++ 2.4.1
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
cxx*)
case $host in
osf3*)
_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
;;
*)
_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
echo "-hidden">> $lib.exp~
$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
$RM $lib.exp'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
;;
esac
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;;
*)
if test yes,no = "$GXX,$with_gnu_ld"; then
_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
case $host in
osf3*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
;;
esac
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
else
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
psos*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
sunos4*)
case $cc_basename in
CC*)
# Sun C++ 4.x
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
lcc*)
# Lucid
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
solaris*)
case $cc_basename in
CC* | sunCC*)
# Sun C++ 4.2, 5.x and Centerline C++
_LT_TAGVAR(archive_cmds_need_lc,$1)=yes
_LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
_LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
$CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
case $host_os in
solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
*)
# The compiler driver will combine and reorder linker options,
# but understands '-z linker_flag'.
# Supported since Solaris 2.6 (maybe 2.5.1?)
_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
;;
esac
_LT_TAGVAR(link_all_deplibs, $1)=yes
output_verbose_link_cmd='func_echo_all'
# Archives containing C++ object files must be created using
# "CC -xar", where "CC" is the Sun C++ compiler. This is
# necessary to make sure instantiated templates are included
# in the archive.
_LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
;;
gcx*)
# Green Hills C++ Compiler
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
# The C++ compiler must be used to create the archive.
_LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
;;
*)
# GNU C++ compiler with Solaris linker
if test yes,no = "$GXX,$with_gnu_ld"; then
_LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs'
if $CC --version | $GREP -v '^2\.7' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
$CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
else
# g++ 2.7 appears to require '-G' NOT '-shared' on this
# platform.
_LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
$CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
case $host_os in
solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
*)
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
;;
esac
fi
;;
esac
;;
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
_LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
runpath_var='LD_RUN_PATH'
case $cc_basename in
CC*)
_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
esac
;;
sysv5* | sco3.2v5* | sco5v6*)
# Note: We CANNOT use -z defs as we might desire, because we do not
# link with -lc, and that would cause any symbols used from libc to
# always be unresolved, which means just about no library would
# ever link correctly. If we're not using GNU ld we use -z text
# though, which does catch some bad symbols but isn't as heavy-handed
# as -z defs.
_LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
_LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
runpath_var='LD_RUN_PATH'
case $cc_basename in
CC*)
_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
'"$_LT_TAGVAR(old_archive_cmds, $1)"
_LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
'"$_LT_TAGVAR(reload_cmds, $1)"
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
esac
;;
tandem*)
case $cc_basename in
NCC*)
# NonStop-UX NCC 3.20
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
vxworks*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
_LT_TAGVAR(GCC, $1)=$GXX
_LT_TAGVAR(LD, $1)=$LD
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
_LT_SYS_HIDDEN_LIBDEPS($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_SYS_DYNAMIC_LINKER($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi # test -n "$compiler"
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
LDCXX=$LD
LD=$lt_save_LD
GCC=$lt_save_GCC
with_gnu_ld=$lt_save_with_gnu_ld
lt_cv_path_LDCXX=$lt_cv_path_LD
lt_cv_path_LD=$lt_save_path_LD
lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
fi # test yes != "$_lt_caught_CXX_error"
AC_LANG_POP
])# _LT_LANG_CXX_CONFIG
# _LT_FUNC_STRIPNAME_CNF
# ----------------------
# func_stripname_cnf prefix suffix name
# strip PREFIX and SUFFIX off of NAME.
# PREFIX and SUFFIX must not contain globbing or regex special
# characters, hashes, percent signs, but SUFFIX may contain a leading
# dot (in which case that matches only a dot).
#
# This function is identical to the (non-XSI) version of func_stripname,
# except this one can be used by m4 code that may be executed by configure,
# rather than the libtool script.
m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
AC_REQUIRE([_LT_DECL_SED])
AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
func_stripname_cnf ()
{
case @S|@2 in
.*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;;
*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;;
esac
} # func_stripname_cnf
])# _LT_FUNC_STRIPNAME_CNF
# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
# ---------------------------------
# Figure out "hidden" library dependencies from verbose
# compiler output when linking a shared library.
# Parse the compiler output and extract the necessary
# objects, libraries and library flags.
m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
# Dependencies to place before and after the object being linked:
_LT_TAGVAR(predep_objects, $1)=
_LT_TAGVAR(postdep_objects, $1)=
_LT_TAGVAR(predeps, $1)=
_LT_TAGVAR(postdeps, $1)=
_LT_TAGVAR(compiler_lib_search_path, $1)=
dnl we can't use the lt_simple_compile_test_code here,
dnl because it contains code intended for an executable,
dnl not a library. It's possible we should let each
dnl tag define a new lt_????_link_test_code variable,
dnl but it's only used here...
m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
int a;
void foo (void) { a = 0; }
_LT_EOF
], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
class Foo
{
public:
Foo (void) { a = 0; }
private:
int a;
};
_LT_EOF
], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
subroutine foo
implicit none
integer*4 a
a=0
return
end
_LT_EOF
], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
subroutine foo
implicit none
integer a
a=0
return
end
_LT_EOF
], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
public class foo {
private int a;
public void bar (void) {
a = 0;
}
};
_LT_EOF
], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
package foo
func foo() {
}
_LT_EOF
])
_lt_libdeps_save_CFLAGS=$CFLAGS
case "$CC $CFLAGS " in #(
*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
esac
dnl Parse the compiler output and extract the necessary
dnl objects, libraries and library flags.
if AC_TRY_EVAL(ac_compile); then
# Parse the compiler output and extract the necessary
# objects, libraries and library flags.
# Sentinel used to keep track of whether or not we are before
# the conftest object file.
pre_test_object_deps_done=no
for p in `eval "$output_verbose_link_cmd"`; do
case $prev$p in
-L* | -R* | -l*)
# Some compilers place space between "-{L,R}" and the path.
# Remove the space.
if test x-L = "$p" ||
test x-R = "$p"; then
prev=$p
continue
fi
# Expand the sysroot to ease extracting the directories later.
if test -z "$prev"; then
case $p in
-L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
-R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
-l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
esac
fi
case $p in
=*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
esac
if test no = "$pre_test_object_deps_done"; then
case $prev in
-L | -R)
# Internal compiler library paths should come after those
# provided the user. The postdeps already come after the
# user supplied libs so there is no need to process them.
if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
_LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p
else
_LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p"
fi
;;
# The "-l" case would never come before the object being
# linked, so don't bother handling this case.
esac
else
if test -z "$_LT_TAGVAR(postdeps, $1)"; then
_LT_TAGVAR(postdeps, $1)=$prev$p
else
_LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p"
fi
fi
prev=
;;
*.lto.$objext) ;; # Ignore GCC LTO objects
*.$objext)
# This assumes that the test object file only shows up
# once in the compiler output.
if test "$p" = "conftest.$objext"; then
pre_test_object_deps_done=yes
continue
fi
if test no = "$pre_test_object_deps_done"; then
if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
_LT_TAGVAR(predep_objects, $1)=$p
else
_LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
fi
else
if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
_LT_TAGVAR(postdep_objects, $1)=$p
else
_LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
fi
fi
;;
*) ;; # Ignore the rest.
esac
done
# Clean up.
rm -f a.out a.exe
else
echo "libtool.m4: error: problem compiling $1 test program"
fi
$RM -f confest.$objext
CFLAGS=$_lt_libdeps_save_CFLAGS
# PORTME: override above test on systems where it is broken
m4_if([$1], [CXX],
[case $host_os in
interix[[3-9]]*)
# Interix 3.5 installs completely hosed .la files for C++, so rather than
# hack all around it, let's just trust "g++" to DTRT.
_LT_TAGVAR(predep_objects,$1)=
_LT_TAGVAR(postdep_objects,$1)=
_LT_TAGVAR(postdeps,$1)=
;;
esac
])
case " $_LT_TAGVAR(postdeps, $1) " in
*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
esac
_LT_TAGVAR(compiler_lib_search_dirs, $1)=
if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
_LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'`
fi
_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
[The directories searched by this compiler when creating a shared library])
_LT_TAGDECL([], [predep_objects], [1],
[Dependencies to place before and after the objects being linked to
create a shared library])
_LT_TAGDECL([], [postdep_objects], [1])
_LT_TAGDECL([], [predeps], [1])
_LT_TAGDECL([], [postdeps], [1])
_LT_TAGDECL([], [compiler_lib_search_path], [1],
[The library search path used internally by the compiler when linking
a shared library])
])# _LT_SYS_HIDDEN_LIBDEPS
# _LT_LANG_F77_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for a Fortran 77 compiler are
# suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_F77_CONFIG],
[AC_LANG_PUSH(Fortran 77)
if test -z "$F77" || test no = "$F77"; then
_lt_disable_F77=yes
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
_LT_TAGVAR(no_undefined_flag, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
# Source file extension for f77 test sources.
ac_ext=f
# Object file extension for compiled f77 test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# No sense in running all these tests if we already determined that
# the F77 compiler isn't working. Some variables (like enable_shared)
# are currently assumed to apply to all compilers on this platform,
# and will be corrupted by setting them based on a non-working compiler.
if test yes != "$_lt_disable_F77"; then
# Code to be used in simple compile tests
lt_simple_compile_test_code="\
subroutine t
return
end
"
# Code to be used in simple link tests
lt_simple_link_test_code="\
program t
end
"
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_GCC=$GCC
lt_save_CFLAGS=$CFLAGS
CC=${F77-"f77"}
CFLAGS=$FFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_CC_BASENAME([$compiler])
GCC=$G77
if test -n "$compiler"; then
AC_MSG_CHECKING([if libtool supports shared libraries])
AC_MSG_RESULT([$can_build_shared])
AC_MSG_CHECKING([whether to build shared libraries])
test no = "$can_build_shared" && enable_shared=no
# On AIX, shared libraries and static libraries use the same namespace, and
# are all built from PIC.
case $host_os in
aix3*)
test yes = "$enable_shared" && enable_static=no
if test -n "$RANLIB"; then
archive_cmds="$archive_cmds~\$RANLIB \$lib"
postinstall_cmds='$RANLIB $lib'
fi
;;
aix[[4-9]]*)
if test ia64 != "$host_cpu"; then
case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
yes,aix,yes) ;; # shared object as lib.so file only
yes,svr4,*) ;; # shared object as lib.so archive member only
yes,*) enable_static=no ;; # shared object in lib.a archive as well
esac
fi
;;
esac
AC_MSG_RESULT([$enable_shared])
AC_MSG_CHECKING([whether to build static libraries])
# Make sure either enable_shared or enable_static is yes.
test yes = "$enable_shared" || enable_static=yes
AC_MSG_RESULT([$enable_static])
_LT_TAGVAR(GCC, $1)=$G77
_LT_TAGVAR(LD, $1)=$LD
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_SYS_DYNAMIC_LINKER($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi # test -n "$compiler"
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
fi # test yes != "$_lt_disable_F77"
AC_LANG_POP
])# _LT_LANG_F77_CONFIG
# _LT_LANG_FC_CONFIG([TAG])
# -------------------------
# Ensure that the configuration variables for a Fortran compiler are
# suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_FC_CONFIG],
[AC_LANG_PUSH(Fortran)
if test -z "$FC" || test no = "$FC"; then
_lt_disable_FC=yes
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
_LT_TAGVAR(no_undefined_flag, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
# Source file extension for fc test sources.
ac_ext=${ac_fc_srcext-f}
# Object file extension for compiled fc test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# No sense in running all these tests if we already determined that
# the FC compiler isn't working. Some variables (like enable_shared)
# are currently assumed to apply to all compilers on this platform,
# and will be corrupted by setting them based on a non-working compiler.
if test yes != "$_lt_disable_FC"; then
# Code to be used in simple compile tests
lt_simple_compile_test_code="\
subroutine t
return
end
"
# Code to be used in simple link tests
lt_simple_link_test_code="\
program t
end
"
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_GCC=$GCC
lt_save_CFLAGS=$CFLAGS
CC=${FC-"f95"}
CFLAGS=$FCFLAGS
compiler=$CC
GCC=$ac_cv_fc_compiler_gnu
_LT_TAGVAR(compiler, $1)=$CC
_LT_CC_BASENAME([$compiler])
if test -n "$compiler"; then
AC_MSG_CHECKING([if libtool supports shared libraries])
AC_MSG_RESULT([$can_build_shared])
AC_MSG_CHECKING([whether to build shared libraries])
test no = "$can_build_shared" && enable_shared=no
# On AIX, shared libraries and static libraries use the same namespace, and
# are all built from PIC.
case $host_os in
aix3*)
test yes = "$enable_shared" && enable_static=no
if test -n "$RANLIB"; then
archive_cmds="$archive_cmds~\$RANLIB \$lib"
postinstall_cmds='$RANLIB $lib'
fi
;;
aix[[4-9]]*)
if test ia64 != "$host_cpu"; then
case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
yes,aix,yes) ;; # shared object as lib.so file only
yes,svr4,*) ;; # shared object as lib.so archive member only
yes,*) enable_static=no ;; # shared object in lib.a archive as well
esac
fi
;;
esac
AC_MSG_RESULT([$enable_shared])
AC_MSG_CHECKING([whether to build static libraries])
# Make sure either enable_shared or enable_static is yes.
test yes = "$enable_shared" || enable_static=yes
AC_MSG_RESULT([$enable_static])
_LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu
_LT_TAGVAR(LD, $1)=$LD
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
_LT_SYS_HIDDEN_LIBDEPS($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_SYS_DYNAMIC_LINKER($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi # test -n "$compiler"
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
fi # test yes != "$_lt_disable_FC"
AC_LANG_POP
])# _LT_LANG_FC_CONFIG
# _LT_LANG_GCJ_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for the GNU Java Compiler compiler
# are suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_GCJ_CONFIG],
[AC_REQUIRE([LT_PROG_GCJ])dnl
AC_LANG_SAVE
# Source file extension for Java test sources.
ac_ext=java
# Object file extension for compiled Java test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code="class foo {}"
# Code to be used in simple link tests
lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=yes
CC=${GCJ-"gcj"}
CFLAGS=$GCJFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_TAGVAR(LD, $1)=$LD
_LT_CC_BASENAME([$compiler])
# GCJ did not exist at the time GCC didn't implicitly link libc in.
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
if test -n "$compiler"; then
_LT_COMPILER_NO_RTTI($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi
AC_LANG_RESTORE
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_GCJ_CONFIG
# _LT_LANG_GO_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for the GNU Go compiler
# are suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_GO_CONFIG],
[AC_REQUIRE([LT_PROG_GO])dnl
AC_LANG_SAVE
# Source file extension for Go test sources.
ac_ext=go
# Object file extension for compiled Go test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code="package main; func main() { }"
# Code to be used in simple link tests
lt_simple_link_test_code='package main; func main() { }'
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=yes
CC=${GOC-"gccgo"}
CFLAGS=$GOFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_TAGVAR(LD, $1)=$LD
_LT_CC_BASENAME([$compiler])
# Go did not exist at the time GCC didn't implicitly link libc in.
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
if test -n "$compiler"; then
_LT_COMPILER_NO_RTTI($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi
AC_LANG_RESTORE
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_GO_CONFIG
# _LT_LANG_RC_CONFIG([TAG])
# -------------------------
# Ensure that the configuration variables for the Windows resource compiler
# are suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_RC_CONFIG],
[AC_REQUIRE([LT_PROG_RC])dnl
AC_LANG_SAVE
# Source file extension for RC test sources.
ac_ext=rc
# Object file extension for compiled RC test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
# Code to be used in simple link tests
lt_simple_link_test_code=$lt_simple_compile_test_code
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=
CC=${RC-"windres"}
CFLAGS=
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_CC_BASENAME([$compiler])
_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
if test -n "$compiler"; then
:
_LT_CONFIG($1)
fi
GCC=$lt_save_GCC
AC_LANG_RESTORE
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_RC_CONFIG
# LT_PROG_GCJ
# -----------
AC_DEFUN([LT_PROG_GCJ],
[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
[m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
[AC_CHECK_TOOL(GCJ, gcj,)
test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2"
AC_SUBST(GCJFLAGS)])])[]dnl
])
# Old name:
AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
# LT_PROG_GO
# ----------
AC_DEFUN([LT_PROG_GO],
[AC_CHECK_TOOL(GOC, gccgo,)
])
# LT_PROG_RC
# ----------
AC_DEFUN([LT_PROG_RC],
[AC_CHECK_TOOL(RC, windres,)
])
# Old name:
AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([LT_AC_PROG_RC], [])
# _LT_DECL_EGREP
# --------------
# If we don't have a new enough Autoconf to choose the best grep
# available, choose the one first in the user's PATH.
m4_defun([_LT_DECL_EGREP],
[AC_REQUIRE([AC_PROG_EGREP])dnl
AC_REQUIRE([AC_PROG_FGREP])dnl
test -z "$GREP" && GREP=grep
_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
_LT_DECL([], [EGREP], [1], [An ERE matcher])
_LT_DECL([], [FGREP], [1], [A literal string matcher])
dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
AC_SUBST([GREP])
])
# _LT_DECL_OBJDUMP
# --------------
# If we don't have a new enough Autoconf to choose the best objdump
# available, choose the one first in the user's PATH.
m4_defun([_LT_DECL_OBJDUMP],
[AC_CHECK_TOOL(OBJDUMP, objdump, false)
test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
AC_SUBST([OBJDUMP])
])
# _LT_DECL_DLLTOOL
# ----------------
# Ensure DLLTOOL variable is set.
m4_defun([_LT_DECL_DLLTOOL],
[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
AC_SUBST([DLLTOOL])
])
# _LT_DECL_SED
# ------------
# Check for a fully-functional sed program, that truncates
# as few characters as possible. Prefer GNU sed if found.
m4_defun([_LT_DECL_SED],
[AC_PROG_SED
test -z "$SED" && SED=sed
Xsed="$SED -e 1s/^X//"
_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
[Sed that helps us avoid accidentally triggering echo(1) options like -n])
])# _LT_DECL_SED
m4_ifndef([AC_PROG_SED], [
# NOTE: This macro has been submitted for inclusion into #
# GNU Autoconf as AC_PROG_SED. When it is available in #
# a released version of Autoconf we should remove this #
# macro and use it instead. #
m4_defun([AC_PROG_SED],
[AC_MSG_CHECKING([for a sed that does not truncate output])
AC_CACHE_VAL(lt_cv_path_SED,
[# Loop through the user's path and test for sed and gsed.
# Then use that list of sed's as ones to test for truncation.
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for lt_ac_prog in sed gsed; do
for ac_exec_ext in '' $ac_executable_extensions; do
if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
fi
done
done
done
IFS=$as_save_IFS
lt_ac_max=0
lt_ac_count=0
# Add /usr/xpg4/bin/sed as it is typically found on Solaris
# along with /bin/sed that truncates output.
for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
test ! -f "$lt_ac_sed" && continue
cat /dev/null > conftest.in
lt_ac_count=0
echo $ECHO_N "0123456789$ECHO_C" >conftest.in
# Check for GNU sed and select it if it is found.
if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
lt_cv_path_SED=$lt_ac_sed
break
fi
while true; do
cat conftest.in conftest.in >conftest.tmp
mv conftest.tmp conftest.in
cp conftest.in conftest.nl
echo >>conftest.nl
$lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
cmp -s conftest.out conftest.nl || break
# 10000 chars as input seems more than enough
test 10 -lt "$lt_ac_count" && break
lt_ac_count=`expr $lt_ac_count + 1`
if test "$lt_ac_count" -gt "$lt_ac_max"; then
lt_ac_max=$lt_ac_count
lt_cv_path_SED=$lt_ac_sed
fi
done
done
])
SED=$lt_cv_path_SED
AC_SUBST([SED])
AC_MSG_RESULT([$SED])
])#AC_PROG_SED
])#m4_ifndef
# Old name:
AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([LT_AC_PROG_SED], [])
# _LT_CHECK_SHELL_FEATURES
# ------------------------
# Find out whether the shell is Bourne or XSI compatible,
# or has some other useful features.
m4_defun([_LT_CHECK_SHELL_FEATURES],
[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
lt_unset=unset
else
lt_unset=false
fi
_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
# test EBCDIC or ASCII
case `echo X|tr X '\101'` in
A) # ASCII based system
# \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
lt_SP2NL='tr \040 \012'
lt_NL2SP='tr \015\012 \040\040'
;;
*) # EBCDIC based system
lt_SP2NL='tr \100 \n'
lt_NL2SP='tr \r\n \100\100'
;;
esac
_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
])# _LT_CHECK_SHELL_FEATURES
# _LT_PATH_CONVERSION_FUNCTIONS
# -----------------------------
# Determine what file name conversion functions should be used by
# func_to_host_file (and, implicitly, by func_to_host_path). These are needed
# for certain cross-compile configurations and native mingw.
m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
AC_MSG_CHECKING([how to convert $build file names to $host format])
AC_CACHE_VAL(lt_cv_to_host_file_cmd,
[case $host in
*-*-mingw* )
case $build in
*-*-mingw* ) # actually msys
lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
;;
*-*-cygwin* )
lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
;;
* ) # otherwise, assume *nix
lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
;;
esac
;;
*-*-cygwin* )
case $build in
*-*-mingw* ) # actually msys
lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
;;
*-*-cygwin* )
lt_cv_to_host_file_cmd=func_convert_file_noop
;;
* ) # otherwise, assume *nix
lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
;;
esac
;;
* ) # unhandled hosts (and "normal" native builds)
lt_cv_to_host_file_cmd=func_convert_file_noop
;;
esac
])
to_host_file_cmd=$lt_cv_to_host_file_cmd
AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
[0], [convert $build file names to $host format])dnl
AC_MSG_CHECKING([how to convert $build file names to toolchain format])
AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
[#assume ordinary cross tools, or native build.
lt_cv_to_tool_file_cmd=func_convert_file_noop
case $host in
*-*-mingw* )
case $build in
*-*-mingw* ) # actually msys
lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
;;
esac
;;
esac
])
to_tool_file_cmd=$lt_cv_to_tool_file_cmd
AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
[0], [convert $build files to toolchain format])dnl
])# _LT_PATH_CONVERSION_FUNCTIONS
# Helper functions for option handling. -*- Autoconf -*-
#
# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# 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 ltoptions.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
# ------------------------------------------
m4_define([_LT_MANGLE_OPTION],
[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
# ---------------------------------------
# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
# matching handler defined, dispatch to it. Other OPTION-NAMEs are
# saved as a flag.
m4_define([_LT_SET_OPTION],
[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
_LT_MANGLE_DEFUN([$1], [$2]),
[m4_warning([Unknown $1 option '$2'])])[]dnl
])
# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
# ------------------------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
m4_define([_LT_IF_OPTION],
[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
# -------------------------------------------------------
# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
# are set.
m4_define([_LT_UNLESS_OPTIONS],
[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
[m4_define([$0_found])])])[]dnl
m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
])[]dnl
])
# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
# ----------------------------------------
# OPTION-LIST is a space-separated list of Libtool options associated
# with MACRO-NAME. If any OPTION has a matching handler declared with
# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
# the unknown option and exit.
m4_defun([_LT_SET_OPTIONS],
[# Set options
m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[_LT_SET_OPTION([$1], _LT_Option)])
m4_if([$1],[LT_INIT],[
dnl
dnl Simply set some default values (i.e off) if boolean options were not
dnl specified:
_LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
])
_LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
])
dnl
dnl If no reference was made to various pairs of opposing options, then
dnl we run the default mode handler for the pair. For example, if neither
dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
dnl archives by default:
_LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
_LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
_LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
_LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
[_LT_ENABLE_FAST_INSTALL])
_LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
[_LT_WITH_AIX_SONAME([aix])])
])
])# _LT_SET_OPTIONS
# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
# -----------------------------------------
m4_define([_LT_MANGLE_DEFUN],
[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
# -----------------------------------------------
m4_define([LT_OPTION_DEFINE],
[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
])# LT_OPTION_DEFINE
# dlopen
# ------
LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
])
AU_DEFUN([AC_LIBTOOL_DLOPEN],
[_LT_SET_OPTION([LT_INIT], [dlopen])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'dlopen' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
# win32-dll
# ---------
# Declare package support for building win32 dll's.
LT_OPTION_DEFINE([LT_INIT], [win32-dll],
[enable_win32_dll=yes
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
AC_CHECK_TOOL(AS, as, false)
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(OBJDUMP, objdump, false)
;;
esac
test -z "$AS" && AS=as
_LT_DECL([], [AS], [1], [Assembler program])dnl
test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
])# win32-dll
AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
_LT_SET_OPTION([LT_INIT], [win32-dll])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'win32-dll' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
# _LT_ENABLE_SHARED([DEFAULT])
# ----------------------------
# implement the --enable-shared flag, and supports the 'shared' and
# 'disable-shared' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_SHARED],
[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([shared],
[AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_shared=yes ;;
no) enable_shared=no ;;
*)
enable_shared=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_shared=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
_LT_DECL([build_libtool_libs], [enable_shared], [0],
[Whether or not to build shared libraries])
])# _LT_ENABLE_SHARED
LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
# Old names:
AC_DEFUN([AC_ENABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
])
AC_DEFUN([AC_DISABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], [disable-shared])
])
AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_SHARED], [])
dnl AC_DEFUN([AM_DISABLE_SHARED], [])
# _LT_ENABLE_STATIC([DEFAULT])
# ----------------------------
# implement the --enable-static flag, and support the 'static' and
# 'disable-static' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_STATIC],
[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([static],
[AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_static=yes ;;
no) enable_static=no ;;
*)
enable_static=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_static=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[enable_static=]_LT_ENABLE_STATIC_DEFAULT)
_LT_DECL([build_old_libs], [enable_static], [0],
[Whether or not to build static libraries])
])# _LT_ENABLE_STATIC
LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
# Old names:
AC_DEFUN([AC_ENABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
])
AC_DEFUN([AC_DISABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], [disable-static])
])
AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_STATIC], [])
dnl AC_DEFUN([AM_DISABLE_STATIC], [])
# _LT_ENABLE_FAST_INSTALL([DEFAULT])
# ----------------------------------
# implement the --enable-fast-install flag, and support the 'fast-install'
# and 'disable-fast-install' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_FAST_INSTALL],
[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([fast-install],
[AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
[optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_fast_install=yes ;;
no) enable_fast_install=no ;;
*)
enable_fast_install=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_fast_install=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
_LT_DECL([fast_install], [enable_fast_install], [0],
[Whether or not to optimize for fast installation])dnl
])# _LT_ENABLE_FAST_INSTALL
LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
# Old names:
AU_DEFUN([AC_ENABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the 'fast-install' option into LT_INIT's first parameter.])
])
AU_DEFUN([AC_DISABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the 'disable-fast-install' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
# _LT_WITH_AIX_SONAME([DEFAULT])
# ----------------------------------
# implement the --with-aix-soname flag, and support the `aix-soname=aix'
# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'.
m4_define([_LT_WITH_AIX_SONAME],
[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
shared_archive_member_spec=
case $host,$enable_shared in
power*-*-aix[[5-9]]*,yes)
AC_MSG_CHECKING([which variant of shared library versioning to provide])
AC_ARG_WITH([aix-soname],
[AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
[shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
[case $withval in
aix|svr4|both)
;;
*)
AC_MSG_ERROR([Unknown argument to --with-aix-soname])
;;
esac
lt_cv_with_aix_soname=$with_aix_soname],
[AC_CACHE_VAL([lt_cv_with_aix_soname],
[lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
with_aix_soname=$lt_cv_with_aix_soname])
AC_MSG_RESULT([$with_aix_soname])
if test aix != "$with_aix_soname"; then
# For the AIX way of multilib, we name the shared archive member
# based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
# and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
# Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
# the AIX toolchain works better with OBJECT_MODE set (default 32).
if test 64 = "${OBJECT_MODE-32}"; then
shared_archive_member_spec=shr_64
else
shared_archive_member_spec=shr
fi
fi
;;
*)
with_aix_soname=aix
;;
esac
_LT_DECL([], [shared_archive_member_spec], [0],
[Shared archive member basename, for filename based shared library versioning on AIX])dnl
])# _LT_WITH_AIX_SONAME
LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
# _LT_WITH_PIC([MODE])
# --------------------
# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
# LT_INIT options.
# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'.
m4_define([_LT_WITH_PIC],
[AC_ARG_WITH([pic],
[AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
[lt_p=${PACKAGE-default}
case $withval in
yes|no) pic_mode=$withval ;;
*)
pic_mode=default
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for lt_pkg in $withval; do
IFS=$lt_save_ifs
if test "X$lt_pkg" = "X$lt_p"; then
pic_mode=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[pic_mode=m4_default([$1], [default])])
_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
])# _LT_WITH_PIC
LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
# Old name:
AU_DEFUN([AC_LIBTOOL_PICMODE],
[_LT_SET_OPTION([LT_INIT], [pic-only])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'pic-only' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
m4_define([_LTDL_MODE], [])
LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
[m4_define([_LTDL_MODE], [nonrecursive])])
LT_OPTION_DEFINE([LTDL_INIT], [recursive],
[m4_define([_LTDL_MODE], [recursive])])
LT_OPTION_DEFINE([LTDL_INIT], [subproject],
[m4_define([_LTDL_MODE], [subproject])])
m4_define([_LTDL_TYPE], [])
LT_OPTION_DEFINE([LTDL_INIT], [installable],
[m4_define([_LTDL_TYPE], [installable])])
LT_OPTION_DEFINE([LTDL_INIT], [convenience],
[m4_define([_LTDL_TYPE], [convenience])])
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# 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 6 ltsugar.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59, which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
[$#], 1, [],
[m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
[m4_foreach([_Lt_suffix],
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
[lt_append([$1], [$2], [$3])$4],
[$5])],
[lt_append([$1], [$2], [$3])$4])])
# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])
# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
[$5],
[$6])])
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
[lt_join(m4_quote(m4_default([$4], [[, ]])),
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004
#
# 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.
# @configure_input@
# serial 4179 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.4.6])
m4_define([LT_PACKAGE_REVISION], [2.4.6])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.4.6'
macro_revision='2.4.6'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software
# Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# 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 5 lt~obsolete.m4
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else. This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
# Copyright (C) 2002-2014 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.
# (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.15'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.15], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
# _AM_AUTOCONF_VERSION(VERSION)
# -----------------------------
# aclocal traces this macro to find the Autoconf version.
# This is a private macro too. Using m4_define simplifies
# the logic in aclocal, which can simply ignore this definition.
m4_define([_AM_AUTOCONF_VERSION], [])
# AM_SET_CURRENT_AUTOMAKE_VERSION
# -------------------------------
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.15])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001-2014 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],
[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
# Expand $ac_aux_dir to an absolute path.
am_aux_dir=`cd "$ac_aux_dir" && pwd`
])
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2014 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_CONDITIONAL(NAME, SHELL-CONDITION)
# -------------------------------------
# Define a conditional.
AC_DEFUN([AM_CONDITIONAL],
[AC_PREREQ([2.52])dnl
m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
AC_SUBST([$1_TRUE])dnl
AC_SUBST([$1_FALSE])dnl
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
m4_define([_AM_COND_VALUE_$1], [$2])dnl
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-2014 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.
# 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", "OBJC", "OBJCXX", "UPC", or "GJC".
# 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
m4_if([$1], [CC], [depcc="$CC" am_compiler_list=],
[$1], [CXX], [depcc="$CXX" am_compiler_list=],
[$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
[$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
[$1], [UPC], [depcc="$UPC" am_compiler_list=],
[$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".
rm -rf conftest.dir
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
am__universal=false
m4_case([$1], [CC],
[case " $depcc " in #(
*\ -arch\ *\ -arch\ *) am__universal=true ;;
esac],
[CXX],
[case " $depcc " in #(
*\ -arch\ *\ -arch\ *) am__universal=true ;;
esac])
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 10 /bin/sh.
echo '/* dummy */' > sub/conftst$i.h
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
# 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. Also, some Intel
# versions had trouble with output in subdirs.
am__obj=sub/conftest.${OBJEXT-o}
am__minus_obj="-o $am__obj"
case $depmode in
gcc)
# This depmode causes a compiler race in universal mode.
test "$am__universal" = false || continue
;;
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
;;
msvc7 | msvc7msys | msvisualcpp | msvcmsys)
# This compiler won't grok '-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
am__obj=conftest.${OBJEXT-o}
am__minus_obj=
;;
none) break ;;
esac
if depmode=$depmode \
source=sub/conftest.c object=$am__obj \
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
$SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
>/dev/null 2>conftest.err &&
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
grep $am__obj 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], [dnl
AS_HELP_STRING(
[--enable-dependency-tracking],
[do not reject slow dependency extractors])
AS_HELP_STRING(
[--disable-dependency-tracking],
[speeds up one-time build])])
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
am__nodep='_no'
fi
AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
AC_SUBST([AMDEPBACKSLASH])dnl
_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
AC_SUBST([am__nodep])dnl
_AM_SUBST_NOTMAKE([am__nodep])dnl
])
# Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999-2014 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_OUTPUT_DEPENDENCY_COMMANDS
# ------------------------------
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
[{
# Older Autoconf quotes --file arguments for eval, but not when files
# are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting.
case $CONFIG_FILES in
*\'*) eval set x "$CONFIG_FILES" ;;
*) set x $CONFIG_FILES ;;
esac
shift
for mf
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.
# Grep'ing the whole file is not good either: AIX grep has a line
# limit of 2048, but all sed's we know have understand at least 4000.
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/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"`
# 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'`; 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"])
])
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996-2014 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 macro actually does too much. Some checks are only needed if
# your package does certain things. But this isn't really a big deal.
dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
m4_define([AC_PROG_CC],
m4_defn([AC_PROG_CC])
[_AM_PROG_CC_C_O
])
# 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.65])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
if test "`cd $srcdir && pwd`" != "`pwd`"; then
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
# is not polluted with repeated "-I."
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
# test to see if srcdir already configured
if test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
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],
[AC_DIAGNOSE([obsolete],
[$0: two- and three-arguments forms are deprecated.])
m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
AC_SUBST([PACKAGE], [$1])dnl
AC_SUBST([VERSION], [$2])],
[_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
m4_if(
m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
[ok:ok],,
[m4_fatal([AC_INIT should be called with package and version arguments])])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])
AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
# For better backward compatibility. To be removed once Automake 1.9.x
# dies out for good. For more background, see:
#
#
AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
# We need awk for the "check" target (and possibly the TAP driver). 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])],
[m4_define([AC_PROG_CC],
m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
AC_PROVIDE_IFELSE([AC_PROG_CXX],
[_AM_DEPENDENCIES([CXX])],
[m4_define([AC_PROG_CXX],
m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
[_AM_DEPENDENCIES([OBJC])],
[m4_define([AC_PROG_OBJC],
m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
[_AM_DEPENDENCIES([OBJCXX])],
[m4_define([AC_PROG_OBJCXX],
m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
])
AC_REQUIRE([AM_SILENT_RULES])dnl
dnl The testsuite driver may need to know about EXEEXT, so add the
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
AC_CONFIG_COMMANDS_PRE(dnl
[m4_provide_if([_AM_COMPILER_EXEEXT],
[AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
# POSIX will say in a future version that running "rm -f" with no argument
# is OK; and we want to be able to make that assumption in our Makefile
# recipes. So use an aggressive probe to check that the usage we want is
# actually supported "in the wild" to an acceptable degree.
# See automake bug#10828.
# To make any issue more visible, cause the running configure to be aborted
# by default if the 'rm' program in use doesn't match our expectations; the
# user can still override this though.
if rm -f && rm -fr && rm -rf; then : OK; else
cat >&2 <<'END'
Oops!
Your 'rm' program seems unable to run without file operands specified
on the command line, even when the '-f' option is present. This is contrary
to the behaviour of most rm programs out there, and not conforming with
the upcoming POSIX standard:
Please tell bug-automake@gnu.org about your system, including the value
of your $PATH and any error possibly output before this message. This
can help us improve future automake versions.
END
if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
echo 'Configuration will proceed anyway, since you have set the' >&2
echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
echo >&2
else
cat >&2 <<'END'
Aborting the configuration process, to ensure you take notice of the issue.
You can download and install GNU coreutils to get an 'rm' implementation
that behaves properly: .
If you want to complete the configuration process using your problematic
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
to "yes", and re-run configure.
END
AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
fi
fi
dnl The trailing newline in this macro's definition is deliberate, for
dnl backward compatibility and to allow trailing 'dnl'-style comments
dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
])
dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
dnl mangled by Autoconf and run in a shell conditional statement.
m4_define([_AC_COMPILER_EXEEXT],
m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
# 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_arg=$1
_am_stamp_count=1
for _am_header in $config_headers :; do
case $_am_header in
$_am_arg | $_am_arg:* )
break ;;
* )
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
esac
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001-2014 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
if test x"${install_sh+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
*)
install_sh="\${SHELL} $am_aux_dir/install-sh"
esac
fi
AC_SUBST([install_sh])])
# Copyright (C) 2003-2014 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.
# 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-2014 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_MAKE_INCLUDE()
# -----------------
# Check to see how make treats includes.
AC_DEFUN([AM_MAKE_INCLUDE],
[am_make=${MAKE-make}
cat > confinc << 'END'
am__doit:
@echo this is the am__doit target
.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
# Ignore all kinds of additional output from 'make'.
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=include
am__quote=
_am_result=GNU
;;
esac
# Now try BSD make style include.
if test "$am__include" = "#"; then
echo '.include "confinc"' > confmf
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=.include
am__quote="\""
_am_result=BSD
;;
esac
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-2014 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_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 is modern enough.
# If it is, set am_missing_run to use it, otherwise, to nothing.
AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then
am_missing_run="$MISSING "
else
am_missing_run=
AC_MSG_WARN(['missing' script is too old or missing])
fi
])
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001-2014 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_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],
[m4_foreach_w([_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])])
# Copyright (C) 1999-2014 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_CC_C_O
# ---------------
# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC
# to automatically call this.
AC_DEFUN([_AM_PROG_CC_C_O],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([compile])dnl
AC_LANG_PUSH([C])dnl
AC_CACHE_CHECK(
[whether $CC understands -c and -o together],
[am_cv_prog_cc_c_o],
[AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
# Make sure it works both with $CC and with simple cc.
# Following AC_PROG_CC_C_O, we do the test twice because some
# compilers refuse to overwrite an existing .o file with -o,
# though they will create one.
am_cv_prog_cc_c_o=yes
for am_i in 1 2; do
if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
&& test -f conftest2.$ac_objext; then
: OK
else
am_cv_prog_cc_c_o=no
break
fi
done
rm -f core conftest*
unset am_i])
if test "$am_cv_prog_cc_c_o" != yes; then
# Losing compiler, so override with the script.
# FIXME: It is wrong to rewrite CC.
# But if we don't then we get into trouble of one sort or another.
# A longer-term fix would be to have automake use am__CC in this case,
# and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
CC="$am_aux_dir/compile $CC"
fi
AC_LANG_POP([C])])
# For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
# Copyright (C) 2001-2014 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_RUN_LOG(COMMAND)
# -------------------
# Run COMMAND, save the exit status in ac_status, and log it.
# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
AC_DEFUN([AM_RUN_LOG],
[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
(exit $ac_status); }])
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996-2014 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_SANITY_CHECK
# ---------------
AC_DEFUN([AM_SANITY_CHECK],
[AC_MSG_CHECKING([whether build environment is sane])
# Reject unsafe characters in $srcdir or the absolute working directory
# name. Accept space and tab only in the latter.
am_lf='
'
case `pwd` in
*[[\\\"\#\$\&\'\`$am_lf]]*)
AC_MSG_ERROR([unsafe absolute working directory name]);;
esac
case $srcdir in
*[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
esac
# 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 (
am_has_slept=no
for am_try in 1 2; do
echo "timestamp, slept: $am_has_slept" > conftest.file
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
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
if test "$[2]" = conftest.file || test $am_try -eq 2; then
break
fi
# Just in case.
sleep 1
am_has_slept=yes
done
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])
# If we didn't sleep, we still need to ensure time stamps of config.status and
# generated files are strictly newer.
am_sleep_pid=
if grep 'slept: no' conftest.file >/dev/null 2>&1; then
( sleep 1 ) &
am_sleep_pid=$!
fi
AC_CONFIG_COMMANDS_PRE(
[AC_MSG_CHECKING([that generated files are newer than configure])
if test -n "$am_sleep_pid"; then
# Hide warnings about reused PIDs.
wait $am_sleep_pid 2>/dev/null
fi
AC_MSG_RESULT([done])])
rm -f conftest.file
])
# Copyright (C) 2009-2014 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_SILENT_RULES([DEFAULT])
# --------------------------
# Enable less verbose build rules; with the default set to DEFAULT
# ("yes" being less verbose, "no" or empty being verbose).
AC_DEFUN([AM_SILENT_RULES],
[AC_ARG_ENABLE([silent-rules], [dnl
AS_HELP_STRING(
[--enable-silent-rules],
[less verbose build output (undo: "make V=1")])
AS_HELP_STRING(
[--disable-silent-rules],
[verbose build output (undo: "make V=0")])dnl
])
case $enable_silent_rules in @%:@ (((
yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
*) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
esac
dnl
dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
dnl do not support nested variable expansions.
dnl See automake bug#9928 and bug#10237.
am_make=${MAKE-make}
AC_CACHE_CHECK([whether $am_make supports nested variables],
[am_cv_make_support_nested_variables],
[if AS_ECHO([['TRUE=$(BAR$(V))
BAR0=false
BAR1=true
V=1
am__doit:
@$(TRUE)
.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
am_cv_make_support_nested_variables=yes
else
am_cv_make_support_nested_variables=no
fi])
if test $am_cv_make_support_nested_variables = yes; then
dnl Using '$V' instead of '$(V)' breaks IRIX make.
AM_V='$(V)'
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
AM_V=$AM_DEFAULT_VERBOSITY
AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
AC_SUBST([AM_V])dnl
AM_SUBST_NOTMAKE([AM_V])dnl
AC_SUBST([AM_DEFAULT_V])dnl
AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
AM_BACKSLASH='\'
AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
# Copyright (C) 2001-2014 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="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006-2014 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_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
# This macro is traced by Automake.
AC_DEFUN([_AM_SUBST_NOTMAKE])
# AM_SUBST_NOTMAKE(VARIABLE)
# --------------------------
# Public sister of _AM_SUBST_NOTMAKE.
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004-2014 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_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. Yes, it's still used
# in the wild :-( We should find a proper way to deprecate it ...
AC_SUBST([AMTAR], ['$${TAR-tar}'])
# We'll loop over all known methods to create a tar archive until one works.
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
m4_if([$1], [v7],
[am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
[m4_case([$1],
[ustar],
[# The POSIX 1988 'ustar' format is defined with fixed-size fields.
# There is notably a 21 bits limit for the UID and the GID. In fact,
# the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
# and bug#13588).
am_max_uid=2097151 # 2^21 - 1
am_max_gid=$am_max_uid
# The $UID and $GID variables are not portable, so we need to resort
# to the POSIX-mandated id(1) utility. Errors in the 'id' calls
# below are definitely unexpected, so allow the users to see them
# (that is, avoid stderr redirection).
am_uid=`id -u || echo unknown`
am_gid=`id -g || echo unknown`
AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
if test $am_uid -le $am_max_uid; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
_am_tools=none
fi
AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
if test $am_gid -le $am_max_gid; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
_am_tools=none
fi],
[pax],
[],
[m4_fatal([Unknown tar format])])
AC_MSG_CHECKING([how to create a $1 tar archive])
# Go ahead even if we have the value already cached. We do so because we
# need to set the values for the 'am__tar' and 'am__untar' variables.
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
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
pkg-config-0.29.1/main.c 0000664 0001750 0001750 00000060036 12652721354 011656 0000000 0000000 /*
* Copyright (C) 2001, 2002 Red Hat 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 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "pkg.h"
#include "parse.h"
#include
#include
#include
#include
#ifdef G_OS_WIN32
#define STRICT
#include
#undef STRICT
#endif
char *pcsysrootdir = NULL;
char *pkg_config_pc_path = NULL;
static gboolean want_my_version = FALSE;
static gboolean want_version = FALSE;
static FlagType pkg_flags = 0;
static gboolean want_list = FALSE;
static gboolean want_static_lib_list = ENABLE_INDIRECT_DEPS;
static gboolean want_short_errors = FALSE;
static gboolean want_uninstalled = FALSE;
static char *variable_name = NULL;
static gboolean want_exists = FALSE;
static gboolean want_provides = FALSE;
static gboolean want_requires = FALSE;
static gboolean want_requires_private = FALSE;
static gboolean want_validate = FALSE;
static char *required_atleast_version = NULL;
static char *required_exact_version = NULL;
static char *required_max_version = NULL;
static char *required_pkgconfig_version = NULL;
static gboolean want_silence_errors = FALSE;
static gboolean want_variable_list = FALSE;
static gboolean want_debug_spew = FALSE;
static gboolean want_verbose_errors = FALSE;
static gboolean want_stdout_errors = FALSE;
static gboolean output_opt_set = FALSE;
void
debug_spew (const char *format, ...)
{
va_list args;
gchar *str;
FILE* stream;
g_return_if_fail (format != NULL);
if (!want_debug_spew)
return;
va_start (args, format);
str = g_strdup_vprintf (format, args);
va_end (args);
if (want_stdout_errors)
stream = stdout;
else
stream = stderr;
fputs (str, stream);
fflush (stream);
g_free (str);
}
void
verbose_error (const char *format, ...)
{
va_list args;
gchar *str;
FILE* stream;
g_return_if_fail (format != NULL);
if (!want_verbose_errors)
return;
va_start (args, format);
str = g_strdup_vprintf (format, args);
va_end (args);
if (want_stdout_errors)
stream = stdout;
else
stream = stderr;
fputs (str, stream);
fflush (stream);
g_free (str);
}
static gboolean
define_variable_cb (const char *opt, const char *arg, gpointer data,
GError **error)
{
char *varname;
char *varval;
char *tmp;
tmp = g_strdup (arg);
varname = tmp;
while (*varname && isspace ((guchar)*varname))
++varname;
varval = varname;
while (*varval && *varval != '=' && *varval != ' ')
++varval;
while (*varval && (*varval == '=' || *varval == ' '))
{
*varval = '\0';
++varval;
}
if (*varval == '\0')
{
fprintf (stderr, "--define-variable argument does not have a value "
"for the variable\n");
exit (1);
}
define_global_variable (varname, varval);
g_free (tmp);
return TRUE;
}
static gboolean
output_opt_cb (const char *opt, const char *arg, gpointer data,
GError **error)
{
static gboolean vercmp_opt_set = FALSE;
/* only allow one output mode, with a few exceptions */
if (output_opt_set)
{
gboolean bad_opt = TRUE;
/* multiple flag options (--cflags --libs-only-l) allowed */
if (pkg_flags != 0 &&
(strcmp (opt, "--libs") == 0 ||
strcmp (opt, "--libs-only-l") == 0 ||
strcmp (opt, "--libs-only-other") == 0 ||
strcmp (opt, "--libs-only-L") == 0 ||
strcmp (opt, "--cflags") == 0 ||
strcmp (opt, "--cflags-only-I") == 0 ||
strcmp (opt, "--cflags-only-other") == 0))
bad_opt = FALSE;
/* --print-requires and --print-requires-private allowed */
if ((want_requires && strcmp (opt, "--print-requires-private") == 0) ||
(want_requires_private && strcmp (opt, "--print-requires") == 0))
bad_opt = FALSE;
/* --exists allowed with --atleast/exact/max-version */
if (want_exists && !vercmp_opt_set &&
(strcmp (opt, "--atleast-version") == 0 ||
strcmp (opt, "--exact-version") == 0 ||
strcmp (opt, "--max-version") == 0))
bad_opt = FALSE;
if (bad_opt)
{
fprintf (stderr, "Ignoring incompatible output option \"%s\"\n",
opt);
fflush (stderr);
return TRUE;
}
}
if (strcmp (opt, "--version") == 0)
want_my_version = TRUE;
else if (strcmp (opt, "--modversion") == 0)
want_version = TRUE;
else if (strcmp (opt, "--libs") == 0)
pkg_flags |= LIBS_ANY;
else if (strcmp (opt, "--libs-only-l") == 0)
pkg_flags |= LIBS_l;
else if (strcmp (opt, "--libs-only-other") == 0)
pkg_flags |= LIBS_OTHER;
else if (strcmp (opt, "--libs-only-L") == 0)
pkg_flags |= LIBS_L;
else if (strcmp (opt, "--cflags") == 0)
pkg_flags |= CFLAGS_ANY;
else if (strcmp (opt, "--cflags-only-I") == 0)
pkg_flags |= CFLAGS_I;
else if (strcmp (opt, "--cflags-only-other") == 0)
pkg_flags |= CFLAGS_OTHER;
else if (strcmp (opt, "--variable") == 0)
variable_name = g_strdup (arg);
else if (strcmp (opt, "--exists") == 0)
want_exists = TRUE;
else if (strcmp (opt, "--print-variables") == 0)
want_variable_list = TRUE;
else if (strcmp (opt, "--uninstalled") == 0)
want_uninstalled = TRUE;
else if (strcmp (opt, "--atleast-version") == 0)
{
required_atleast_version = g_strdup (arg);
want_exists = TRUE;
vercmp_opt_set = TRUE;
}
else if (strcmp (opt, "--exact-version") == 0)
{
required_exact_version = g_strdup (arg);
want_exists = TRUE;
vercmp_opt_set = TRUE;
}
else if (strcmp (opt, "--max-version") == 0)
{
required_max_version = g_strdup (arg);
want_exists = TRUE;
vercmp_opt_set = TRUE;
}
else if (strcmp (opt, "--list-all") == 0)
want_list = TRUE;
else if (strcmp (opt, "--print-provides") == 0)
want_provides = TRUE;
else if (strcmp (opt, "--print-requires") == 0)
want_requires = TRUE;
else if (strcmp (opt, "--print-requires-private") == 0)
want_requires_private = TRUE;
else if (strcmp (opt, "--validate") == 0)
want_validate = TRUE;
else
return FALSE;
output_opt_set = TRUE;
return TRUE;
}
static gboolean
pkg_uninstalled (Package *pkg)
{
/* See if > 0 pkgs were uninstalled */
GList *tmp;
if (pkg->uninstalled)
return TRUE;
tmp = pkg->requires;
while (tmp != NULL)
{
Package *pkg = tmp->data;
if (pkg_uninstalled (pkg))
return TRUE;
tmp = g_list_next (tmp);
}
return FALSE;
}
void
print_list_data (gpointer data,
gpointer user_data)
{
g_print ("%s\n", (gchar *)data);
}
static void
init_pc_path (void)
{
#ifdef G_OS_WIN32
char *instdir, *lpath, *shpath;
instdir = g_win32_get_package_installation_directory_of_module (NULL);
if (instdir == NULL)
{
/* This only happens when GetModuleFilename() fails. If it does, that
* failure should be investigated and fixed.
*/
debug_spew ("g_win32_get_package_installation_directory_of_module failed\n");
return;
}
lpath = g_build_filename (instdir, "lib", "pkgconfig", NULL);
shpath = g_build_filename (instdir, "share", "pkgconfig", NULL);
pkg_config_pc_path = g_strconcat (lpath, G_SEARCHPATH_SEPARATOR_S, shpath,
NULL);
g_free (instdir);
g_free (lpath);
g_free (shpath);
#else
pkg_config_pc_path = PKG_CONFIG_PC_PATH;
#endif
}
static gboolean
process_package_args (const char *cmdline, GList **packages, FILE *log)
{
gboolean success = TRUE;
GList *reqs;
reqs = parse_module_list (NULL, cmdline, "(command line arguments)");
if (reqs == NULL)
{
fprintf (stderr, "Must specify package names on the command line\n");
fflush (stderr);
return FALSE;
}
for (; reqs != NULL; reqs = g_list_next (reqs))
{
Package *req;
RequiredVersion *ver = reqs->data;
/* override requested versions with cmdline options */
if (required_exact_version)
{
g_free (ver->version);
ver->comparison = EQUAL;
ver->version = g_strdup (required_exact_version);
}
else if (required_atleast_version)
{
g_free (ver->version);
ver->comparison = GREATER_THAN_EQUAL;
ver->version = g_strdup (required_atleast_version);
}
else if (required_max_version)
{
g_free (ver->version);
ver->comparison = LESS_THAN_EQUAL;
ver->version = g_strdup (required_max_version);
}
if (want_short_errors)
req = get_package_quiet (ver->name);
else
req = get_package (ver->name);
if (log != NULL)
{
if (req == NULL)
fprintf (log, "%s NOT-FOUND\n", ver->name);
else
fprintf (log, "%s %s %s\n", ver->name,
comparison_to_str (ver->comparison),
(ver->version == NULL) ? "(null)" : ver->version);
}
if (req == NULL)
{
success = FALSE;
verbose_error ("No package '%s' found\n", ver->name);
continue;
}
if (!version_test (ver->comparison, req->version, ver->version))
{
success = FALSE;
verbose_error ("Requested '%s %s %s' but version of %s is %s\n",
ver->name,
comparison_to_str (ver->comparison),
ver->version,
req->name,
req->version);
if (req->url)
verbose_error ("You may find new versions of %s at %s\n",
req->name, req->url);
continue;
}
*packages = g_list_prepend (*packages, req);
}
*packages = g_list_reverse (*packages);
return success;
}
static const GOptionEntry options_table[] = {
{ "version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "output version of pkg-config", NULL },
{ "modversion", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "output version for package", NULL },
{ "atleast-pkgconfig-version", 0, 0, G_OPTION_ARG_STRING,
&required_pkgconfig_version,
"require given version of pkg-config", "VERSION" },
{ "libs", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, &output_opt_cb,
"output all linker flags", NULL },
{ "static", 0, 0, G_OPTION_ARG_NONE, &want_static_lib_list,
"output linker flags for static linking", NULL },
{ "short-errors", 0, 0, G_OPTION_ARG_NONE, &want_short_errors,
"print short errors", NULL },
{ "libs-only-l", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "output -l flags", NULL },
{ "libs-only-other", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "output other libs (e.g. -pthread)", NULL },
{ "libs-only-L", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "output -L flags", NULL },
{ "cflags", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, &output_opt_cb,
"output all pre-processor and compiler flags", NULL },
{ "cflags-only-I", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "output -I flags", NULL },
{ "cflags-only-other", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "output cflags not covered by the cflags-only-I option",
NULL },
{ "variable", 0, 0, G_OPTION_ARG_CALLBACK, &output_opt_cb,
"get the value of variable named NAME", "NAME" },
{ "define-variable", 0, 0, G_OPTION_ARG_CALLBACK, &define_variable_cb,
"set variable NAME to VALUE", "NAME=VALUE" },
{ "exists", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, &output_opt_cb,
"return 0 if the module(s) exist", NULL },
{ "print-variables", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "output list of variables defined by the module", NULL },
{ "uninstalled", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "return 0 if the uninstalled version of one or more "
"module(s) or their dependencies will be used", NULL },
{ "atleast-version", 0, 0, G_OPTION_ARG_CALLBACK, &output_opt_cb,
"return 0 if the module is at least version VERSION", "VERSION" },
{ "exact-version", 0, 0, G_OPTION_ARG_CALLBACK, &output_opt_cb,
"return 0 if the module is at exactly version VERSION", "VERSION" },
{ "max-version", 0, 0, G_OPTION_ARG_CALLBACK, &output_opt_cb,
"return 0 if the module is at no newer than version VERSION", "VERSION" },
{ "list-all", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "list all known packages", NULL },
{ "debug", 0, 0, G_OPTION_ARG_NONE, &want_debug_spew,
"show verbose debug information", NULL },
{ "print-errors", 0, 0, G_OPTION_ARG_NONE, &want_verbose_errors,
"show verbose information about missing or conflicting packages "
"(default unless --exists or --atleast/exact/max-version given on the "
"command line)", NULL },
{ "silence-errors", 0, 0, G_OPTION_ARG_NONE, &want_silence_errors,
"be silent about errors (default when --exists or "
"--atleast/exact/max-version given on the command line)", NULL },
{ "errors-to-stdout", 0, 0, G_OPTION_ARG_NONE, &want_stdout_errors,
"print errors from --print-errors to stdout not stderr", NULL },
{ "print-provides", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "print which packages the package provides", NULL },
{ "print-requires", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "print which packages the package requires", NULL },
{ "print-requires-private", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "print which packages the package requires for static "
"linking", NULL },
{ "validate", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
&output_opt_cb, "validate a package's .pc file", NULL },
{ "define-prefix", 0, 0, G_OPTION_ARG_NONE, &define_prefix,
"try to override the value of prefix for each .pc file found with a "
"guesstimated value based on the location of the .pc file", NULL },
{ "dont-define-prefix", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE,
&define_prefix, "don't try to override the value of prefix for each .pc "
"file found with a guesstimated value based on the location of the .pc "
"file", NULL },
{ "prefix-variable", 0, 0, G_OPTION_ARG_STRING, &prefix_variable,
"set the name of the variable that pkg-config automatically sets",
"PREFIX" },
#ifdef G_OS_WIN32
{ "msvc-syntax", 0, 0, G_OPTION_ARG_NONE, &msvc_syntax,
"output -l and -L flags for the Microsoft compiler (cl)", NULL },
#endif
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
int
main (int argc, char **argv)
{
GString *str;
GList *packages = NULL;
char *search_path;
char *pcbuilddir;
gboolean need_newline;
FILE *log = NULL;
GError *error = NULL;
GOptionContext *opt_context;
/* This is here so that we get debug spew from the start,
* during arg parsing
*/
if (getenv ("PKG_CONFIG_DEBUG_SPEW"))
{
want_debug_spew = TRUE;
want_verbose_errors = TRUE;
want_silence_errors = FALSE;
debug_spew ("PKG_CONFIG_DEBUG_SPEW variable enabling debug spew\n");
}
/* Get the built-in search path */
init_pc_path ();
if (pkg_config_pc_path == NULL)
{
/* Even when we override the built-in search path, we still use it later
* to add pc_path to the virtual pkg-config package.
*/
verbose_error ("Failed to get default search path\n");
exit (1);
}
search_path = getenv ("PKG_CONFIG_PATH");
if (search_path)
{
add_search_dirs(search_path, G_SEARCHPATH_SEPARATOR_S);
}
if (getenv("PKG_CONFIG_LIBDIR") != NULL)
{
add_search_dirs(getenv("PKG_CONFIG_LIBDIR"), G_SEARCHPATH_SEPARATOR_S);
}
else
{
add_search_dirs(pkg_config_pc_path, G_SEARCHPATH_SEPARATOR_S);
}
pcsysrootdir = getenv ("PKG_CONFIG_SYSROOT_DIR");
if (pcsysrootdir)
{
define_global_variable ("pc_sysrootdir", pcsysrootdir);
}
else
{
define_global_variable ("pc_sysrootdir", "/");
}
pcbuilddir = getenv ("PKG_CONFIG_TOP_BUILD_DIR");
if (pcbuilddir)
{
define_global_variable ("pc_top_builddir", pcbuilddir);
}
else
{
/* Default appropriate for automake */
define_global_variable ("pc_top_builddir", "$(top_builddir)");
}
if (getenv ("PKG_CONFIG_DISABLE_UNINSTALLED"))
{
debug_spew ("disabling auto-preference for uninstalled packages\n");
disable_uninstalled = TRUE;
}
/* Parse options */
opt_context = g_option_context_new (NULL);
g_option_context_add_main_entries (opt_context, options_table, NULL);
if (!g_option_context_parse(opt_context, &argc, &argv, &error))
{
fprintf (stderr, "%s\n", error->message);
return 1;
}
/* If no output option was set, then --exists is the default. */
if (!output_opt_set)
{
debug_spew ("no output option set, defaulting to --exists\n");
want_exists = TRUE;
}
/* Error printing is determined as follows:
* - for --exists, --*-version, --list-all and no options at all,
* it's off by default and --print-errors will turn it on
* - for all other output options, it's on by default and
* --silence-errors can turn it off
*/
if (want_exists || want_list)
{
debug_spew ("Error printing disabled by default due to use of output "
"options --exists, --atleast/exact/max-version, "
"--list-all or no output option at all. Value of "
"--print-errors: %d\n",
want_verbose_errors);
/* Leave want_verbose_errors unchanged, reflecting --print-errors */
}
else
{
debug_spew ("Error printing enabled by default due to use of output "
"options besides --exists, --atleast/exact/max-version or "
"--list-all. Value of --silence-errors: %d\n",
want_silence_errors);
if (want_silence_errors && getenv ("PKG_CONFIG_DEBUG_SPEW") == NULL)
want_verbose_errors = FALSE;
else
want_verbose_errors = TRUE;
}
if (want_verbose_errors)
debug_spew ("Error printing enabled\n");
else
debug_spew ("Error printing disabled\n");
if (want_static_lib_list)
enable_private_libs();
else
disable_private_libs();
/* honor Requires.private if any Cflags are requested or any static
* libs are requested */
if (pkg_flags & CFLAGS_ANY || want_requires_private || want_exists ||
(want_static_lib_list && (pkg_flags & LIBS_ANY)))
enable_requires_private();
/* ignore Requires if no Cflags or Libs are requested */
if (pkg_flags == 0 && !want_requires && !want_exists)
disable_requires();
/* Allow errors in .pc files when listing all. */
if (want_list)
parse_strict = FALSE;
if (want_my_version)
{
printf ("%s\n", VERSION);
return 0;
}
if (required_pkgconfig_version)
{
if (compare_versions (VERSION, required_pkgconfig_version) >= 0)
return 0;
else
return 1;
}
package_init ();
if (want_list)
{
print_package_list ();
return 0;
}
/* Collect packages from remaining args */
str = g_string_new ("");
while (argc > 1)
{
argc--;
argv++;
g_string_append (str, *argv);
g_string_append (str, " ");
}
g_option_context_free (opt_context);
g_strstrip (str->str);
if (getenv("PKG_CONFIG_LOG") != NULL)
{
log = fopen (getenv ("PKG_CONFIG_LOG"), "a");
if (log == NULL)
{
fprintf (stderr, "Cannot open log file: %s\n",
getenv ("PKG_CONFIG_LOG"));
exit (1);
}
}
/* find and parse each of the packages specified */
if (!process_package_args (str->str, &packages, log))
return 1;
if (log != NULL)
fclose (log);
g_string_free (str, TRUE);
/* If the user just wants to check package existence or validate its .pc
* file, we're all done. */
if (want_exists || want_validate)
return 0;
if (want_variable_list)
{
GList *tmp;
tmp = packages;
while (tmp != NULL)
{
Package *pkg = tmp->data;
if (pkg->vars != NULL)
{
/* Sort variables for consistent output */
GList *keys = g_hash_table_get_keys (pkg->vars);
keys = g_list_sort (keys, (GCompareFunc)g_strcmp0);
g_list_foreach (keys, print_list_data, NULL);
g_list_free (keys);
}
tmp = g_list_next (tmp);
if (tmp) printf ("\n");
}
need_newline = FALSE;
}
if (want_uninstalled)
{
/* See if > 0 pkgs (including dependencies recursively) were uninstalled */
GList *tmp;
tmp = packages;
while (tmp != NULL)
{
Package *pkg = tmp->data;
if (pkg_uninstalled (pkg))
return 0;
tmp = g_list_next (tmp);
}
return 1;
}
if (want_version)
{
GList *tmp;
tmp = packages;
while (tmp != NULL)
{
Package *pkg = tmp->data;
printf ("%s\n", pkg->version);
tmp = g_list_next (tmp);
}
}
if (want_provides)
{
GList *tmp;
tmp = packages;
while (tmp != NULL)
{
Package *pkg = tmp->data;
char *key;
key = pkg->key;
while (*key == '/')
key++;
if (strlen(key) > 0)
printf ("%s = %s\n", key, pkg->version);
tmp = g_list_next (tmp);
}
}
if (want_requires)
{
GList *pkgtmp;
for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_list_next (pkgtmp))
{
Package *pkg = pkgtmp->data;
GList *reqtmp;
/* process Requires: */
for (reqtmp = pkg->requires; reqtmp != NULL; reqtmp = g_list_next (reqtmp))
{
Package *deppkg = reqtmp->data;
RequiredVersion *req;
req = g_hash_table_lookup(pkg->required_versions, deppkg->key);
if ((req == NULL) || (req->comparison == ALWAYS_MATCH))
printf ("%s\n", deppkg->key);
else
printf ("%s %s %s\n", deppkg->key,
comparison_to_str(req->comparison),
req->version);
}
}
}
if (want_requires_private)
{
GList *pkgtmp;
for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_list_next (pkgtmp))
{
Package *pkg = pkgtmp->data;
GList *reqtmp;
/* process Requires.private: */
for (reqtmp = pkg->requires_private; reqtmp != NULL; reqtmp = g_list_next (reqtmp))
{
Package *deppkg = reqtmp->data;
RequiredVersion *req;
if (g_list_find (pkg->requires, reqtmp->data))
continue;
req = g_hash_table_lookup(pkg->required_versions, deppkg->key);
if ((req == NULL) || (req->comparison == ALWAYS_MATCH))
printf ("%s\n", deppkg->key);
else
printf ("%s %s %s\n", deppkg->key,
comparison_to_str(req->comparison),
req->version);
}
}
}
/* Print all flags; then print a newline at the end. */
need_newline = FALSE;
if (variable_name)
{
char *str = packages_get_var (packages, variable_name);
printf ("%s", str);
g_free (str);
need_newline = TRUE;
}
if (pkg_flags != 0)
{
char *str = packages_get_flags (packages, pkg_flags);
printf ("%s", str);
g_free (str);
need_newline = TRUE;
}
if (need_newline)
printf ("\n");
return 0;
}
pkg-config-0.29.1/detectenv-msvc.mak 0000664 0001750 0001750 00000003257 12651243607 014210 0000000 0000000 # Check to see we are configured to build with MSVC (MSDEVDIR, MSVCDIR or
# VCINSTALLDIR) or with the MS Platform SDK (MSSDK or WindowsSDKDir)
!if !defined(VCINSTALLDIR) && !defined(WINDOWSSDKDIR)
MSG = ^
This Makefile is only for Visual Studio 2008 and later.^
You need to ensure that the Visual Studio Environment is properly set up^
before running this Makefile.
!error $(MSG)
!endif
ERRNUL = 2>NUL
_HASH=^#
!if ![echo VCVERSION=_MSC_VER > vercl.x] \
&& ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \
&& ![echo PLAT=Win32 >> vercl.x] \
&& ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \
&& ![echo PLAT=x64 >> vercl.x] \
&& ![echo $(_HASH)endif >> vercl.x] \
&& ![cl -nologo -TC -P vercl.x $(ERRNUL)]
!include vercl.i
!if ![echo VCVER= ^\> vercl.vc] \
&& ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc]
!include vercl.vc
!endif
!endif
!if ![del $(ERRNUL) /q/f vercl.x vercl.i vercl.vc]
!endif
!if $(VCVERSION) > 1499 && $(VCVERSION) < 1600
VSVER = 9
!elseif $(VCVERSION) > 1599 && $(VCVERSION) < 1700
VSVER = 10
!elseif $(VCVERSION) > 1699 && $(VCVERSION) < 1800
VSVER = 11
!elseif $(VCVERSION) > 1799 && $(VCVERSION) < 1900
VSVER = 12
!elseif $(VCVERSION) > 1899 && $(VCVERSION) < 2000
VSVER = 14
!else
VSVER = 0
!endif
!if "$(VSVER)" == "0"
MSG = ^
This NMake Makefile set supports Visual Studio^
9 (2008) through 14 (2015). Your Visual Studio^
version is not supported.
!error $(MSG)
!endif
VALID_CFGSET = FALSE
!if "$(CFG)" == "release" || "$(CFG)" == "debug"
VALID_CFGSET = TRUE
!endif
!if "$(CFG)" == "release"
CFLAGS_ADD = /MD /O2 /GL
!else
CFLAGS_ADD = /MDd /Od
!endif
!if "$(PLAT)" == "x64"
LDFLAGS_ARCH = /machine:x64
!else
LDFLAGS_ARCH = /machine:x86
!endif
pkg-config-0.29.1/README.win32 0000664 0001750 0001750 00000004555 12651243607 012412 0000000 0000000 pkg-config on Win32
===================
This file describes pkg-config for "native" Win32. (On Cygwin,
pkg-config builds fine right out of the box. Cygwin is just another
Unix variant, as far as pkg-config is concerned.) I don't call this
"native" Win32 target MinGW, as pkg-config on Windows is supposed to
be useable also by MSVC users.
When pkg-config.exe is invoked, it uses the glib function
g_win32_get_package_installation_directory_of_module() to find the
directory it's being run from. It then adds the "lib" and "share"
subdirectories to the pkg-config search path unless PKG_CONFIG_LIBDIR is
set in the environment. This allows pkg-config to adjust to being
relocated on Windows.
For each .pc file encountered, pkg-config will replace the prefix
variable to the base of it's currently installed directory unless the
command line option --dont-define-prefix is set. It will take the .pc
directory and strip off either lib\pkgconfig or share\pkgconfig to
determine the prefix. This allows the paths encoded in .pc files at
build time to be replaced with appropriate values at runtime.
In order to use the output of pkg-config with MSVC, the option
--msvc-syntax can be used to convert UNIX style library output to
arguments that work with MSVC. This means -Lfoo will be converted to
/libpath:foo, and -lfoo will be converted to foo.lib.
Building pkg-config is now supported on Visual Studio/MSVC as well. To
build it, you will need to have a glib installation. Note that MSVC
builds of glib does not have a build-time dependency on pkg-config,
unlike the normal autotools builds. The headers and libs either need to
be found in your default %INCLUDE% and %LIB% respectively, or they need
to be found in $(GLIB_PREFIX)\include and $(GLIB_PREFIX)\lib respectively;
please see Makefile.vc for adjusting $(GLIB_PREFIX) to suit your needs.
To build pkg-config with MSVC, run in a Visual Studio command prompt:
"nmake /f Makefile.vc CFG=release" (release builds) -or-
"nmake /f Makefile.vc CFG=debug" (debug builds)
The resulting pkg-config.exe will be found in [release|debug]\[win32|x64];
a 'clean' target is supported to clean up the build. MSVC 2008
through 2015 is supported; older versions may work as well but is not
tested. Note that building with the glib bundled with this source
distribution is not currently supported-the glib DLL and all of its
dependent DLLs are required at runtime.
pkg-config-0.29.1/config.h.win32 0000664 0001750 0001750 00000005274 12665370327 013154 0000000 0000000 /* config.h.in. Generated from configure.ac by autoheader. */
/* Define ${prefix} in .pc files at runtime */
#define ENABLE_DEFINE_PREFIX 1
/* Link library to all dependent libraries, not only directly needed ones */
#define ENABLE_INDIRECT_DEPS 1
/* Define to 1 if you have the header file. */
#ifndef _MSC_VER
#define HAVE_DIRENT_H 1
#endif
/* Define to 1 if you have the header file. */
/* #undef HAVE_DLFCN_H */
/* Define to 1 if you have the header file. */
#if !defined (_MSC_VER) || (_MSC_VER >= 1800)
#define HAVE_INTTYPES_H 1
#endif
/* Define to 1 if you have the header file. */
#define HAVE_MALLOC_H 1
/* Define to 1 if you have the header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the header file. */
#if (!defined(_MSC_VER) || (_MSC_VER >= 1600))
#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 header file. */
#ifndef _MSC_VER
#define HAVE_STRINGS_H 1
#endif
/* Define to 1 if you have the header file. */
#define HAVE_STRING_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 header file. */
/* #undef HAVE_SYS_WAIT_H */
/* Define to 1 if you have the header file. */
#ifndef _MSC_VER
#define HAVE_UNISTD_H 1
#endif
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "pkg-config"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "https://bugs.freedesktop.org/enter_bug.cgi?product=pkg-config"
/* Define to the full name of this package. */
#define PACKAGE_NAME "pkg-config"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "pkg-config 0.29.1"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pkg-config"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.29.1"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.29.1"
/* 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 */
pkg-config-0.29.1/glib/ 0000775 0001750 0001750 00000000000 12665370350 011556 5 0000000 0000000 pkg-config-0.29.1/glib/config.guess 0000755 0001750 0001750 00000123672 12601774025 014024 0000000 0000000 #! /bin/sh
# Attempt to guess a canonical system name.
# Copyright 1992-2015 Free Software Foundation, Inc.
timestamp='2015-01-01'
# 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 3 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, see .
#
# 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 Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
#
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
#
# Please send patches to .
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 1992-2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help" >&2
exit 1 ;;
* )
break ;;
esac
done
if test $# != 0; then
echo "$me: too many arguments$help" >&2
exit 1
fi
trap 'exit 1' 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 "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
dummy=$tmp/dummy ;
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
case $CC_FOR_BUILD,$HOST_CC,$CC in
,,) echo "int x;" > $dummy.c ;
for c in cc gcc c89 c99 ; do
if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
CC_FOR_BUILD="$c"; break ;
fi ;
done ;
if test x"$CC_FOR_BUILD" = x ; then
CC_FOR_BUILD=no_compiler_found ;
fi
;;
,,*) CC_FOR_BUILD=$CC ;;
,*,*) CC_FOR_BUILD=$HOST_CC ;;
esac ; set_cc_for_build= ;'
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "${UNAME_SYSTEM}" in
Linux|GNU|GNU/*)
# If the system lacks a compiler, then just pick glibc.
# We could probably try harder.
LIBC=gnu
eval $set_cc_for_build
cat <<-EOF > $dummy.c
#include
#if defined(__UCLIBC__)
LIBC=uclibc
#elif defined(__dietlibc__)
LIBC=dietlibc
#else
LIBC=gnu
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
;;
esac
# 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 tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
# compatibility and a consistent mechanism for selecting the
# object file format.
#
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
sysctl="sysctl -n hw.machine_arch"
UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
/usr/sbin/$sysctl 2>/dev/null || echo unknown)`
case "${UNAME_MACHINE_ARCH}" in
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
esac
# The Operating System including object format, if it has switched
# to ELF recently, or will in the future.
case "${UNAME_MACHINE_ARCH}" in
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
eval $set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ELF__
then
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
# Return netbsd for either. FIX?
os=netbsd
else
os=netbsdelf
fi
;;
*)
os=netbsd
;;
esac
# The OS release
# Debian GNU/NetBSD machines have a different userland, and
# thus, need a distinct triplet. However, they do not need
# kernel version information, so it can be replaced with a
# suitable tag, in the style of linux-gnu.
case "${UNAME_VERSION}" in
Debian*)
release='-gnu'
;;
*)
release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
echo "${machine}-${os}${release}"
exit ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
exit ;;
*:ekkoBSD:*:*)
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
exit ;;
*:SolidBSD:*:*)
echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
exit ;;
macppc:MirBSD:*:*)
echo powerpc-unknown-mirbsd${UNAME_RELEASE}
exit ;;
*:MirBSD:*:*)
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
exit ;;
alpha:OSF1:*:*)
case $UNAME_RELEASE in
*4.0)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;;
*5.*)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU
# types through head -n 1, so we only detect the type of CPU 0.
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
case "$ALPHA_CPU_TYPE" in
"EV4 (21064)")
UNAME_MACHINE="alpha" ;;
"EV4.5 (21064)")
UNAME_MACHINE="alpha" ;;
"LCA4 (21066/21068)")
UNAME_MACHINE="alpha" ;;
"EV5 (21164)")
UNAME_MACHINE="alphaev5" ;;
"EV5.6 (21164A)")
UNAME_MACHINE="alphaev56" ;;
"EV5.6 (21164PC)")
UNAME_MACHINE="alphapca56" ;;
"EV5.7 (21164PC)")
UNAME_MACHINE="alphapca57" ;;
"EV6 (21264)")
UNAME_MACHINE="alphaev6" ;;
"EV6.7 (21264A)")
UNAME_MACHINE="alphaev67" ;;
"EV6.8CB (21264C)")
UNAME_MACHINE="alphaev68" ;;
"EV6.8AL (21264B)")
UNAME_MACHINE="alphaev68" ;;
"EV6.8CX (21264D)")
UNAME_MACHINE="alphaev68" ;;
"EV6.9A (21264/EV69A)")
UNAME_MACHINE="alphaev69" ;;
"EV7 (21364)")
UNAME_MACHINE="alphaev7" ;;
"EV7.9 (21364A)")
UNAME_MACHINE="alphaev79" ;;
esac
# A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
exitcode=$?
trap '' 0
exit $exitcode ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# Should we change UNAME_MACHINE based on the output of uname instead
# of the specific Alpha model?
echo alpha-pc-interix
exit ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
exit ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-unknown-sysv4
exit ;;
*:[Aa]miga[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-amigaos
exit ;;
*:[Mm]orph[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-morphos
exit ;;
*:OS/390:*:*)
echo i370-ibm-openedition
exit ;;
*:z/VM:*:*)
echo s390-ibm-zvmoe
exit ;;
*:OS400:*:*)
echo powerpc-ibm-os400
exit ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit ;;
arm*:riscos:*:*|arm*:RISCOS:*:*)
echo arm-unknown-riscos
exit ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
echo hppa1.1-hitachi-hiuxmpp
exit ;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "`(/bin/universe) 2>/dev/null`" = att ; then
echo pyramid-pyramid-sysv3
else
echo pyramid-pyramid-bsd
fi
exit ;;
NILE*:*:*:dcosx)
echo pyramid-pyramid-svr4
exit ;;
DRS?6000:unix:4.0:6*)
echo sparc-icl-nx6
exit ;;
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
case `/usr/bin/uname -p` in
sparc) echo sparc-icl-nx7; exit ;;
esac ;;
s390x:SunOS:*:*)
echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4H:SunOS:5.*:*)
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
echo i386-pc-auroraux${UNAME_RELEASE}
exit ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
eval $set_cc_for_build
SUN_ARCH="i386"
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
SUN_ARCH="x86_64"
fi
fi
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
exit ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
exit ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
case "`/bin/arch`" in
sun3)
echo m68k-sun-sunos${UNAME_RELEASE}
;;
sun4)
echo sparc-sun-sunos${UNAME_RELEASE}
;;
esac
exit ;;
aushp:SunOS:*:*)
echo sparc-auspex-sunos${UNAME_RELEASE}
exit ;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
# "atarist" or "atariste" at least should have a processor
# > m68000). The system name ranges from "MiNT" over "FreeMiNT"
# to the lowercase version "mint" (or "freemint"). Finally
# the system name "TOS" denotes a system which is actually not
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
echo m68k-milan-mint${UNAME_RELEASE}
exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
echo m68k-hades-mint${UNAME_RELEASE}
exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
echo m68k-unknown-mint${UNAME_RELEASE}
exit ;;
m68k:machten:*:*)
echo m68k-apple-machten${UNAME_RELEASE}
exit ;;
powerpc:machten:*:*)
echo powerpc-apple-machten${UNAME_RELEASE}
exit ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
exit ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
exit ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
exit ;;
2020:CLIX:*:* | 2430:CLIX:*:*)
echo clipper-intergraph-clix${UNAME_RELEASE}
exit ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#ifdef __cplusplus
#include /* for printf() prototype */
int main (int argc, char *argv[]) {
#else
int main (argc, argv) int argc; char *argv[]; {
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
$CC_FOR_BUILD -o $dummy $dummy.c &&
dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
SYSTEM_NAME=`$dummy $dummyarg` &&
{ echo "$SYSTEM_NAME"; exit; }
echo mips-mips-riscos${UNAME_RELEASE}
exit ;;
Motorola:PowerMAX_OS:*:*)
echo powerpc-motorola-powermax
exit ;;
Motorola:*:4.3:PL8-*)
echo powerpc-harris-powermax
exit ;;
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
echo powerpc-harris-powermax
exit ;;
Night_Hawk:Power_UNIX:*:*)
echo powerpc-harris-powerunix
exit ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
exit ;;
m88k:*:4*:R4*)
echo m88k-motorola-sysv4
exit ;;
m88k:*:3*:R3*)
echo m88k-motorola-sysv3
exit ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
[ ${TARGET_BINARY_INTERFACE}x = x ]
then
echo m88k-dg-dgux${UNAME_RELEASE}
else
echo m88k-dg-dguxbcs${UNAME_RELEASE}
fi
else
echo i586-dg-dgux${UNAME_RELEASE}
fi
exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
echo m88k-motorola-sysv3
exit ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
echo m88k-tektronix-sysv3
exit ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
echo m68k-tektronix-bsd
exit ;;
*:IRIX*:*:*)
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
exit ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*)
echo i386-ibm-aix
exit ;;
ia64:AIX:*:*)
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
exit ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#include
main()
{
if (!__power_pc())
exit(1);
puts("powerpc-ibm-aix3.2.5");
exit(0);
}
EOF
if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
then
echo "$SYSTEM_NAME"
else
echo rs6000-ibm-aix3.2.5
fi
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
else
echo rs6000-ibm-aix3.2
fi
exit ;;
*:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if [ -x /usr/bin/lslpp ] ; then
IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
exit ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
echo romp-ibm-bsd4.4
exit ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
exit ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
exit ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
exit ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
exit ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit ;;
9000/[34678]??:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "${sc_cpu_version}" in
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "${sc_kernel_bits}" in
32) HP_ARCH="hppa2.0n" ;;
64) HP_ARCH="hppa2.0w" ;;
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
esac ;;
esac
fi
if [ "${HP_ARCH}" = "" ]; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#define _HPUX_SOURCE
#include
#include
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
EOF
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
if [ ${HP_ARCH} = "hppa2.0w" ]
then
eval $set_cc_for_build
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
# generating 64-bit code. GNU and HP use different nomenclature:
#
# $ CC_FOR_BUILD=cc ./config.guess
# => hppa2.0w-hp-hpux11.23
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
# => hppa64-hp-hpux11.23
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
grep -q __LP64__
then
HP_ARCH="hppa2.0w"
else
HP_ARCH="hppa64"
fi
fi
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
exit ;;
ia64:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ia64-hp-hpux${HPUX_REV}
exit ;;
3050*:HI-UX:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#include
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
{ echo "$SYSTEM_NAME"; exit; }
echo unknown-hitachi-hiuxwe2
exit ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
exit ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit ;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
echo hppa1.0-hp-mpeix
exit ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
exit ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit ;;
i*86:OSF1:*:*)
if [ -x /usr/sbin/sysversion ] ; then
echo ${UNAME_MACHINE}-unknown-osf1mk
else
echo ${UNAME_MACHINE}-unknown-osf1
fi
exit ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*[A-Z]90:*:*:*)
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*T3E:*:*:*)
echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*SV1:*:*:*)
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
*:UNICOS/mp:*:*)
echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
exit ;;
sparc*:BSD/OS:*:*)
echo sparc-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:FreeBSD:*:*)
UNAME_PROCESSOR=`/usr/bin/uname -p`
case ${UNAME_PROCESSOR} in
amd64)
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
*)
echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
esac
exit ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
exit ;;
*:MINGW64*:*)
echo ${UNAME_MACHINE}-pc-mingw64
exit ;;
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
*:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32
exit ;;
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
*:Interix*:*)
case ${UNAME_MACHINE} in
x86)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
authenticamd | genuineintel | EM64T)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
IA64)
echo ia64-unknown-interix${UNAME_RELEASE}
exit ;;
esac ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
exit ;;
8664:Windows_NT:*)
echo x86_64-pc-mks
exit ;;
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
# UNAME_MACHINE based on the output of uname instead of i386?
echo i586-pc-interix
exit ;;
i*:UWIN*:*)
echo ${UNAME_MACHINE}-pc-uwin
exit ;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
echo x86_64-unknown-cygwin
exit ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin
exit ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
*:GNU:*:*)
# the GNU system
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
exit ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit ;;
aarch64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
PCA57) UNAME_MACHINE=alphapca56 ;;
EV6) UNAME_MACHINE=alphaev6 ;;
EV67) UNAME_MACHINE=alphaev67 ;;
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arc:Linux:*:* | arceb:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arm*:Linux:*:*)
eval $set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
else
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
cris:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
crisv32:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
frv:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
hexagon:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:Linux:*:*)
echo ${UNAME_MACHINE}-pc-linux-${LIBC}
exit ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
mips:Linux:*:* | mips64:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
#undef ${UNAME_MACHINE}
#undef ${UNAME_MACHINE}el
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
CPU=${UNAME_MACHINE}el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
CPU=${UNAME_MACHINE}
#else
CPU=
#endif
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
openrisc*:Linux:*:*)
echo or1k-unknown-linux-${LIBC}
exit ;;
or32:Linux:*:* | or1k*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-${LIBC}
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-${LIBC}
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
*) echo hppa-unknown-linux-${LIBC} ;;
esac
exit ;;
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-${LIBC}
exit ;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-${LIBC}
exit ;;
ppc64le:Linux:*:*)
echo powerpc64le-unknown-linux-${LIBC}
exit ;;
ppcle:Linux:*:*)
echo powerpcle-unknown-linux-${LIBC}
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
exit ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
tile*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
vax:Linux:*:*)
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
exit ;;
x86_64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
# sysname and nodename.
echo i386-sequent-sysv4
exit ;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
exit ;;
i*86:OS/2:*:*)
# If we were able to find `uname', then EMX Unix compatibility
# is probably installed.
echo ${UNAME_MACHINE}-pc-os2-emx
exit ;;
i*86:XTS-300:*:STOP)
echo ${UNAME_MACHINE}-unknown-stop
exit ;;
i*86:atheos:*:*)
echo ${UNAME_MACHINE}-unknown-atheos
exit ;;
i*86:syllable:*:*)
echo ${UNAME_MACHINE}-pc-syllable
exit ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
exit ;;
i*86:*DOS:*:*)
echo ${UNAME_MACHINE}-pc-msdosdjgpp
exit ;;
i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
else
echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
fi
exit ;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
exit ;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
&& UNAME_MACHINE=i686
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
&& UNAME_MACHINE=i686
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
else
echo ${UNAME_MACHINE}-pc-sysv32
fi
exit ;;
pc:*:*:*)
# Left here for compatibility:
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
# prints for the "djgpp" host, or else GDB configury will decide that
# this is a cross-build.
echo i586-pc-msdosdjgpp
exit ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit ;;
paragon:*:*:*)
echo i860-intel-osf1
exit ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
fi
exit ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
echo m68010-convergent-sysv
exit ;;
mc68k:UNIX:SYSTEM5:3.51m)
echo m68k-convergent-sysv
exit ;;
M680?0:D-NIX:5.3:*)
echo m68k-diab-dnix
exit ;;
M68*:*:R3V[5678]*:*)
test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
OS_REL='.3'
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
echo m68k-unknown-lynxos${UNAME_RELEASE}
exit ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit ;;
TSUNAMI:LynxOS:2.*:*)
echo sparc-unknown-lynxos${UNAME_RELEASE}
exit ;;
rs6000:LynxOS:2.*:*)
echo rs6000-unknown-lynxos${UNAME_RELEASE}
exit ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
echo powerpc-unknown-lynxos${UNAME_RELEASE}
exit ;;
SM[BE]S:UNIX_SV:*:*)
echo mips-dde-sysv${UNAME_RELEASE}
exit ;;
RM*:ReliantUNIX-*:*:*)
echo mips-sni-sysv4
exit ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
exit ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
echo ${UNAME_MACHINE}-sni-sysv4
else
echo ns32k-sni-sysv
fi
exit ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says
echo i586-unisys-sysv4
exit ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes .
# How about differentiating between stratus architectures? -djm
echo hppa1.1-stratus-sysv4
exit ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
echo i860-stratus-sysv4
exit ;;
i*86:VOS:*:*)
# From Paul.Green@stratus.com.
echo ${UNAME_MACHINE}-stratus-vos
exit ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
echo hppa1.1-stratus-vos
exit ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
exit ;;
news*:NEWS-OS:6*:*)
echo mips-sony-newsos6
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
exit ;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
echo powerpc-apple-beos
exit ;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
exit ;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
echo i586-pc-haiku
exit ;;
x86_64:Haiku:*:*)
echo x86_64-unknown-haiku
exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
exit ;;
SX-5:SUPER-UX:*:*)
echo sx5-nec-superux${UNAME_RELEASE}
exit ;;
SX-6:SUPER-UX:*:*)
echo sx6-nec-superux${UNAME_RELEASE}
exit ;;
SX-7:SUPER-UX:*:*)
echo sx7-nec-superux${UNAME_RELEASE}
exit ;;
SX-8:SUPER-UX:*:*)
echo sx8-nec-superux${UNAME_RELEASE}
exit ;;
SX-8R:SUPER-UX:*:*)
echo sx8r-nec-superux${UNAME_RELEASE}
exit ;;
Power*:Rhapsody:*:*)
echo powerpc-apple-rhapsody${UNAME_RELEASE}
exit ;;
*:Rhapsody:*:*)
echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
exit ;;
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
eval $set_cc_for_build
if test "$UNAME_PROCESSOR" = unknown ; then
UNAME_PROCESSOR=powerpc
fi
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
case $UNAME_PROCESSOR in
i386) UNAME_PROCESSOR=x86_64 ;;
powerpc) UNAME_PROCESSOR=powerpc64 ;;
esac
fi
fi
elif test "$UNAME_PROCESSOR" = i386 ; then
# Avoid executing cc on OS X 10.9, as it ships with a stub
# that puts up a graphical alert prompting to install
# developer tools. Any system running Mac OS X 10.7 or
# later (Darwin 11 and later) is required to have a 64-bit
# processor. This is not true of the ARM version of Darwin
# that Apple uses in portable devices.
UNAME_PROCESSOR=x86_64
fi
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
if test "$UNAME_PROCESSOR" = "x86"; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
exit ;;
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
NEO-?:NONSTOP_KERNEL:*:*)
echo neo-tandem-nsk${UNAME_RELEASE}
exit ;;
NSE-*:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk${UNAME_RELEASE}
exit ;;
NSR-?:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit ;;
*:NonStop-UX:*:*)
echo mips-compaq-nonstopux
exit ;;
BS2000:POSIX*:*:*)
echo bs2000-siemens-sysv
exit ;;
DS/*:UNIX_System_V:*:*)
echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
exit ;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
if test "$cputype" = "386"; then
UNAME_MACHINE=i386
else
UNAME_MACHINE="$cputype"
fi
echo ${UNAME_MACHINE}-unknown-plan9
exit ;;
*:TOPS-10:*:*)
echo pdp10-unknown-tops10
exit ;;
*:TENEX:*:*)
echo pdp10-unknown-tenex
exit ;;
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
echo pdp10-dec-tops20
exit ;;
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
echo pdp10-xkl-tops20
exit ;;
*:TOPS-20:*:*)
echo pdp10-unknown-tops20
exit ;;
*:ITS:*:*)
echo pdp10-unknown-its
exit ;;
SEI:*:*:SEIUX)
echo mips-sei-seiux${UNAME_RELEASE}
exit ;;
*:DragonFly:*:*)
echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit ;;
*:*VMS:*:*)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
case "${UNAME_MACHINE}" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
V*) echo vax-dec-vms ; exit ;;
esac ;;
*:XENIX:*:SysV)
echo i386-pc-xenix
exit ;;
i*86:skyos:*:*)
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
exit ;;
i*86:rdos:*:*)
echo ${UNAME_MACHINE}-pc-rdos
exit ;;
i*86:AROS:*:*)
echo ${UNAME_MACHINE}-pc-aros
exit ;;
x86_64:VMkernel:*:*)
echo ${UNAME_MACHINE}-unknown-esx
exit ;;
esac
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:
pkg-config-0.29.1/glib/glib.mk 0000664 0001750 0001750 00000024245 12651243552 012751 0000000 0000000 # GLIB - Library of useful C routines
#GTESTER = gtester # for non-GLIB packages
#GTESTER_REPORT = gtester-report # for non-GLIB packages
GTESTER = $(top_builddir)/glib/gtester # for the GLIB package
GTESTER_REPORT = $(top_builddir)/glib/gtester-report # for the GLIB package
NULL =
# initialize variables for unconditional += appending
BUILT_SOURCES =
BUILT_EXTRA_DIST =
CLEANFILES = *.log *.trs
DISTCLEANFILES =
MAINTAINERCLEANFILES =
EXTRA_DIST =
TEST_PROGS =
installed_test_LTLIBRARIES =
installed_test_PROGRAMS =
installed_test_SCRIPTS =
nobase_installed_test_DATA =
noinst_LTLIBRARIES =
noinst_PROGRAMS =
noinst_SCRIPTS =
noinst_DATA =
check_LTLIBRARIES =
check_PROGRAMS =
check_SCRIPTS =
check_DATA =
TESTS =
### testing rules
# test: run all tests in cwd and subdirs
test: test-nonrecursive
if OS_UNIX
@ for subdir in $(SUBDIRS) . ; do \
test "$$subdir" = "." -o "$$subdir" = "po" || \
( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
done
# test-nonrecursive: run tests only in cwd
test-nonrecursive: ${TEST_PROGS}
@test -z "${TEST_PROGS}" || G_TEST_SRCDIR="$(abs_srcdir)" G_TEST_BUILDDIR="$(abs_builddir)" G_DEBUG=gc-friendly MALLOC_CHECK_=2 MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) ${GTESTER} --verbose ${TEST_PROGS}
else
test-nonrecursive:
endif
# test-report: run tests in subdirs and generate report
# perf-report: run tests in subdirs with -m perf and generate report
# full-report: like test-report: with -m perf and -m slow
test-report perf-report full-report: ${TEST_PROGS}
@test -z "${TEST_PROGS}" || { \
case $@ in \
test-report) test_options="-k";; \
perf-report) test_options="-k -m=perf";; \
full-report) test_options="-k -m=perf -m=slow";; \
esac ; \
if test -z "$$GTESTER_LOGDIR" ; then \
G_TEST_SRCDIR="$(abs_srcdir)" G_TEST_BUILDDIR="$(abs_builddir)" ${GTESTER} --verbose $$test_options -o test-report.xml ${TEST_PROGS} ; \
elif test -n "${TEST_PROGS}" ; then \
G_TEST_SRCDIR="$(abs_srcdir)" G_TEST_BUILDDIR="$(abs_builddir)" ${GTESTER} --verbose $$test_options -o `mktemp "$$GTESTER_LOGDIR/log-XXXXXX"` ${TEST_PROGS} ; \
fi ; \
}
@ ignore_logdir=true ; \
if test -z "$$GTESTER_LOGDIR" ; then \
GTESTER_LOGDIR=`mktemp -d "\`pwd\`/.testlogs-XXXXXX"`; export GTESTER_LOGDIR ; \
ignore_logdir=false ; \
fi ; \
if test -d "$(top_srcdir)/.git" ; then \
REVISION=`git describe` ; \
else \
REVISION=$(VERSION) ; \
fi ; \
for subdir in $(SUBDIRS) . ; do \
test "$$subdir" = "." -o "$$subdir" = "po" || \
( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
done ; \
$$ignore_logdir || { \
echo '' > $@.xml ; \
echo '' >> $@.xml ; \
echo '' >> $@.xml ; \
echo ' $(PACKAGE)' >> $@.xml ; \
echo ' $(VERSION)' >> $@.xml ; \
echo " $$REVISION" >> $@.xml ; \
echo '' >> $@.xml ; \
for lf in `ls -L "$$GTESTER_LOGDIR"/.` ; do \
sed '1,1s/^?]*?>//' <"$$GTESTER_LOGDIR"/"$$lf" >> $@.xml ; \
done ; \
echo >> $@.xml ; \
echo '' >> $@.xml ; \
rm -rf "$$GTESTER_LOGDIR"/ ; \
${GTESTER_REPORT} --version 2>/dev/null 1>&2 ; test "$$?" != 0 || ${GTESTER_REPORT} $@.xml >$@.html ; \
}
.PHONY: test test-report perf-report full-report test-nonrecursive
.PHONY: lcov genlcov lcov-clean
# use recursive makes in order to ignore errors during check
lcov:
-$(MAKE) $(AM_MAKEFLAGS) -k check
$(MAKE) $(AM_MAKEFLAGS) genlcov
# we have to massage the lcov.info file slightly to hide the effect of libtool
# placing the objects files in the .libs/ directory separate from the *.c
# we also have to delete tests/.libs/libmoduletestplugin_*.gcda
genlcov:
rm -f $(top_builddir)/tests/.libs/libmoduletestplugin_*.gcda
$(LTP) --directory $(top_builddir) --capture --output-file glib-lcov.info --test-name GLIB_PERF --no-checksum --compat-libtool
LANG=C $(LTP_GENHTML) --prefix $(top_builddir) --output-directory glib-lcov --title "GLib Code Coverage" --legend --show-details glib-lcov.info
@echo "file://$(abs_top_builddir)/glib-lcov/index.html"
lcov-clean:
-$(LTP) --directory $(top_builddir) -z
-rm -rf glib-lcov.info glib-lcov
-find -name '*.gcda' -print | xargs rm
# run tests in cwd as part of make check
check-local: test-nonrecursive
# We support a fairly large range of possible variables. It is expected that all types of files in a test suite
# will belong in exactly one of the following variables.
#
# First, we support the usual automake suffixes, but in lowercase, with the customary meaning:
#
# test_programs, test_scripts, test_data, test_ltlibraries
#
# The above are used to list files that are involved in both uninstalled and installed testing. The
# test_programs and test_scripts are taken to be actual testcases and will be run as part of the test suite.
# Note that _data is always used with the nobase_ automake variable name to ensure that installed test data is
# installed in the same way as it appears in the package layout.
#
# In order to mark a particular file as being only for one type of testing, use 'installed' or 'uninstalled',
# like so:
#
# installed_test_programs, uninstalled_test_programs
# installed_test_scripts, uninstalled_test_scripts
# installed_test_data, uninstalled_test_data
# installed_test_ltlibraries, uninstalled_test_ltlibraries
#
# Additionally, we support 'extra' infixes for programs and scripts. This is used for support programs/scripts
# that should not themselves be run as testcases (but exist to be used from other testcases):
#
# test_extra_programs, installed_test_extra_programs, uninstalled_test_extra_programs
# test_extra_scripts, installed_test_extra_scripts, uninstalled_test_extra_scripts
#
# Additionally, for _scripts and _data, we support the customary dist_ prefix so that the named script or data
# file automatically end up in the tarball.
#
# dist_test_scripts, dist_test_data, dist_test_extra_scripts
# dist_installed_test_scripts, dist_installed_test_data, dist_installed_test_extra_scripts
# dist_uninstalled_test_scripts, dist_uninstalled_test_data, dist_uninstalled_test_extra_scripts
#
# Note that no file is automatically disted unless it appears in one of the dist_ variables. This follows the
# standard automake convention of not disting programs scripts or data by default.
#
# test_programs, test_scripts, uninstalled_test_programs and uninstalled_test_scripts (as well as their disted
# variants) will be run as part of the in-tree 'make check'. These are all assumed to be runnable under
# gtester. That's a bit strange for scripts, but it's possible.
# we use test -z "$(TEST_PROGS)" above, so make sure we have no extra whitespace...
TEST_PROGS += $(strip $(test_programs) $(test_scripts) $(uninstalled_test_programs) $(uninstalled_test_scripts) \
$(dist_test_scripts) $(dist_uninstalled_test_scripts))
if OS_WIN32
TESTS += $(test_programs) $(test_scripts) $(uninstalled_test_programs) $(uninstalled_test_scripts) \
$(dist_test_scripts) $(dist_uninstalled_test_scripts)
endif
# Note: build even the installed-only targets during 'make check' to ensure that they still work.
# We need to do a bit of trickery here and manage disting via EXTRA_DIST instead of using dist_ prefixes to
# prevent automake from mistreating gmake functions like $(wildcard ...) and $(addprefix ...) as if they were
# filenames, including removing duplicate instances of the opening part before the space, eg. '$(addprefix'.
all_test_programs = $(test_programs) $(uninstalled_test_programs) $(installed_test_programs) \
$(test_extra_programs) $(uninstalled_test_extra_programs) $(installed_test_extra_programs)
all_test_scripts = $(test_scripts) $(uninstalled_test_scripts) $(installed_test_scripts) \
$(test_extra_scripts) $(uninstalled_test_extra_scripts) $(installed_test_extra_scripts)
all_dist_test_scripts = $(dist_test_scripts) $(dist_uninstalled_test_scripts) $(dist_installed_test_scripts) \
$(dist_test_extra_scripts) $(dist_uninstalled_test_extra_scripts) $(dist_installed_test_extra_scripts)
all_test_scripts += $(all_dist_test_scripts)
EXTRA_DIST += $(all_dist_test_scripts)
all_test_data = $(test_data) $(uninstalled_test_data) $(installed_test_data)
all_dist_test_data = $(dist_test_data) $(dist_uninstalled_test_data) $(dist_installed_test_data)
all_test_data += $(all_dist_test_data)
EXTRA_DIST += $(all_dist_test_data)
all_test_ltlibs = $(test_ltlibraries) $(uninstalled_test_ltlibraries) $(installed_test_ltlibraries)
if ENABLE_ALWAYS_BUILD_TESTS
noinst_LTLIBRARIES += $(all_test_ltlibs)
noinst_PROGRAMS += $(all_test_programs)
noinst_SCRIPTS += $(all_test_scripts)
noinst_DATA += $(all_test_data)
else
check_LTLIBRARIES += $(all_test_ltlibs)
check_PROGRAMS += $(all_test_programs)
check_SCRIPTS += $(all_test_scripts)
check_DATA += $(all_test_data)
endif
if ENABLE_INSTALLED_TESTS
installed_test_PROGRAMS += $(test_programs) $(installed_test_programs) \
$(test_extra_programs) $(installed_test_extra_programs)
installed_test_SCRIPTS += $(test_scripts) $(installed_test_scripts) \
$(test_extra_scripts) $(test_installed_extra_scripts)
installed_test_SCRIPTS += $(dist_test_scripts) $(dist_test_extra_scripts) \
$(dist_installed_test_scripts) $(dist_installed_test_extra_scripts)
nobase_installed_test_DATA += $(test_data) $(installed_test_data)
nobase_installed_test_DATA += $(dist_test_data) $(dist_installed_test_data)
installed_test_LTLIBRARIES += $(test_ltlibraries) $(installed_test_ltlibraries)
installed_testcases = $(test_programs) $(installed_test_programs) \
$(test_scripts) $(installed_test_scripts) \
$(dist_test_scripts) $(dist_installed_test_scripts)
installed_test_meta_DATA = $(installed_testcases:=.test)
%.test: %$(EXEEXT) Makefile
$(AM_V_GEN) (echo '[Test]' > $@.tmp; \
echo 'Type=session' >> $@.tmp; \
echo 'Exec=$(installed_testdir)/$<' >> $@.tmp; \
mv $@.tmp $@)
CLEANFILES += $(installed_test_meta_DATA)
endif
pkg-config-0.29.1/glib/depcomp 0000755 0001750 0001750 00000056016 12601774026 013057 0000000 0000000 #! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999-2014 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, see .
# 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 outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to .
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
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"
# Avoid interferences from the environment.
gccflag= dashmflag=
# 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
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
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.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## 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). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - 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 -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# 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.
## 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. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -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 -ne 0; then
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 ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# 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
;;
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.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
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"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
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.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# 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
;;
#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 "X$1" != 'X--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|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| 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 "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
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.
-arch)
eat=yes ;;
-*|$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"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| 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 "X$1" != 'X--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 -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [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.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# 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
;;
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-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
pkg-config-0.29.1/glib/aclocal.m4 0000664 0001750 0001750 00000147362 12665370331 013352 0000000 0000000 # generated automatically by aclocal 1.15 -*- Autoconf -*-
# Copyright (C) 1996-2014 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.
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
[m4_warning([this file was generated for autoconf 2.69.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
# Copyright (C) 2002-2014 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.
# (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.15'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.15], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
# _AM_AUTOCONF_VERSION(VERSION)
# -----------------------------
# aclocal traces this macro to find the Autoconf version.
# This is a private macro too. Using m4_define simplifies
# the logic in aclocal, which can simply ignore this definition.
m4_define([_AM_AUTOCONF_VERSION], [])
# AM_SET_CURRENT_AUTOMAKE_VERSION
# -------------------------------
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.15])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001-2014 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],
[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
# Expand $ac_aux_dir to an absolute path.
am_aux_dir=`cd "$ac_aux_dir" && pwd`
])
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2014 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_CONDITIONAL(NAME, SHELL-CONDITION)
# -------------------------------------
# Define a conditional.
AC_DEFUN([AM_CONDITIONAL],
[AC_PREREQ([2.52])dnl
m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
AC_SUBST([$1_TRUE])dnl
AC_SUBST([$1_FALSE])dnl
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
m4_define([_AM_COND_VALUE_$1], [$2])dnl
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-2014 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.
# 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", "OBJC", "OBJCXX", "UPC", or "GJC".
# 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
m4_if([$1], [CC], [depcc="$CC" am_compiler_list=],
[$1], [CXX], [depcc="$CXX" am_compiler_list=],
[$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
[$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
[$1], [UPC], [depcc="$UPC" am_compiler_list=],
[$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".
rm -rf conftest.dir
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
am__universal=false
m4_case([$1], [CC],
[case " $depcc " in #(
*\ -arch\ *\ -arch\ *) am__universal=true ;;
esac],
[CXX],
[case " $depcc " in #(
*\ -arch\ *\ -arch\ *) am__universal=true ;;
esac])
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 10 /bin/sh.
echo '/* dummy */' > sub/conftst$i.h
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
# 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. Also, some Intel
# versions had trouble with output in subdirs.
am__obj=sub/conftest.${OBJEXT-o}
am__minus_obj="-o $am__obj"
case $depmode in
gcc)
# This depmode causes a compiler race in universal mode.
test "$am__universal" = false || continue
;;
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
;;
msvc7 | msvc7msys | msvisualcpp | msvcmsys)
# This compiler won't grok '-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
am__obj=conftest.${OBJEXT-o}
am__minus_obj=
;;
none) break ;;
esac
if depmode=$depmode \
source=sub/conftest.c object=$am__obj \
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
$SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
>/dev/null 2>conftest.err &&
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
grep $am__obj 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], [dnl
AS_HELP_STRING(
[--enable-dependency-tracking],
[do not reject slow dependency extractors])
AS_HELP_STRING(
[--disable-dependency-tracking],
[speeds up one-time build])])
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
am__nodep='_no'
fi
AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
AC_SUBST([AMDEPBACKSLASH])dnl
_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
AC_SUBST([am__nodep])dnl
_AM_SUBST_NOTMAKE([am__nodep])dnl
])
# Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999-2014 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_OUTPUT_DEPENDENCY_COMMANDS
# ------------------------------
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
[{
# Older Autoconf quotes --file arguments for eval, but not when files
# are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting.
case $CONFIG_FILES in
*\'*) eval set x "$CONFIG_FILES" ;;
*) set x $CONFIG_FILES ;;
esac
shift
for mf
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.
# Grep'ing the whole file is not good either: AIX grep has a line
# limit of 2048, but all sed's we know have understand at least 4000.
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/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"`
# 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'`; 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"])
])
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996-2014 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 macro actually does too much. Some checks are only needed if
# your package does certain things. But this isn't really a big deal.
dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
m4_define([AC_PROG_CC],
m4_defn([AC_PROG_CC])
[_AM_PROG_CC_C_O
])
# 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.65])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
if test "`cd $srcdir && pwd`" != "`pwd`"; then
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
# is not polluted with repeated "-I."
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
# test to see if srcdir already configured
if test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
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],
[AC_DIAGNOSE([obsolete],
[$0: two- and three-arguments forms are deprecated.])
m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
AC_SUBST([PACKAGE], [$1])dnl
AC_SUBST([VERSION], [$2])],
[_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
m4_if(
m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
[ok:ok],,
[m4_fatal([AC_INIT should be called with package and version arguments])])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])
AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
# For better backward compatibility. To be removed once Automake 1.9.x
# dies out for good. For more background, see:
#
#
AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
# We need awk for the "check" target (and possibly the TAP driver). 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])],
[m4_define([AC_PROG_CC],
m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
AC_PROVIDE_IFELSE([AC_PROG_CXX],
[_AM_DEPENDENCIES([CXX])],
[m4_define([AC_PROG_CXX],
m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
[_AM_DEPENDENCIES([OBJC])],
[m4_define([AC_PROG_OBJC],
m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
[_AM_DEPENDENCIES([OBJCXX])],
[m4_define([AC_PROG_OBJCXX],
m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
])
AC_REQUIRE([AM_SILENT_RULES])dnl
dnl The testsuite driver may need to know about EXEEXT, so add the
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
AC_CONFIG_COMMANDS_PRE(dnl
[m4_provide_if([_AM_COMPILER_EXEEXT],
[AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
# POSIX will say in a future version that running "rm -f" with no argument
# is OK; and we want to be able to make that assumption in our Makefile
# recipes. So use an aggressive probe to check that the usage we want is
# actually supported "in the wild" to an acceptable degree.
# See automake bug#10828.
# To make any issue more visible, cause the running configure to be aborted
# by default if the 'rm' program in use doesn't match our expectations; the
# user can still override this though.
if rm -f && rm -fr && rm -rf; then : OK; else
cat >&2 <<'END'
Oops!
Your 'rm' program seems unable to run without file operands specified
on the command line, even when the '-f' option is present. This is contrary
to the behaviour of most rm programs out there, and not conforming with
the upcoming POSIX standard:
Please tell bug-automake@gnu.org about your system, including the value
of your $PATH and any error possibly output before this message. This
can help us improve future automake versions.
END
if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
echo 'Configuration will proceed anyway, since you have set the' >&2
echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
echo >&2
else
cat >&2 <<'END'
Aborting the configuration process, to ensure you take notice of the issue.
You can download and install GNU coreutils to get an 'rm' implementation
that behaves properly: .
If you want to complete the configuration process using your problematic
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
to "yes", and re-run configure.
END
AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
fi
fi
dnl The trailing newline in this macro's definition is deliberate, for
dnl backward compatibility and to allow trailing 'dnl'-style comments
dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
])
dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
dnl mangled by Autoconf and run in a shell conditional statement.
m4_define([_AC_COMPILER_EXEEXT],
m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
# 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_arg=$1
_am_stamp_count=1
for _am_header in $config_headers :; do
case $_am_header in
$_am_arg | $_am_arg:* )
break ;;
* )
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
esac
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001-2014 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
if test x"${install_sh+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
*)
install_sh="\${SHELL} $am_aux_dir/install-sh"
esac
fi
AC_SUBST([install_sh])])
# Copyright (C) 2003-2014 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.
# 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])])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
# Copyright (C) 1996-2014 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_MAINTAINER_MODE([DEFAULT-MODE])
# ----------------------------------
# Control maintainer-specific portions of Makefiles.
# Default is to disable them, unless 'enable' is passed literally.
# For symmetry, 'disable' may be passed as well. Anyway, the user
# can override the default with the --enable/--disable switch.
AC_DEFUN([AM_MAINTAINER_MODE],
[m4_case(m4_default([$1], [disable]),
[enable], [m4_define([am_maintainer_other], [disable])],
[disable], [m4_define([am_maintainer_other], [enable])],
[m4_define([am_maintainer_other], [enable])
m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
dnl maintainer-mode's default is 'disable' unless 'enable' is passed
AC_ARG_ENABLE([maintainer-mode],
[AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode],
am_maintainer_other[ make rules and dependencies not useful
(and sometimes confusing) to the casual installer])],
[USE_MAINTAINER_MODE=$enableval],
[USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
AC_MSG_RESULT([$USE_MAINTAINER_MODE])
AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
MAINT=$MAINTAINER_MODE_TRUE
AC_SUBST([MAINT])dnl
]
)
# Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001-2014 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_MAKE_INCLUDE()
# -----------------
# Check to see how make treats includes.
AC_DEFUN([AM_MAKE_INCLUDE],
[am_make=${MAKE-make}
cat > confinc << 'END'
am__doit:
@echo this is the am__doit target
.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
# Ignore all kinds of additional output from 'make'.
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=include
am__quote=
_am_result=GNU
;;
esac
# Now try BSD make style include.
if test "$am__include" = "#"; then
echo '.include "confinc"' > confmf
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=.include
am__quote="\""
_am_result=BSD
;;
esac
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-2014 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_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 is modern enough.
# If it is, set am_missing_run to use it, otherwise, to nothing.
AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then
am_missing_run="$MISSING "
else
am_missing_run=
AC_MSG_WARN(['missing' script is too old or missing])
fi
])
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001-2014 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_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],
[m4_foreach_w([_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])])
# Copyright (C) 1999-2014 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_CC_C_O
# ---------------
# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC
# to automatically call this.
AC_DEFUN([_AM_PROG_CC_C_O],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([compile])dnl
AC_LANG_PUSH([C])dnl
AC_CACHE_CHECK(
[whether $CC understands -c and -o together],
[am_cv_prog_cc_c_o],
[AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
# Make sure it works both with $CC and with simple cc.
# Following AC_PROG_CC_C_O, we do the test twice because some
# compilers refuse to overwrite an existing .o file with -o,
# though they will create one.
am_cv_prog_cc_c_o=yes
for am_i in 1 2; do
if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
&& test -f conftest2.$ac_objext; then
: OK
else
am_cv_prog_cc_c_o=no
break
fi
done
rm -f core conftest*
unset am_i])
if test "$am_cv_prog_cc_c_o" != yes; then
# Losing compiler, so override with the script.
# FIXME: It is wrong to rewrite CC.
# But if we don't then we get into trouble of one sort or another.
# A longer-term fix would be to have automake use am__CC in this case,
# and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
CC="$am_aux_dir/compile $CC"
fi
AC_LANG_POP([C])])
# For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
# Copyright (C) 1999-2014 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_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
# ---------------------------------------------------------------------------
# Adds support for distributing Python modules and packages. To
# install modules, copy them to $(pythondir), using the python_PYTHON
# automake variable. To install a package with the same name as the
# automake package, install to $(pkgpythondir), or use the
# pkgpython_PYTHON automake variable.
#
# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as
# locations to install python extension modules (shared libraries).
# Another macro is required to find the appropriate flags to compile
# extension modules.
#
# If your package is configured with a different prefix to python,
# users will have to add the install directory to the PYTHONPATH
# environment variable, or create a .pth file (see the python
# documentation for details).
#
# If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will
# cause an error if the version of python installed on the system
# doesn't meet the requirement. MINIMUM-VERSION should consist of
# numbers and dots only.
AC_DEFUN([AM_PATH_PYTHON],
[
dnl Find a Python interpreter. Python versions prior to 2.0 are not
dnl supported. (2.0 was released on October 16, 2000).
m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
[python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl
python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0])
AC_ARG_VAR([PYTHON], [the Python interpreter])
m4_if([$1],[],[
dnl No version check is needed.
# Find any Python interpreter.
if test -z "$PYTHON"; then
AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :)
fi
am_display_PYTHON=python
], [
dnl A version check is needed.
if test -n "$PYTHON"; then
# If the user set $PYTHON, use it and don't search something else.
AC_MSG_CHECKING([whether $PYTHON version is >= $1])
AM_PYTHON_CHECK_VERSION([$PYTHON], [$1],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
AC_MSG_ERROR([Python interpreter is too old])])
am_display_PYTHON=$PYTHON
else
# Otherwise, try each interpreter until we find one that satisfies
# VERSION.
AC_CACHE_CHECK([for a Python interpreter with version >= $1],
[am_cv_pathless_PYTHON],[
for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do
test "$am_cv_pathless_PYTHON" = none && break
AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break])
done])
# Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON.
if test "$am_cv_pathless_PYTHON" = none; then
PYTHON=:
else
AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON])
fi
am_display_PYTHON=$am_cv_pathless_PYTHON
fi
])
if test "$PYTHON" = :; then
dnl Run any user-specified action, or abort.
m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])])
else
dnl Query Python for its version number. Getting [:3] seems to be
dnl the best way to do this; it's what "site.py" does in the standard
dnl library.
AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version],
[am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`])
AC_SUBST([PYTHON_VERSION], [$am_cv_python_version])
dnl Use the values of $prefix and $exec_prefix for the corresponding
dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made
dnl distinct variables so they can be overridden if need be. However,
dnl general consensus is that you shouldn't need this ability.
AC_SUBST([PYTHON_PREFIX], ['${prefix}'])
AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}'])
dnl At times (like when building shared libraries) you may want
dnl to know which OS platform Python thinks this is.
AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform],
[am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`])
AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform])
# Just factor out some code duplication.
am_python_setup_sysconfig="\
import sys
# Prefer sysconfig over distutils.sysconfig, for better compatibility
# with python 3.x. See automake bug#10227.
try:
import sysconfig
except ImportError:
can_use_sysconfig = 0
else:
can_use_sysconfig = 1
# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs:
#
try:
from platform import python_implementation
if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7':
can_use_sysconfig = 0
except ImportError:
pass"
dnl Set up 4 directories:
dnl pythondir -- where to install python scripts. This is the
dnl site-packages directory, not the python standard library
dnl directory like in previous automake betas. This behavior
dnl is more consistent with lispdir.m4 for example.
dnl Query distutils for this directory.
AC_CACHE_CHECK([for $am_display_PYTHON script directory],
[am_cv_python_pythondir],
[if test "x$prefix" = xNONE
then
am_py_prefix=$ac_default_prefix
else
am_py_prefix=$prefix
fi
am_cv_python_pythondir=`$PYTHON -c "
$am_python_setup_sysconfig
if can_use_sysconfig:
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
else:
from distutils import sysconfig
sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
sys.stdout.write(sitedir)"`
case $am_cv_python_pythondir in
$am_py_prefix*)
am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'`
am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"`
;;
*)
case $am_py_prefix in
/usr|/System*) ;;
*)
am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages
;;
esac
;;
esac
])
AC_SUBST([pythondir], [$am_cv_python_pythondir])
dnl pkgpythondir -- $PACKAGE directory under pythondir. Was
dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is
dnl more consistent with the rest of automake.
AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE])
dnl pyexecdir -- directory for installing python extension modules
dnl (shared libraries)
dnl Query distutils for this directory.
AC_CACHE_CHECK([for $am_display_PYTHON extension module directory],
[am_cv_python_pyexecdir],
[if test "x$exec_prefix" = xNONE
then
am_py_exec_prefix=$am_py_prefix
else
am_py_exec_prefix=$exec_prefix
fi
am_cv_python_pyexecdir=`$PYTHON -c "
$am_python_setup_sysconfig
if can_use_sysconfig:
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'})
else:
from distutils import sysconfig
sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix')
sys.stdout.write(sitedir)"`
case $am_cv_python_pyexecdir in
$am_py_exec_prefix*)
am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'`
am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"`
;;
*)
case $am_py_exec_prefix in
/usr|/System*) ;;
*)
am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages
;;
esac
;;
esac
])
AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir])
dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE)
AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE])
dnl Run any user-specified action.
$2
fi
])
# AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
# ---------------------------------------------------------------------------
# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION.
# Run ACTION-IF-FALSE otherwise.
# This test uses sys.hexversion instead of the string equivalent (first
# word of sys.version), in order to cope with versions such as 2.2c1.
# This supports Python 2.0 or higher. (2.0 was released on October 16, 2000).
AC_DEFUN([AM_PYTHON_CHECK_VERSION],
[prog="import sys
# split strings by '.' and convert to numeric. Append some zeros
# because we need at least 4 digits for the hex conversion.
# map returns an iterator in Python 3.0 and a list in 2.x
minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]]
minverhex = 0
# xrange is not present in Python 3.0 and range returns an iterator
for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]]
sys.exit(sys.hexversion < minverhex)"
AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])])
# Copyright (C) 2001-2014 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_RUN_LOG(COMMAND)
# -------------------
# Run COMMAND, save the exit status in ac_status, and log it.
# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
AC_DEFUN([AM_RUN_LOG],
[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
(exit $ac_status); }])
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996-2014 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_SANITY_CHECK
# ---------------
AC_DEFUN([AM_SANITY_CHECK],
[AC_MSG_CHECKING([whether build environment is sane])
# Reject unsafe characters in $srcdir or the absolute working directory
# name. Accept space and tab only in the latter.
am_lf='
'
case `pwd` in
*[[\\\"\#\$\&\'\`$am_lf]]*)
AC_MSG_ERROR([unsafe absolute working directory name]);;
esac
case $srcdir in
*[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
esac
# 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 (
am_has_slept=no
for am_try in 1 2; do
echo "timestamp, slept: $am_has_slept" > conftest.file
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
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
if test "$[2]" = conftest.file || test $am_try -eq 2; then
break
fi
# Just in case.
sleep 1
am_has_slept=yes
done
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])
# If we didn't sleep, we still need to ensure time stamps of config.status and
# generated files are strictly newer.
am_sleep_pid=
if grep 'slept: no' conftest.file >/dev/null 2>&1; then
( sleep 1 ) &
am_sleep_pid=$!
fi
AC_CONFIG_COMMANDS_PRE(
[AC_MSG_CHECKING([that generated files are newer than configure])
if test -n "$am_sleep_pid"; then
# Hide warnings about reused PIDs.
wait $am_sleep_pid 2>/dev/null
fi
AC_MSG_RESULT([done])])
rm -f conftest.file
])
# Copyright (C) 2009-2014 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_SILENT_RULES([DEFAULT])
# --------------------------
# Enable less verbose build rules; with the default set to DEFAULT
# ("yes" being less verbose, "no" or empty being verbose).
AC_DEFUN([AM_SILENT_RULES],
[AC_ARG_ENABLE([silent-rules], [dnl
AS_HELP_STRING(
[--enable-silent-rules],
[less verbose build output (undo: "make V=1")])
AS_HELP_STRING(
[--disable-silent-rules],
[verbose build output (undo: "make V=0")])dnl
])
case $enable_silent_rules in @%:@ (((
yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
*) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
esac
dnl
dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
dnl do not support nested variable expansions.
dnl See automake bug#9928 and bug#10237.
am_make=${MAKE-make}
AC_CACHE_CHECK([whether $am_make supports nested variables],
[am_cv_make_support_nested_variables],
[if AS_ECHO([['TRUE=$(BAR$(V))
BAR0=false
BAR1=true
V=1
am__doit:
@$(TRUE)
.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
am_cv_make_support_nested_variables=yes
else
am_cv_make_support_nested_variables=no
fi])
if test $am_cv_make_support_nested_variables = yes; then
dnl Using '$V' instead of '$(V)' breaks IRIX make.
AM_V='$(V)'
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
AM_V=$AM_DEFAULT_VERBOSITY
AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
AC_SUBST([AM_V])dnl
AM_SUBST_NOTMAKE([AM_V])dnl
AC_SUBST([AM_DEFAULT_V])dnl
AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
AM_BACKSLASH='\'
AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
# Copyright (C) 2001-2014 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="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006-2014 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_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
# This macro is traced by Automake.
AC_DEFUN([_AM_SUBST_NOTMAKE])
# AM_SUBST_NOTMAKE(VARIABLE)
# --------------------------
# Public sister of _AM_SUBST_NOTMAKE.
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004-2014 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_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. Yes, it's still used
# in the wild :-( We should find a proper way to deprecate it ...
AC_SUBST([AMTAR], ['$${TAR-tar}'])
# We'll loop over all known methods to create a tar archive until one works.
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
m4_if([$1], [v7],
[am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
[m4_case([$1],
[ustar],
[# The POSIX 1988 'ustar' format is defined with fixed-size fields.
# There is notably a 21 bits limit for the UID and the GID. In fact,
# the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
# and bug#13588).
am_max_uid=2097151 # 2^21 - 1
am_max_gid=$am_max_uid
# The $UID and $GID variables are not portable, so we need to resort
# to the POSIX-mandated id(1) utility. Errors in the 'id' calls
# below are definitely unexpected, so allow the users to see them
# (that is, avoid stderr redirection).
am_uid=`id -u || echo unknown`
am_gid=`id -g || echo unknown`
AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
if test $am_uid -le $am_max_uid; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
_am_tools=none
fi
AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
if test $am_gid -le $am_max_gid; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
_am_tools=none
fi],
[pax],
[],
[m4_fatal([Unknown tar format])])
AC_MSG_CHECKING([how to create a $1 tar archive])
# Go ahead even if we have the value already cached. We do so because we
# need to set the values for the 'am__tar' and 'am__untar' variables.
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
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([m4macros/attributes.m4])
m4_include([m4macros/glibtests.m4])
m4_include([m4macros/libtool.m4])
m4_include([m4macros/ltoptions.m4])
m4_include([m4macros/ltsugar.m4])
m4_include([m4macros/ltversion.m4])
m4_include([m4macros/lt~obsolete.m4])
m4_include([acinclude.m4])
pkg-config-0.29.1/glib/acglib.m4 0000664 0001750 0001750 00000010701 12275467762 013173 0000000 0000000 ## Portability defines that help interoperate with classic and modern autoconfs
ifdef([AC_TR_SH],[
define([GLIB_TR_SH],[AC_TR_SH([$1])])
define([GLIB_TR_CPP],[AC_TR_CPP([$1])])
], [
define([GLIB_TR_SH],
[patsubst(translit([[$1]], [*+], [pp]), [[^a-zA-Z0-9_]], [_])])
define([GLIB_TR_CPP],
[patsubst(translit([[$1]],
[*abcdefghijklmnopqrstuvwxyz],
[PABCDEFGHIJKLMNOPQRSTUVWXYZ]),
[[^A-Z0-9_]], [_])])
])
# GLIB_AC_DIVERT_BEFORE_HELP(STUFF)
# ---------------------------------
# Put STUFF early enough so that they are available for $ac_help expansion.
# Handle both classic (<= v2.13) and modern autoconf
AC_DEFUN([GLIB_AC_DIVERT_BEFORE_HELP],
[ifdef([m4_divert_text], [m4_divert_text([NOTICE],[$1])],
[ifdef([AC_DIVERT], [AC_DIVERT([NOTICE],[$1])],
[AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl
$1
AC_DIVERT_POP()])])])
dnl GLIB_IF_VAR_EQ (ENV_VAR, VALUE [, EQUALS_ACTION] [, ELSE_ACTION])
AC_DEFUN([GLIB_IF_VAR_EQ],[
case "$[$1]" in
"[$2]"[)]
[$3]
;;
*[)]
[$4]
;;
esac
])
dnl GLIB_STR_CONTAINS (SRC_STRING, SUB_STRING [, CONTAINS_ACTION] [, ELSE_ACTION])
AC_DEFUN([GLIB_STR_CONTAINS],[
case "[$1]" in
*"[$2]"*[)]
[$3]
;;
*[)]
[$4]
;;
esac
])
dnl GLIB_ADD_TO_VAR (ENV_VARIABLE, CHECK_STRING, ADD_STRING)
AC_DEFUN([GLIB_ADD_TO_VAR],[
GLIB_STR_CONTAINS($[$1], [$2], [$1]="$[$1]", [$1]="$[$1] [$3]")
])
# GLIB_SIZEOF (INCLUDES, TYPE, ALIAS)
# ---------------------------------------------------------------
# The definition here is based of that of AC_CHECK_SIZEOF
AC_DEFUN([GLIB_SIZEOF],
[AS_LITERAL_IF([$3], [],
[AC_FATAL([$0: requires literal arguments])])dnl
AC_CACHE_CHECK([size of $2], AS_TR_SH([glib_cv_sizeof_$3]),
[ # The cast to unsigned long works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
_AC_COMPUTE_INT([(long) (sizeof ($2))],
[AS_TR_SH([glib_cv_sizeof_$3])],
[AC_INCLUDES_DEFAULT([$1])],
[AC_MSG_ERROR([cannot compute sizeof ($2), 77])])
])dnl
AC_DEFINE_UNQUOTED(GLIB_TR_CPP(glib_sizeof_$3), $AS_TR_SH([glib_cv_sizeof_$3]),
[The size of $3, as computed by sizeof.])
])# GLIB_SIZEOF
dnl GLIB_BYTE_CONTENTS (INCLUDES, TYPE, ALIAS, N_BYTES, INITIALIZER)
AC_DEFUN([GLIB_BYTE_CONTENTS],
[pushdef([glib_ByteContents], GLIB_TR_SH([glib_cv_byte_contents_$3]))dnl
AC_CACHE_CHECK([byte contents of $5], glib_ByteContents,
[AC_TRY_RUN([#include
$1
main()
{
static $2 tv = $5;
char *p = (char*) &tv;
int i;
FILE *f=fopen("conftestval", "w");
if (!f) exit(1);
for (i = 0; i < $4; i++)
fprintf(f, "%s%d", i?",":"", *(p++));
fprintf(f, "\n");
exit(0);
}],
[glib_ByteContents=`cat conftestval` dnl''
],
[glib_ByteContents=no],
[glib_ByteContents=no])])
AC_DEFINE_UNQUOTED(GLIB_TR_CPP(glib_byte_contents_$3), [$[]glib_ByteContents],
[Byte contents of $3])
popdef([glib_ByteContents])dnl
])
# GLIB_CHECK_VALUE(SYMBOL, INCLUDES, ACTION-IF-FAIL)
# ---------------------------------------------------------------
AC_DEFUN([GLIB_CHECK_VALUE],
[AC_CACHE_CHECK([value of $1], AS_TR_SH([glib_cv_value_$1]),
[_AC_COMPUTE_INT([$1], AS_TR_SH([glib_cv_value_$1]), [$2], [$3])])
])dnl
# GLIB_CHECK_COMPILE_WARNINGS(PROGRAM, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
# ---------------------------------------------------------------------
# Try to compile PROGRAM, check for warnings
m4_define([GLIB_CHECK_COMPILE_WARNINGS],
[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl
rm -f conftest.$ac_objext
glib_ac_compile_save="$ac_compile"
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext'
AS_IF([_AC_EVAL_STDERR($ac_compile) &&
AC_TRY_COMMAND([(if test -s conftest.err; then false ; else true; fi)])],
[$2],
[echo "$as_me: failed program was:" >&AS_MESSAGE_LOG_FD
cat conftest.$ac_ext >&AS_MESSAGE_LOG_FD
m4_ifvaln([$3],[$3])dnl])
ac_compile="$glib_ac_compile_save"
rm -f conftest.$ac_objext conftest.err m4_ifval([$1], [conftest.$ac_ext])[]dnl
])# GLIB_CHECK_COMPILE_WARNINGS
# GLIB_ASSERT_SET(VARIABLE)
# -------------------------
AC_DEFUN([GLIB_ASSERT_SET],
[if test "x${$1+set}" != "xset" ; then
AC_MSG_ERROR($1 [must be set in cache file when cross-compiling.])
fi
])dnl
pkg-config-0.29.1/glib/glib/ 0000775 0001750 0001750 00000000000 12665370350 012473 5 0000000 0000000 pkg-config-0.29.1/glib/glib/gmappedfile.h 0000664 0001750 0001750 00000004044 12651243552 015041 0000000 0000000 /* GLIB - Library of useful routines for C programming
* gmappedfile.h: Simplified wrapper around the mmap function
*
* Copyright 2005 Matthias Clasen
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __G_MAPPED_FILE_H__
#define __G_MAPPED_FILE_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
#include
G_BEGIN_DECLS
typedef struct _GMappedFile GMappedFile;
GLIB_AVAILABLE_IN_ALL
GMappedFile *g_mapped_file_new (const gchar *filename,
gboolean writable,
GError **error) G_GNUC_MALLOC;
GLIB_AVAILABLE_IN_ALL
GMappedFile *g_mapped_file_new_from_fd (gint fd,
gboolean writable,
GError **error) G_GNUC_MALLOC;
GLIB_AVAILABLE_IN_ALL
gsize g_mapped_file_get_length (GMappedFile *file);
GLIB_AVAILABLE_IN_ALL
gchar *g_mapped_file_get_contents (GMappedFile *file);
GLIB_AVAILABLE_IN_2_34
GBytes * g_mapped_file_get_bytes (GMappedFile *file);
GLIB_AVAILABLE_IN_ALL
GMappedFile *g_mapped_file_ref (GMappedFile *file);
GLIB_AVAILABLE_IN_ALL
void g_mapped_file_unref (GMappedFile *file);
GLIB_DEPRECATED_FOR(g_mapped_file_unref)
void g_mapped_file_free (GMappedFile *file);
G_END_DECLS
#endif /* __G_MAPPED_FILE_H__ */
pkg-config-0.29.1/glib/glib/gvariant.c 0000664 0001750 0001750 00000464577 12651243552 014417 0000000 0000000 /*
* Copyright © 2007, 2008 Ryan Lortie
* Copyright © 2010 Codethink Limited
*
* This 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 of the licence, 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ryan Lortie
*/
/* Prologue {{{1 */
#include "config.h"
#include
#include "gvariant-internal.h"
#include
#include
#include
#include
#include
#include
#include
/**
* SECTION:gvariant
* @title: GVariant
* @short_description: strongly typed value datatype
* @see_also: GVariantType
*
* #GVariant is a variant datatype; it stores a value along with
* information about the type of that value. The range of possible
* values is determined by the type. The type system used by #GVariant
* is #GVariantType.
*
* #GVariant instances always have a type and a value (which are given
* at construction time). The type and value of a #GVariant instance
* can never change other than by the #GVariant itself being
* destroyed. A #GVariant cannot contain a pointer.
*
* #GVariant is reference counted using g_variant_ref() and
* g_variant_unref(). #GVariant also has floating reference counts --
* see g_variant_ref_sink().
*
* #GVariant is completely threadsafe. A #GVariant instance can be
* concurrently accessed in any way from any number of threads without
* problems.
*
* #GVariant is heavily optimised for dealing with data in serialised
* form. It works particularly well with data located in memory-mapped
* files. It can perform nearly all deserialisation operations in a
* small constant time, usually touching only a single memory page.
* Serialised #GVariant data can also be sent over the network.
*
* #GVariant is largely compatible with D-Bus. Almost all types of
* #GVariant instances can be sent over D-Bus. See #GVariantType for
* exceptions. (However, #GVariant's serialisation format is not the same
* as the serialisation format of a D-Bus message body: use #GDBusMessage,
* in the gio library, for those.)
*
* For space-efficiency, the #GVariant serialisation format does not
* automatically include the variant's type or endianness, which must
* either be implied from context (such as knowledge that a particular
* file format always contains a little-endian %G_VARIANT_TYPE_VARIANT)
* or supplied out-of-band (for instance, a type and/or endianness
* indicator could be placed at the beginning of a file, network message
* or network stream).
*
* A #GVariant's size is limited mainly by any lower level operating
* system constraints, such as the number of bits in #gsize. For
* example, it is reasonable to have a 2GB file mapped into memory
* with #GMappedFile, and call g_variant_new_from_data() on it.
*
* For convenience to C programmers, #GVariant features powerful
* varargs-based value construction and destruction. This feature is
* designed to be embedded in other libraries.
*
* There is a Python-inspired text language for describing #GVariant
* values. #GVariant includes a printer for this language and a parser
* with type inferencing.
*
*
* Memory Use
*
* #GVariant tries to be quite efficient with respect to memory use.
* This section gives a rough idea of how much memory is used by the
* current implementation. The information here is subject to change
* in the future.
*
*
* The memory allocated by #GVariant can be grouped into 4 broad
* purposes: memory for serialised data, memory for the type
* information cache, buffer management memory and memory for the
* #GVariant structure itself.
*
*
* Serialised Data Memory
*
* This is the memory that is used for storing GVariant data in
* serialised form. This is what would be sent over the network or
* what would end up on disk.
*
*
* The amount of memory required to store a boolean is 1 byte. 16,
* 32 and 64 bit integers and double precision floating point numbers
* use their "natural" size. Strings (including object path and
* signature strings) are stored with a nul terminator, and as such
* use the length of the string plus 1 byte.
*
*
* Maybe types use no space at all to represent the null value and
* use the same amount of space (sometimes plus one byte) as the
* equivalent non-maybe-typed value to represent the non-null case.
*
*
* Arrays use the amount of space required to store each of their
* members, concatenated. Additionally, if the items stored in an
* array are not of a fixed-size (ie: strings, other arrays, etc)
* then an additional framing offset is stored for each item. The
* size of this offset is either 1, 2 or 4 bytes depending on the
* overall size of the container. Additionally, extra padding bytes
* are added as required for alignment of child values.
*
*
* Tuples (including dictionary entries) use the amount of space
* required to store each of their members, concatenated, plus one
* framing offset (as per arrays) for each non-fixed-sized item in
* the tuple, except for the last one. Additionally, extra padding
* bytes are added as required for alignment of child values.
*
*
* Variants use the same amount of space as the item inside of the
* variant, plus 1 byte, plus the length of the type string for the
* item inside the variant.
*
*
* As an example, consider a dictionary mapping strings to variants.
* In the case that the dictionary is empty, 0 bytes are required for
* the serialisation.
*
*
* If we add an item "width" that maps to the int32 value of 500 then
* we will use 4 byte to store the int32 (so 6 for the variant
* containing it) and 6 bytes for the string. The variant must be
* aligned to 8 after the 6 bytes of the string, so that's 2 extra
* bytes. 6 (string) + 2 (padding) + 6 (variant) is 14 bytes used
* for the dictionary entry. An additional 1 byte is added to the
* array as a framing offset making a total of 15 bytes.
*
*
* If we add another entry, "title" that maps to a nullable string
* that happens to have a value of null, then we use 0 bytes for the
* null value (and 3 bytes for the variant to contain it along with
* its type string) plus 6 bytes for the string. Again, we need 2
* padding bytes. That makes a total of 6 + 2 + 3 = 11 bytes.
*
*
* We now require extra padding between the two items in the array.
* After the 14 bytes of the first item, that's 2 bytes required. We
* now require 2 framing offsets for an extra two bytes. 14 + 2 + 11
* + 2 = 29 bytes to encode the entire two-item dictionary.
*
*
*
* Type Information Cache
*
* For each GVariant type that currently exists in the program a type
* information structure is kept in the type information cache. The
* type information structure is required for rapid deserialisation.
*
*
* Continuing with the above example, if a #GVariant exists with the
* type "a{sv}" then a type information struct will exist for
* "a{sv}", "{sv}", "s", and "v". Multiple uses of the same type
* will share the same type information. Additionally, all
* single-digit types are stored in read-only static memory and do
* not contribute to the writable memory footprint of a program using
* #GVariant.
*
*
* Aside from the type information structures stored in read-only
* memory, there are two forms of type information. One is used for
* container types where there is a single element type: arrays and
* maybe types. The other is used for container types where there
* are multiple element types: tuples and dictionary entries.
*
*
* Array type info structures are 6 * sizeof (void *), plus the
* memory required to store the type string itself. This means that
* on 32bit systems, the cache entry for "a{sv}" would require 30
* bytes of memory (plus malloc overhead).
*
*
* Tuple type info structures are 6 * sizeof (void *), plus 4 *
* sizeof (void *) for each item in the tuple, plus the memory
* required to store the type string itself. A 2-item tuple, for
* example, would have a type information structure that consumed
* writable memory in the size of 14 * sizeof (void *) (plus type
* string) This means that on 32bit systems, the cache entry for
* "{sv}" would require 61 bytes of memory (plus malloc overhead).
*
*
* This means that in total, for our "a{sv}" example, 91 bytes of
* type information would be allocated.
*
*
* The type information cache, additionally, uses a #GHashTable to
* store and lookup the cached items and stores a pointer to this
* hash table in static storage. The hash table is freed when there
* are zero items in the type cache.
*
*
* Although these sizes may seem large it is important to remember
* that a program will probably only have a very small number of
* different types of values in it and that only one type information
* structure is required for many different values of the same type.
*
*
*
* Buffer Management Memory
*
* #GVariant uses an internal buffer management structure to deal
* with the various different possible sources of serialised data
* that it uses. The buffer is responsible for ensuring that the
* correct call is made when the data is no longer in use by
* #GVariant. This may involve a g_free() or a g_slice_free() or
* even g_mapped_file_unref().
*
*
* One buffer management structure is used for each chunk of
* serialised data. The size of the buffer management structure is 4
* * (void *). On 32bit systems, that's 16 bytes.
*
*
*
* GVariant structure
*
* The size of a #GVariant structure is 6 * (void *). On 32 bit
* systems, that's 24 bytes.
*
*
* #GVariant structures only exist if they are explicitly created
* with API calls. For example, if a #GVariant is constructed out of
* serialised data for the example given above (with the dictionary)
* then although there are 9 individual values that comprise the
* entire dictionary (two keys, two values, two variants containing
* the values, two dictionary entries, plus the dictionary itself),
* only 1 #GVariant instance exists -- the one referring to the
* dictionary.
*
*
* If calls are made to start accessing the other values then
* #GVariant instances will exist for those values only for as long
* as they are in use (ie: until you call g_variant_unref()). The
* type information is shared. The serialised data and the buffer
* management structure for that serialised data is shared by the
* child.
*
*
*
* Summary
*
* To put the entire example together, for our dictionary mapping
* strings to variants (with two entries, as given above), we are
* using 91 bytes of memory for type information, 29 byes of memory
* for the serialised data, 16 bytes for buffer management and 24
* bytes for the #GVariant instance, or a total of 160 bytes, plus
* malloc overhead. If we were to use g_variant_get_child_value() to
* access the two dictionary entries, we would use an additional 48
* bytes. If we were to have other dictionaries of the same type, we
* would use more memory for the serialised data and buffer
* management for those dictionaries, but the type information would
* be shared.
*
*
*
*/
/* definition of GVariant structure is in gvariant-core.c */
/* this is a g_return_val_if_fail() for making
* sure a (GVariant *) has the required type.
*/
#define TYPE_CHECK(value, TYPE, val) \
if G_UNLIKELY (!g_variant_is_of_type (value, TYPE)) { \
g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, \
"g_variant_is_of_type (" #value \
", " #TYPE ")"); \
return val; \
}
/* Numeric Type Constructor/Getters {{{1 */
/* < private >
* g_variant_new_from_trusted:
* @type: the #GVariantType
* @data: the data to use
* @size: the size of @data
*
* Constructs a new trusted #GVariant instance from the provided data.
* This is used to implement g_variant_new_* for all the basic types.
*
* Returns: a new floating #GVariant
*/
static GVariant *
g_variant_new_from_trusted (const GVariantType *type,
gconstpointer data,
gsize size)
{
GVariant *value;
GBytes *bytes;
bytes = g_bytes_new (data, size);
value = g_variant_new_from_bytes (type, bytes, TRUE);
g_bytes_unref (bytes);
return value;
}
/**
* g_variant_new_boolean:
* @value: a #gboolean value
*
* Creates a new boolean #GVariant instance -- either %TRUE or %FALSE.
*
* Returns: (transfer none): a floating reference to a new boolean #GVariant instance
*
* Since: 2.24
**/
GVariant *
g_variant_new_boolean (gboolean value)
{
guchar v = value;
return g_variant_new_from_trusted (G_VARIANT_TYPE_BOOLEAN, &v, 1);
}
/**
* g_variant_get_boolean:
* @value: a boolean #GVariant instance
*
* Returns the boolean value of @value.
*
* It is an error to call this function with a @value of any type
* other than %G_VARIANT_TYPE_BOOLEAN.
*
* Returns: %TRUE or %FALSE
*
* Since: 2.24
**/
gboolean
g_variant_get_boolean (GVariant *value)
{
const guchar *data;
TYPE_CHECK (value, G_VARIANT_TYPE_BOOLEAN, FALSE);
data = g_variant_get_data (value);
return data != NULL ? *data != 0 : FALSE;
}
/* the constructors and accessors for byte, int{16,32,64}, handles and
* doubles all look pretty much exactly the same, so we reduce
* copy/pasting here.
*/
#define NUMERIC_TYPE(TYPE, type, ctype) \
GVariant *g_variant_new_##type (ctype value) { \
return g_variant_new_from_trusted (G_VARIANT_TYPE_##TYPE, \
&value, sizeof value); \
} \
ctype g_variant_get_##type (GVariant *value) { \
const ctype *data; \
TYPE_CHECK (value, G_VARIANT_TYPE_ ## TYPE, 0); \
data = g_variant_get_data (value); \
return data != NULL ? *data : 0; \
}
/**
* g_variant_new_byte:
* @value: a #guint8 value
*
* Creates a new byte #GVariant instance.
*
* Returns: (transfer none): a floating reference to a new byte #GVariant instance
*
* Since: 2.24
**/
/**
* g_variant_get_byte:
* @value: a byte #GVariant instance
*
* Returns the byte value of @value.
*
* It is an error to call this function with a @value of any type
* other than %G_VARIANT_TYPE_BYTE.
*
* Returns: a #guchar
*
* Since: 2.24
**/
NUMERIC_TYPE (BYTE, byte, guchar)
/**
* g_variant_new_int16:
* @value: a #gint16 value
*
* Creates a new int16 #GVariant instance.
*
* Returns: (transfer none): a floating reference to a new int16 #GVariant instance
*
* Since: 2.24
**/
/**
* g_variant_get_int16:
* @value: a int16 #GVariant instance
*
* Returns the 16-bit signed integer value of @value.
*
* It is an error to call this function with a @value of any type
* other than %G_VARIANT_TYPE_INT16.
*
* Returns: a #gint16
*
* Since: 2.24
**/
NUMERIC_TYPE (INT16, int16, gint16)
/**
* g_variant_new_uint16:
* @value: a #guint16 value
*
* Creates a new uint16 #GVariant instance.
*
* Returns: (transfer none): a floating reference to a new uint16 #GVariant instance
*
* Since: 2.24
**/
/**
* g_variant_get_uint16:
* @value: a uint16 #GVariant instance
*
* Returns the 16-bit unsigned integer value of @value.
*
* It is an error to call this function with a @value of any type
* other than %G_VARIANT_TYPE_UINT16.
*
* Returns: a #guint16
*
* Since: 2.24
**/
NUMERIC_TYPE (UINT16, uint16, guint16)
/**
* g_variant_new_int32:
* @value: a #gint32 value
*
* Creates a new int32 #GVariant instance.
*
* Returns: (transfer none): a floating reference to a new int32 #GVariant instance
*
* Since: 2.24
**/
/**
* g_variant_get_int32:
* @value: a int32 #GVariant instance
*
* Returns the 32-bit signed integer value of @value.
*
* It is an error to call this function with a @value of any type
* other than %G_VARIANT_TYPE_INT32.
*
* Returns: a #gint32
*
* Since: 2.24
**/
NUMERIC_TYPE (INT32, int32, gint32)
/**
* g_variant_new_uint32:
* @value: a #guint32 value
*
* Creates a new uint32 #GVariant instance.
*
* Returns: (transfer none): a floating reference to a new uint32 #GVariant instance
*
* Since: 2.24
**/
/**
* g_variant_get_uint32:
* @value: a uint32 #GVariant instance
*
* Returns the 32-bit unsigned integer value of @value.
*
* It is an error to call this function with a @value of any type
* other than %G_VARIANT_TYPE_UINT32.
*
* Returns: a #guint32
*
* Since: 2.24
**/
NUMERIC_TYPE (UINT32, uint32, guint32)
/**
* g_variant_new_int64:
* @value: a #gint64 value
*
* Creates a new int64 #GVariant instance.
*
* Returns: (transfer none): a floating reference to a new int64 #GVariant instance
*
* Since: 2.24
**/
/**
* g_variant_get_int64:
* @value: a int64 #GVariant instance
*
* Returns the 64-bit signed integer value of @value.
*
* It is an error to call this function with a @value of any type
* other than %G_VARIANT_TYPE_INT64.
*
* Returns: a #gint64
*
* Since: 2.24
**/
NUMERIC_TYPE (INT64, int64, gint64)
/**
* g_variant_new_uint64:
* @value: a #guint64 value
*
* Creates a new uint64 #GVariant instance.
*
* Returns: (transfer none): a floating reference to a new uint64 #GVariant instance
*
* Since: 2.24
**/
/**
* g_variant_get_uint64:
* @value: a uint64 #GVariant instance
*
* Returns the 64-bit unsigned integer value of @value.
*
* It is an error to call this function with a @value of any type
* other than %G_VARIANT_TYPE_UINT64.
*
* Returns: a #guint64
*
* Since: 2.24
**/
NUMERIC_TYPE (UINT64, uint64, guint64)
/**
* g_variant_new_handle:
* @value: a #gint32 value
*
* Creates a new handle #GVariant instance.
*
* By convention, handles are indexes into an array of file descriptors
* that are sent alongside a D-Bus message. If you're not interacting
* with D-Bus, you probably don't need them.
*
* Returns: (transfer none): a floating reference to a new handle #GVariant instance
*
* Since: 2.24
**/
/**
* g_variant_get_handle:
* @value: a handle #GVariant instance
*
* Returns the 32-bit signed integer value of @value.
*
* It is an error to call this function with a @value of any type other
* than %G_VARIANT_TYPE_HANDLE.
*
* By convention, handles are indexes into an array of file descriptors
* that are sent alongside a D-Bus message. If you're not interacting
* with D-Bus, you probably don't need them.
*
* Returns: a #gint32
*
* Since: 2.24
**/
NUMERIC_TYPE (HANDLE, handle, gint32)
/**
* g_variant_new_double:
* @value: a #gdouble floating point value
*
* Creates a new double #GVariant instance.
*
* Returns: (transfer none): a floating reference to a new double #GVariant instance
*
* Since: 2.24
**/
/**
* g_variant_get_double:
* @value: a double #GVariant instance
*
* Returns the double precision floating point value of @value.
*
* It is an error to call this function with a @value of any type
* other than %G_VARIANT_TYPE_DOUBLE.
*
* Returns: a #gdouble
*
* Since: 2.24
**/
NUMERIC_TYPE (DOUBLE, double, gdouble)
/* Container type Constructor / Deconstructors {{{1 */
/**
* g_variant_new_maybe:
* @child_type: (allow-none): the #GVariantType of the child, or %NULL
* @child: (allow-none): the child value, or %NULL
*
* Depending on if @child is %NULL, either wraps @child inside of a
* maybe container or creates a Nothing instance for the given @type.
*
* At least one of @child_type and @child must be non-%NULL.
* If @child_type is non-%NULL then it must be a definite type.
* If they are both non-%NULL then @child_type must be the type
* of @child.
*
* If @child is a floating reference (see g_variant_ref_sink()), the new
* instance takes ownership of @child.
*
* Returns: (transfer none): a floating reference to a new #GVariant maybe instance
*
* Since: 2.24
**/
GVariant *
g_variant_new_maybe (const GVariantType *child_type,
GVariant *child)
{
GVariantType *maybe_type;
GVariant *value;
g_return_val_if_fail (child_type == NULL || g_variant_type_is_definite
(child_type), 0);
g_return_val_if_fail (child_type != NULL || child != NULL, NULL);
g_return_val_if_fail (child_type == NULL || child == NULL ||
g_variant_is_of_type (child, child_type),
NULL);
if (child_type == NULL)
child_type = g_variant_get_type (child);
maybe_type = g_variant_type_new_maybe (child_type);
if (child != NULL)
{
GVariant **children;
gboolean trusted;
children = g_new (GVariant *, 1);
children[0] = g_variant_ref_sink (child);
trusted = g_variant_is_trusted (children[0]);
value = g_variant_new_from_children (maybe_type, children, 1, trusted);
}
else
value = g_variant_new_from_children (maybe_type, NULL, 0, TRUE);
g_variant_type_free (maybe_type);
return value;
}
/**
* g_variant_get_maybe:
* @value: a maybe-typed value
*
* Given a maybe-typed #GVariant instance, extract its value. If the
* value is Nothing, then this function returns %NULL.
*
* Returns: (allow-none) (transfer full): the contents of @value, or %NULL
*
* Since: 2.24
**/
GVariant *
g_variant_get_maybe (GVariant *value)
{
TYPE_CHECK (value, G_VARIANT_TYPE_MAYBE, NULL);
if (g_variant_n_children (value))
return g_variant_get_child_value (value, 0);
return NULL;
}
/**
* g_variant_new_variant: (constructor)
* @value: a #GVariant instance
*
* Boxes @value. The result is a #GVariant instance representing a
* variant containing the original value.
*
* If @child is a floating reference (see g_variant_ref_sink()), the new
* instance takes ownership of @child.
*
* Returns: (transfer none): a floating reference to a new variant #GVariant instance
*
* Since: 2.24
**/
GVariant *
g_variant_new_variant (GVariant *value)
{
g_return_val_if_fail (value != NULL, NULL);
g_variant_ref_sink (value);
return g_variant_new_from_children (G_VARIANT_TYPE_VARIANT,
g_memdup (&value, sizeof value),
1, g_variant_is_trusted (value));
}
/**
* g_variant_get_variant:
* @value: a variant #GVariant instance
*
* Unboxes @value. The result is the #GVariant instance that was
* contained in @value.
*
* Returns: (transfer full): the item contained in the variant
*
* Since: 2.24
**/
GVariant *
g_variant_get_variant (GVariant *value)
{
TYPE_CHECK (value, G_VARIANT_TYPE_VARIANT, NULL);
return g_variant_get_child_value (value, 0);
}
/**
* g_variant_new_array:
* @child_type: (allow-none): the element type of the new array
* @children: (allow-none) (array length=n_children): an array of
* #GVariant pointers, the children
* @n_children: the length of @children
*
* Creates a new #GVariant array from @children.
*
* @child_type must be non-%NULL if @n_children is zero. Otherwise, the
* child type is determined by inspecting the first element of the
* @children array. If @child_type is non-%NULL then it must be a
* definite type.
*
* The items of the array are taken from the @children array. No entry
* in the @children array may be %NULL.
*
* All items in the array must have the same type, which must be the
* same as @child_type, if given.
*
* If the @children are floating references (see g_variant_ref_sink()), the
* new instance takes ownership of them as if via g_variant_ref_sink().
*
* Returns: (transfer none): a floating reference to a new #GVariant array
*
* Since: 2.24
**/
GVariant *
g_variant_new_array (const GVariantType *child_type,
GVariant * const *children,
gsize n_children)
{
GVariantType *array_type;
GVariant **my_children;
gboolean trusted;
GVariant *value;
gsize i;
g_return_val_if_fail (n_children > 0 || child_type != NULL, NULL);
g_return_val_if_fail (n_children == 0 || children != NULL, NULL);
g_return_val_if_fail (child_type == NULL ||
g_variant_type_is_definite (child_type), NULL);
my_children = g_new (GVariant *, n_children);
trusted = TRUE;
if (child_type == NULL)
child_type = g_variant_get_type (children[0]);
array_type = g_variant_type_new_array (child_type);
for (i = 0; i < n_children; i++)
{
TYPE_CHECK (children[i], child_type, NULL);
my_children[i] = g_variant_ref_sink (children[i]);
trusted &= g_variant_is_trusted (children[i]);
}
value = g_variant_new_from_children (array_type, my_children,
n_children, trusted);
g_variant_type_free (array_type);
return value;
}
/*< private >
* g_variant_make_tuple_type:
* @children: (array length=n_children): an array of GVariant *
* @n_children: the length of @children
*
* Return the type of a tuple containing @children as its items.
**/
static GVariantType *
g_variant_make_tuple_type (GVariant * const *children,
gsize n_children)
{
const GVariantType **types;
GVariantType *type;
gsize i;
types = g_new (const GVariantType *, n_children);
for (i = 0; i < n_children; i++)
types[i] = g_variant_get_type (children[i]);
type = g_variant_type_new_tuple (types, n_children);
g_free (types);
return type;
}
/**
* g_variant_new_tuple:
* @children: (array length=n_children): the items to make the tuple out of
* @n_children: the length of @children
*
* Creates a new tuple #GVariant out of the items in @children. The
* type is determined from the types of @children. No entry in the
* @children array may be %NULL.
*
* If @n_children is 0 then the unit tuple is constructed.
*
* If the @children are floating references (see g_variant_ref_sink()), the
* new instance takes ownership of them as if via g_variant_ref_sink().
*
* Returns: (transfer none): a floating reference to a new #GVariant tuple
*
* Since: 2.24
**/
GVariant *
g_variant_new_tuple (GVariant * const *children,
gsize n_children)
{
GVariantType *tuple_type;
GVariant **my_children;
gboolean trusted;
GVariant *value;
gsize i;
g_return_val_if_fail (n_children == 0 || children != NULL, NULL);
my_children = g_new (GVariant *, n_children);
trusted = TRUE;
for (i = 0; i < n_children; i++)
{
my_children[i] = g_variant_ref_sink (children[i]);
trusted &= g_variant_is_trusted (children[i]);
}
tuple_type = g_variant_make_tuple_type (children, n_children);
value = g_variant_new_from_children (tuple_type, my_children,
n_children, trusted);
g_variant_type_free (tuple_type);
return value;
}
/*< private >
* g_variant_make_dict_entry_type:
* @key: a #GVariant, the key
* @val: a #GVariant, the value
*
* Return the type of a dictionary entry containing @key and @val as its
* children.
**/
static GVariantType *
g_variant_make_dict_entry_type (GVariant *key,
GVariant *val)
{
return g_variant_type_new_dict_entry (g_variant_get_type (key),
g_variant_get_type (val));
}
/**
* g_variant_new_dict_entry: (constructor)
* @key: a basic #GVariant, the key
* @value: a #GVariant, the value
*
* Creates a new dictionary entry #GVariant. @key and @value must be
* non-%NULL. @key must be a value of a basic type (ie: not a container).
*
* If the @key or @value are floating references (see g_variant_ref_sink()),
* the new instance takes ownership of them as if via g_variant_ref_sink().
*
* Returns: (transfer none): a floating reference to a new dictionary entry #GVariant
*
* Since: 2.24
**/
GVariant *
g_variant_new_dict_entry (GVariant *key,
GVariant *value)
{
GVariantType *dict_type;
GVariant **children;
gboolean trusted;
g_return_val_if_fail (key != NULL && value != NULL, NULL);
g_return_val_if_fail (!g_variant_is_container (key), NULL);
children = g_new (GVariant *, 2);
children[0] = g_variant_ref_sink (key);
children[1] = g_variant_ref_sink (value);
trusted = g_variant_is_trusted (key) && g_variant_is_trusted (value);
dict_type = g_variant_make_dict_entry_type (key, value);
value = g_variant_new_from_children (dict_type, children, 2, trusted);
g_variant_type_free (dict_type);
return value;
}
/**
* g_variant_lookup: (skip)
* @dictionary: a dictionary #GVariant
* @key: the key to lookup in the dictionary
* @format_string: a GVariant format string
* @...: the arguments to unpack the value into
*
* Looks up a value in a dictionary #GVariant.
*
* This function is a wrapper around g_variant_lookup_value() and
* g_variant_get(). In the case that %NULL would have been returned,
* this function returns %FALSE. Otherwise, it unpacks the returned
* value and returns %TRUE.
*
* @format_string determines the C types that are used for unpacking
* the values and also determines if the values are copied or borrowed,
* see the section on
* GVariant Format Strings.
*
* Returns: %TRUE if a value was unpacked
*
* Since: 2.28
*/
gboolean
g_variant_lookup (GVariant *dictionary,
const gchar *key,
const gchar *format_string,
...)
{
GVariantType *type;
GVariant *value;
/* flatten */
g_variant_get_data (dictionary);
type = g_variant_format_string_scan_type (format_string, NULL, NULL);
value = g_variant_lookup_value (dictionary, key, type);
g_variant_type_free (type);
if (value)
{
va_list ap;
va_start (ap, format_string);
g_variant_get_va (value, format_string, NULL, &ap);
g_variant_unref (value);
va_end (ap);
return TRUE;
}
else
return FALSE;
}
/**
* g_variant_lookup_value:
* @dictionary: a dictionary #GVariant
* @key: the key to lookup in the dictionary
* @expected_type: (allow-none): a #GVariantType, or %NULL
*
* Looks up a value in a dictionary #GVariant.
*
* This function works with dictionaries of the type
* a{s*} (and equally well with type
* a{o*}, but we only further discuss the string case
* for sake of clarity).
*
* In the event that @dictionary has the type a{sv},
* the @expected_type string specifies what type of value is expected to
* be inside of the variant. If the value inside the variant has a
* different type then %NULL is returned. In the event that @dictionary
* has a value type other than v then @expected_type
* must directly match the key type and it is used to unpack the value
* directly or an error occurs.
*
* In either case, if @key is not found in @dictionary, %NULL is
* returned.
*
* If the key is found and the value has the correct type, it is
* returned. If @expected_type was specified then any non-%NULL return
* value will have this type.
*
* Returns: (transfer full): the value of the dictionary key, or %NULL
*
* Since: 2.28
*/
GVariant *
g_variant_lookup_value (GVariant *dictionary,
const gchar *key,
const GVariantType *expected_type)
{
GVariantIter iter;
GVariant *entry;
GVariant *value;
g_return_val_if_fail (g_variant_is_of_type (dictionary,
G_VARIANT_TYPE ("a{s*}")) ||
g_variant_is_of_type (dictionary,
G_VARIANT_TYPE ("a{o*}")),
NULL);
g_variant_iter_init (&iter, dictionary);
while ((entry = g_variant_iter_next_value (&iter)))
{
GVariant *entry_key;
gboolean matches;
entry_key = g_variant_get_child_value (entry, 0);
matches = strcmp (g_variant_get_string (entry_key, NULL), key) == 0;
g_variant_unref (entry_key);
if (matches)
break;
g_variant_unref (entry);
}
if (entry == NULL)
return NULL;
value = g_variant_get_child_value (entry, 1);
g_variant_unref (entry);
if (g_variant_is_of_type (value, G_VARIANT_TYPE_VARIANT))
{
GVariant *tmp;
tmp = g_variant_get_variant (value);
g_variant_unref (value);
if (expected_type && !g_variant_is_of_type (tmp, expected_type))
{
g_variant_unref (tmp);
tmp = NULL;
}
value = tmp;
}
g_return_val_if_fail (expected_type == NULL || value == NULL ||
g_variant_is_of_type (value, expected_type), NULL);
return value;
}
/**
* g_variant_get_fixed_array:
* @value: a #GVariant array with fixed-sized elements
* @n_elements: (out): a pointer to the location to store the number of items
* @element_size: the size of each element
*
* Provides access to the serialised data for an array of fixed-sized
* items.
*
* @value must be an array with fixed-sized elements. Numeric types are
* fixed-size, as are tuples containing only other fixed-sized types.
*
* @element_size must be the size of a single element in the array,
* as given by the section on
* Serialised Data
* Memory.
*
* In particular, arrays of these fixed-sized types can be interpreted
* as an array of the given C type, with @element_size set to
* sizeof
the appropriate type:
*
*
*
* element type C type
*
* %G_VARIANT_TYPE_INT16 (etc.)
* #gint16 (etc.)
* %G_VARIANT_TYPE_BOOLEAN
* #guchar (not #gboolean!)
* %G_VARIANT_TYPE_BYTE #guchar
* %G_VARIANT_TYPE_HANDLE #guint32
* %G_VARIANT_TYPE_DOUBLE #gdouble
*
*
*
*
* For example, if calling this function for an array of 32 bit integers,
* you might say sizeof (gint32)
. This value isn't used
* except for the purpose of a double-check that the form of the
* serialised data matches the caller's expectation.
*
* @n_elements, which must be non-%NULL is set equal to the number of
* items in the array.
*
* Returns: (array length=n_elements) (transfer none): a pointer to
* the fixed array
*
* Since: 2.24
**/
gconstpointer
g_variant_get_fixed_array (GVariant *value,
gsize *n_elements,
gsize element_size)
{
GVariantTypeInfo *array_info;
gsize array_element_size;
gconstpointer data;
gsize size;
TYPE_CHECK (value, G_VARIANT_TYPE_ARRAY, NULL);
g_return_val_if_fail (n_elements != NULL, NULL);
g_return_val_if_fail (element_size > 0, NULL);
array_info = g_variant_get_type_info (value);
g_variant_type_info_query_element (array_info, NULL, &array_element_size);
g_return_val_if_fail (array_element_size, NULL);
if G_UNLIKELY (array_element_size != element_size)
{
if (array_element_size)
g_critical ("g_variant_get_fixed_array: assertion "
"'g_variant_array_has_fixed_size (value, element_size)' "
"failed: array size %"G_GSIZE_FORMAT" does not match "
"given element_size %"G_GSIZE_FORMAT".",
array_element_size, element_size);
else
g_critical ("g_variant_get_fixed_array: assertion "
"'g_variant_array_has_fixed_size (value, element_size)' "
"failed: array does not have fixed size.");
}
data = g_variant_get_data (value);
size = g_variant_get_size (value);
if (size % element_size)
*n_elements = 0;
else
*n_elements = size / element_size;
if (*n_elements)
return data;
return NULL;
}
/**
* g_variant_new_fixed_array:
* @element_type: the #GVariantType of each element
* @elements: a pointer to the fixed array of contiguous elements
* @n_elements: the number of elements
* @element_size: the size of each element
*
* Provides access to the serialised data for an array of fixed-sized
* items.
*
* @value must be an array with fixed-sized elements. Numeric types are
* fixed-size as are tuples containing only other fixed-sized types.
*
* @element_size must be the size of a single element in the array. For
* example, if calling this function for an array of 32 bit integers,
* you might say sizeof (gint32)
. This value isn't used
* except for the purpose of a double-check that the form of the
* serialised data matches the caller's expectation.
*
* @n_elements, which must be non-%NULL is set equal to the number of
* items in the array.
*
* Returns: (transfer none): a floating reference to a new array #GVariant instance
*
* Since: 2.32
**/
GVariant *
g_variant_new_fixed_array (const GVariantType *element_type,
gconstpointer elements,
gsize n_elements,
gsize element_size)
{
GVariantType *array_type;
gsize array_element_size;
GVariantTypeInfo *array_info;
GVariant *value;
gpointer data;
g_return_val_if_fail (g_variant_type_is_definite (element_type), NULL);
g_return_val_if_fail (element_size > 0, NULL);
array_type = g_variant_type_new_array (element_type);
array_info = g_variant_type_info_get (array_type);
g_variant_type_info_query_element (array_info, NULL, &array_element_size);
if G_UNLIKELY (array_element_size != element_size)
{
if (array_element_size)
g_critical ("g_variant_new_fixed_array: array size %" G_GSIZE_FORMAT
" does not match given element_size %" G_GSIZE_FORMAT ".",
array_element_size, element_size);
else
g_critical ("g_variant_get_fixed_array: array does not have fixed size.");
return NULL;
}
data = g_memdup (elements, n_elements * element_size);
value = g_variant_new_from_data (array_type, data,
n_elements * element_size,
FALSE, g_free, data);
g_variant_type_free (array_type);
g_variant_type_info_unref (array_info);
return value;
}
/* String type constructor/getters/validation {{{1 */
/**
* g_variant_new_string:
* @string: a normal utf8 nul-terminated string
*
* Creates a string #GVariant with the contents of @string.
*
* @string must be valid utf8.
*
* Returns: (transfer none): a floating reference to a new string #GVariant instance
*
* Since: 2.24
**/
GVariant *
g_variant_new_string (const gchar *string)
{
g_return_val_if_fail (string != NULL, NULL);
g_return_val_if_fail (g_utf8_validate (string, -1, NULL), NULL);
return g_variant_new_from_trusted (G_VARIANT_TYPE_STRING,
string, strlen (string) + 1);
}
/**
* g_variant_new_take_string: (skip)
* @string: a normal utf8 nul-terminated string
*
* Creates a string #GVariant with the contents of @string.
*
* @string must be valid utf8.
*
* This function consumes @string. g_free() will be called on @string
* when it is no longer required.
*
* You must not modify or access @string in any other way after passing
* it to this function. It is even possible that @string is immediately
* freed.
*
* Returns: (transfer none): a floating reference to a new string
* #GVariant instance
*
* Since: 2.38
**/
GVariant *
g_variant_new_take_string (gchar *string)
{
GVariant *value;
GBytes *bytes;
g_return_val_if_fail (string != NULL, NULL);
g_return_val_if_fail (g_utf8_validate (string, -1, NULL), NULL);
bytes = g_bytes_new_take (string, strlen (string) + 1);
value = g_variant_new_from_bytes (G_VARIANT_TYPE_STRING, bytes, TRUE);
g_bytes_unref (bytes);
return value;
}
/**
* g_variant_new_printf: (skip)
* @format_string: a printf-style format string
* @...: arguments for @format_string
*
* Creates a string-type GVariant using printf formatting.
*
* This is similar to calling g_strdup_printf() and then
* g_variant_new_string() but it saves a temporary variable and an
* unnecessary copy.
*
* Returns: (transfer none): a floating reference to a new string
* #GVariant instance
*
* Since: 2.38
**/
GVariant *
g_variant_new_printf (const gchar *format_string,
...)
{
GVariant *value;
GBytes *bytes;
gchar *string;
va_list ap;
g_return_val_if_fail (format_string != NULL, NULL);
va_start (ap, format_string);
string = g_strdup_vprintf (format_string, ap);
va_end (ap);
bytes = g_bytes_new_take (string, strlen (string) + 1);
value = g_variant_new_from_bytes (G_VARIANT_TYPE_STRING, bytes, TRUE);
g_bytes_unref (bytes);
return value;
}
/**
* g_variant_new_object_path:
* @object_path: a normal C nul-terminated string
*
* Creates a D-Bus object path #GVariant with the contents of @string.
* @string must be a valid D-Bus object path. Use
* g_variant_is_object_path() if you're not sure.
*
* Returns: (transfer none): a floating reference to a new object path #GVariant instance
*
* Since: 2.24
**/
GVariant *
g_variant_new_object_path (const gchar *object_path)
{
g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
return g_variant_new_from_trusted (G_VARIANT_TYPE_OBJECT_PATH,
object_path, strlen (object_path) + 1);
}
/**
* g_variant_is_object_path:
* @string: a normal C nul-terminated string
*
* Determines if a given string is a valid D-Bus object path. You
* should ensure that a string is a valid D-Bus object path before
* passing it to g_variant_new_object_path().
*
* A valid object path starts with '/' followed by zero or more
* sequences of characters separated by '/' characters. Each sequence
* must contain only the characters "[A-Z][a-z][0-9]_". No sequence
* (including the one following the final '/' character) may be empty.
*
* Returns: %TRUE if @string is a D-Bus object path
*
* Since: 2.24
**/
gboolean
g_variant_is_object_path (const gchar *string)
{
g_return_val_if_fail (string != NULL, FALSE);
return g_variant_serialiser_is_object_path (string, strlen (string) + 1);
}
/**
* g_variant_new_signature:
* @signature: a normal C nul-terminated string
*
* Creates a D-Bus type signature #GVariant with the contents of
* @string. @string must be a valid D-Bus type signature. Use
* g_variant_is_signature() if you're not sure.
*
* Returns: (transfer none): a floating reference to a new signature #GVariant instance
*
* Since: 2.24
**/
GVariant *
g_variant_new_signature (const gchar *signature)
{
g_return_val_if_fail (g_variant_is_signature (signature), NULL);
return g_variant_new_from_trusted (G_VARIANT_TYPE_SIGNATURE,
signature, strlen (signature) + 1);
}
/**
* g_variant_is_signature:
* @string: a normal C nul-terminated string
*
* Determines if a given string is a valid D-Bus type signature. You
* should ensure that a string is a valid D-Bus type signature before
* passing it to g_variant_new_signature().
*
* D-Bus type signatures consist of zero or more definite #GVariantType
* strings in sequence.
*
* Returns: %TRUE if @string is a D-Bus type signature
*
* Since: 2.24
**/
gboolean
g_variant_is_signature (const gchar *string)
{
g_return_val_if_fail (string != NULL, FALSE);
return g_variant_serialiser_is_signature (string, strlen (string) + 1);
}
/**
* g_variant_get_string:
* @value: a string #GVariant instance
* @length: (allow-none) (default 0) (out): a pointer to a #gsize,
* to store the length
*
* Returns the string value of a #GVariant instance with a string
* type. This includes the types %G_VARIANT_TYPE_STRING,
* %G_VARIANT_TYPE_OBJECT_PATH and %G_VARIANT_TYPE_SIGNATURE.
*
* The string will always be utf8 encoded.
*
* If @length is non-%NULL then the length of the string (in bytes) is
* returned there. For trusted values, this information is already
* known. For untrusted values, a strlen() will be performed.
*
* It is an error to call this function with a @value of any type
* other than those three.
*
* The return value remains valid as long as @value exists.
*
* Returns: (transfer none): the constant string, utf8 encoded
*
* Since: 2.24
**/
const gchar *
g_variant_get_string (GVariant *value,
gsize *length)
{
gconstpointer data;
gsize size;
g_return_val_if_fail (value != NULL, NULL);
g_return_val_if_fail (
g_variant_is_of_type (value, G_VARIANT_TYPE_STRING) ||
g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH) ||
g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE), NULL);
data = g_variant_get_data (value);
size = g_variant_get_size (value);
if (!g_variant_is_trusted (value))
{
switch (g_variant_classify (value))
{
case G_VARIANT_CLASS_STRING:
if (g_variant_serialiser_is_string (data, size))
break;
data = "";
size = 1;
break;
case G_VARIANT_CLASS_OBJECT_PATH:
if (g_variant_serialiser_is_object_path (data, size))
break;
data = "/";
size = 2;
break;
case G_VARIANT_CLASS_SIGNATURE:
if (g_variant_serialiser_is_signature (data, size))
break;
data = "";
size = 1;
break;
default:
g_assert_not_reached ();
}
}
if (length)
*length = size - 1;
return data;
}
/**
* g_variant_dup_string:
* @value: a string #GVariant instance
* @length: (out): a pointer to a #gsize, to store the length
*
* Similar to g_variant_get_string() except that instead of returning
* a constant string, the string is duplicated.
*
* The string will always be utf8 encoded.
*
* The return value must be freed using g_free().
*
* Returns: (transfer full): a newly allocated string, utf8 encoded
*
* Since: 2.24
**/
gchar *
g_variant_dup_string (GVariant *value,
gsize *length)
{
return g_strdup (g_variant_get_string (value, length));
}
/**
* g_variant_new_strv:
* @strv: (array length=length) (element-type utf8): an array of strings
* @length: the length of @strv, or -1
*
* Constructs an array of strings #GVariant from the given array of
* strings.
*
* If @length is -1 then @strv is %NULL-terminated.
*
* Returns: (transfer none): a new floating #GVariant instance
*
* Since: 2.24
**/
GVariant *
g_variant_new_strv (const gchar * const *strv,
gssize length)
{
GVariant **strings;
gsize i;
g_return_val_if_fail (length == 0 || strv != NULL, NULL);
if (length < 0)
length = g_strv_length ((gchar **) strv);
strings = g_new (GVariant *, length);
for (i = 0; i < length; i++)
strings[i] = g_variant_ref_sink (g_variant_new_string (strv[i]));
return g_variant_new_from_children (G_VARIANT_TYPE_STRING_ARRAY,
strings, length, TRUE);
}
/**
* g_variant_get_strv:
* @value: an array of strings #GVariant
* @length: (out) (allow-none): the length of the result, or %NULL
*
* Gets the contents of an array of strings #GVariant. This call
* makes a shallow copy; the return result should be released with
* g_free(), but the individual strings must not be modified.
*
* If @length is non-%NULL then the number of elements in the result
* is stored there. In any case, the resulting array will be
* %NULL-terminated.
*
* For an empty array, @length will be set to 0 and a pointer to a
* %NULL pointer will be returned.
*
* Returns: (array length=length zero-terminated=1) (transfer container): an array of constant strings
*
* Since: 2.24
**/
const gchar **
g_variant_get_strv (GVariant *value,
gsize *length)
{
const gchar **strv;
gsize n;
gsize i;
TYPE_CHECK (value, G_VARIANT_TYPE_STRING_ARRAY, NULL);
g_variant_get_data (value);
n = g_variant_n_children (value);
strv = g_new (const gchar *, n + 1);
for (i = 0; i < n; i++)
{
GVariant *string;
string = g_variant_get_child_value (value, i);
strv[i] = g_variant_get_string (string, NULL);
g_variant_unref (string);
}
strv[i] = NULL;
if (length)
*length = n;
return strv;
}
/**
* g_variant_dup_strv:
* @value: an array of strings #GVariant
* @length: (out) (allow-none): the length of the result, or %NULL
*
* Gets the contents of an array of strings #GVariant. This call
* makes a deep copy; the return result should be released with
* g_strfreev().
*
* If @length is non-%NULL then the number of elements in the result
* is stored there. In any case, the resulting array will be
* %NULL-terminated.
*
* For an empty array, @length will be set to 0 and a pointer to a
* %NULL pointer will be returned.
*
* Returns: (array length=length zero-terminated=1) (transfer full): an array of strings
*
* Since: 2.24
**/
gchar **
g_variant_dup_strv (GVariant *value,
gsize *length)
{
gchar **strv;
gsize n;
gsize i;
TYPE_CHECK (value, G_VARIANT_TYPE_STRING_ARRAY, NULL);
n = g_variant_n_children (value);
strv = g_new (gchar *, n + 1);
for (i = 0; i < n; i++)
{
GVariant *string;
string = g_variant_get_child_value (value, i);
strv[i] = g_variant_dup_string (string, NULL);
g_variant_unref (string);
}
strv[i] = NULL;
if (length)
*length = n;
return strv;
}
/**
* g_variant_new_objv:
* @strv: (array length=length) (element-type utf8): an array of strings
* @length: the length of @strv, or -1
*
* Constructs an array of object paths #GVariant from the given array of
* strings.
*
* Each string must be a valid #GVariant object path; see
* g_variant_is_object_path().
*
* If @length is -1 then @strv is %NULL-terminated.
*
* Returns: (transfer none): a new floating #GVariant instance
*
* Since: 2.30
**/
GVariant *
g_variant_new_objv (const gchar * const *strv,
gssize length)
{
GVariant **strings;
gsize i;
g_return_val_if_fail (length == 0 || strv != NULL, NULL);
if (length < 0)
length = g_strv_length ((gchar **) strv);
strings = g_new (GVariant *, length);
for (i = 0; i < length; i++)
strings[i] = g_variant_ref_sink (g_variant_new_object_path (strv[i]));
return g_variant_new_from_children (G_VARIANT_TYPE_OBJECT_PATH_ARRAY,
strings, length, TRUE);
}
/**
* g_variant_get_objv:
* @value: an array of object paths #GVariant
* @length: (out) (allow-none): the length of the result, or %NULL
*
* Gets the contents of an array of object paths #GVariant. This call
* makes a shallow copy; the return result should be released with
* g_free(), but the individual strings must not be modified.
*
* If @length is non-%NULL then the number of elements in the result
* is stored there. In any case, the resulting array will be
* %NULL-terminated.
*
* For an empty array, @length will be set to 0 and a pointer to a
* %NULL pointer will be returned.
*
* Returns: (array length=length zero-terminated=1) (transfer container): an array of constant strings
*
* Since: 2.30
**/
const gchar **
g_variant_get_objv (GVariant *value,
gsize *length)
{
const gchar **strv;
gsize n;
gsize i;
TYPE_CHECK (value, G_VARIANT_TYPE_OBJECT_PATH_ARRAY, NULL);
g_variant_get_data (value);
n = g_variant_n_children (value);
strv = g_new (const gchar *, n + 1);
for (i = 0; i < n; i++)
{
GVariant *string;
string = g_variant_get_child_value (value, i);
strv[i] = g_variant_get_string (string, NULL);
g_variant_unref (string);
}
strv[i] = NULL;
if (length)
*length = n;
return strv;
}
/**
* g_variant_dup_objv:
* @value: an array of object paths #GVariant
* @length: (out) (allow-none): the length of the result, or %NULL
*
* Gets the contents of an array of object paths #GVariant. This call
* makes a deep copy; the return result should be released with
* g_strfreev().
*
* If @length is non-%NULL then the number of elements in the result
* is stored there. In any case, the resulting array will be
* %NULL-terminated.
*
* For an empty array, @length will be set to 0 and a pointer to a
* %NULL pointer will be returned.
*
* Returns: (array length=length zero-terminated=1) (transfer full): an array of strings
*
* Since: 2.30
**/
gchar **
g_variant_dup_objv (GVariant *value,
gsize *length)
{
gchar **strv;
gsize n;
gsize i;
TYPE_CHECK (value, G_VARIANT_TYPE_OBJECT_PATH_ARRAY, NULL);
n = g_variant_n_children (value);
strv = g_new (gchar *, n + 1);
for (i = 0; i < n; i++)
{
GVariant *string;
string = g_variant_get_child_value (value, i);
strv[i] = g_variant_dup_string (string, NULL);
g_variant_unref (string);
}
strv[i] = NULL;
if (length)
*length = n;
return strv;
}
/**
* g_variant_new_bytestring:
* @string: (array zero-terminated=1) (element-type guint8): a normal
* nul-terminated string in no particular encoding
*
* Creates an array-of-bytes #GVariant with the contents of @string.
* This function is just like g_variant_new_string() except that the
* string need not be valid utf8.
*
* The nul terminator character at the end of the string is stored in
* the array.
*
* Returns: (transfer none): a floating reference to a new bytestring #GVariant instance
*
* Since: 2.26
**/
GVariant *
g_variant_new_bytestring (const gchar *string)
{
g_return_val_if_fail (string != NULL, NULL);
return g_variant_new_from_trusted (G_VARIANT_TYPE_BYTESTRING,
string, strlen (string) + 1);
}
/**
* g_variant_get_bytestring:
* @value: an array-of-bytes #GVariant instance
*
* Returns the string value of a #GVariant instance with an
* array-of-bytes type. The string has no particular encoding.
*
* If the array does not end with a nul terminator character, the empty
* string is returned. For this reason, you can always trust that a
* non-%NULL nul-terminated string will be returned by this function.
*
* If the array contains a nul terminator character somewhere other than
* the last byte then the returned string is the string, up to the first
* such nul character.
*
* It is an error to call this function with a @value that is not an
* array of bytes.
*
* The return value remains valid as long as @value exists.
*
* Returns: (transfer none) (array zero-terminated=1) (element-type guint8):
* the constant string
*
* Since: 2.26
**/
const gchar *
g_variant_get_bytestring (GVariant *value)
{
const gchar *string;
gsize size;
TYPE_CHECK (value, G_VARIANT_TYPE_BYTESTRING, NULL);
/* Won't be NULL since this is an array type */
string = g_variant_get_data (value);
size = g_variant_get_size (value);
if (size && string[size - 1] == '\0')
return string;
else
return "";
}
/**
* g_variant_dup_bytestring:
* @value: an array-of-bytes #GVariant instance
* @length: (out) (allow-none) (default NULL): a pointer to a #gsize, to store
* the length (not including the nul terminator)
*
* Similar to g_variant_get_bytestring() except that instead of
* returning a constant string, the string is duplicated.
*
* The return value must be freed using g_free().
*
* Returns: (transfer full) (array zero-terminated=1 length=length) (element-type guint8):
* a newly allocated string
*
* Since: 2.26
**/
gchar *
g_variant_dup_bytestring (GVariant *value,
gsize *length)
{
const gchar *original = g_variant_get_bytestring (value);
gsize size;
/* don't crash in case get_bytestring() had an assert failure */
if (original == NULL)
return NULL;
size = strlen (original);
if (length)
*length = size;
return g_memdup (original, size + 1);
}
/**
* g_variant_new_bytestring_array:
* @strv: (array length=length): an array of strings
* @length: the length of @strv, or -1
*
* Constructs an array of bytestring #GVariant from the given array of
* strings.
*
* If @length is -1 then @strv is %NULL-terminated.
*
* Returns: (transfer none): a new floating #GVariant instance
*
* Since: 2.26
**/
GVariant *
g_variant_new_bytestring_array (const gchar * const *strv,
gssize length)
{
GVariant **strings;
gsize i;
g_return_val_if_fail (length == 0 || strv != NULL, NULL);
if (length < 0)
length = g_strv_length ((gchar **) strv);
strings = g_new (GVariant *, length);
for (i = 0; i < length; i++)
strings[i] = g_variant_ref_sink (g_variant_new_bytestring (strv[i]));
return g_variant_new_from_children (G_VARIANT_TYPE_BYTESTRING_ARRAY,
strings, length, TRUE);
}
/**
* g_variant_get_bytestring_array:
* @value: an array of array of bytes #GVariant ('aay')
* @length: (out) (allow-none): the length of the result, or %NULL
*
* Gets the contents of an array of array of bytes #GVariant. This call
* makes a shallow copy; the return result should be released with
* g_free(), but the individual strings must not be modified.
*
* If @length is non-%NULL then the number of elements in the result is
* stored there. In any case, the resulting array will be
* %NULL-terminated.
*
* For an empty array, @length will be set to 0 and a pointer to a
* %NULL pointer will be returned.
*
* Returns: (array length=length) (transfer container): an array of constant strings
*
* Since: 2.26
**/
const gchar **
g_variant_get_bytestring_array (GVariant *value,
gsize *length)
{
const gchar **strv;
gsize n;
gsize i;
TYPE_CHECK (value, G_VARIANT_TYPE_BYTESTRING_ARRAY, NULL);
g_variant_get_data (value);
n = g_variant_n_children (value);
strv = g_new (const gchar *, n + 1);
for (i = 0; i < n; i++)
{
GVariant *string;
string = g_variant_get_child_value (value, i);
strv[i] = g_variant_get_bytestring (string);
g_variant_unref (string);
}
strv[i] = NULL;
if (length)
*length = n;
return strv;
}
/**
* g_variant_dup_bytestring_array:
* @value: an array of array of bytes #GVariant ('aay')
* @length: (out) (allow-none): the length of the result, or %NULL
*
* Gets the contents of an array of array of bytes #GVariant. This call
* makes a deep copy; the return result should be released with
* g_strfreev().
*
* If @length is non-%NULL then the number of elements in the result is
* stored there. In any case, the resulting array will be
* %NULL-terminated.
*
* For an empty array, @length will be set to 0 and a pointer to a
* %NULL pointer will be returned.
*
* Returns: (array length=length) (transfer full): an array of strings
*
* Since: 2.26
**/
gchar **
g_variant_dup_bytestring_array (GVariant *value,
gsize *length)
{
gchar **strv;
gsize n;
gsize i;
TYPE_CHECK (value, G_VARIANT_TYPE_BYTESTRING_ARRAY, NULL);
g_variant_get_data (value);
n = g_variant_n_children (value);
strv = g_new (gchar *, n + 1);
for (i = 0; i < n; i++)
{
GVariant *string;
string = g_variant_get_child_value (value, i);
strv[i] = g_variant_dup_bytestring (string, NULL);
g_variant_unref (string);
}
strv[i] = NULL;
if (length)
*length = n;
return strv;
}
/* Type checking and querying {{{1 */
/**
* g_variant_get_type:
* @value: a #GVariant
*
* Determines the type of @value.
*
* The return value is valid for the lifetime of @value and must not
* be freed.
*
* Returns: a #GVariantType
*
* Since: 2.24
**/
const GVariantType *
g_variant_get_type (GVariant *value)
{
GVariantTypeInfo *type_info;
g_return_val_if_fail (value != NULL, NULL);
type_info = g_variant_get_type_info (value);
return (GVariantType *) g_variant_type_info_get_type_string (type_info);
}
/**
* g_variant_get_type_string:
* @value: a #GVariant
*
* Returns the type string of @value. Unlike the result of calling
* g_variant_type_peek_string(), this string is nul-terminated. This
* string belongs to #GVariant and must not be freed.
*
* Returns: the type string for the type of @value
*
* Since: 2.24
**/
const gchar *
g_variant_get_type_string (GVariant *value)
{
GVariantTypeInfo *type_info;
g_return_val_if_fail (value != NULL, NULL);
type_info = g_variant_get_type_info (value);
return g_variant_type_info_get_type_string (type_info);
}
/**
* g_variant_is_of_type:
* @value: a #GVariant instance
* @type: a #GVariantType
*
* Checks if a value has a type matching the provided type.
*
* Returns: %TRUE if the type of @value matches @type
*
* Since: 2.24
**/
gboolean
g_variant_is_of_type (GVariant *value,
const GVariantType *type)
{
return g_variant_type_is_subtype_of (g_variant_get_type (value), type);
}
/**
* g_variant_is_container:
* @value: a #GVariant instance
*
* Checks if @value is a container.
*
* Returns: %TRUE if @value is a container
*
* Since: 2.24
*/
gboolean
g_variant_is_container (GVariant *value)
{
return g_variant_type_is_container (g_variant_get_type (value));
}
/**
* g_variant_classify:
* @value: a #GVariant
*
* Classifies @value according to its top-level type.
*
* Returns: the #GVariantClass of @value
*
* Since: 2.24
**/
/**
* GVariantClass:
* @G_VARIANT_CLASS_BOOLEAN: The #GVariant is a boolean.
* @G_VARIANT_CLASS_BYTE: The #GVariant is a byte.
* @G_VARIANT_CLASS_INT16: The #GVariant is a signed 16 bit integer.
* @G_VARIANT_CLASS_UINT16: The #GVariant is an unsigned 16 bit integer.
* @G_VARIANT_CLASS_INT32: The #GVariant is a signed 32 bit integer.
* @G_VARIANT_CLASS_UINT32: The #GVariant is an unsigned 32 bit integer.
* @G_VARIANT_CLASS_INT64: The #GVariant is a signed 64 bit integer.
* @G_VARIANT_CLASS_UINT64: The #GVariant is an unsigned 64 bit integer.
* @G_VARIANT_CLASS_HANDLE: The #GVariant is a file handle index.
* @G_VARIANT_CLASS_DOUBLE: The #GVariant is a double precision floating
* point value.
* @G_VARIANT_CLASS_STRING: The #GVariant is a normal string.
* @G_VARIANT_CLASS_OBJECT_PATH: The #GVariant is a D-Bus object path
* string.
* @G_VARIANT_CLASS_SIGNATURE: The #GVariant is a D-Bus signature string.
* @G_VARIANT_CLASS_VARIANT: The #GVariant is a variant.
* @G_VARIANT_CLASS_MAYBE: The #GVariant is a maybe-typed value.
* @G_VARIANT_CLASS_ARRAY: The #GVariant is an array.
* @G_VARIANT_CLASS_TUPLE: The #GVariant is a tuple.
* @G_VARIANT_CLASS_DICT_ENTRY: The #GVariant is a dictionary entry.
*
* The range of possible top-level types of #GVariant instances.
*
* Since: 2.24
**/
GVariantClass
g_variant_classify (GVariant *value)
{
g_return_val_if_fail (value != NULL, 0);
return *g_variant_get_type_string (value);
}
/* Pretty printer {{{1 */
/* This function is not introspectable because if @string is NULL,
@returns is (transfer full), otherwise it is (transfer none), which
is not supported by GObjectIntrospection */
/**
* g_variant_print_string: (skip)
* @value: a #GVariant
* @string: (allow-none) (default NULL): a #GString, or %NULL
* @type_annotate: %TRUE if type information should be included in
* the output
*
* Behaves as g_variant_print(), but operates on a #GString.
*
* If @string is non-%NULL then it is appended to and returned. Else,
* a new empty #GString is allocated and it is returned.
*
* Returns: a #GString containing the string
*
* Since: 2.24
**/
GString *
g_variant_print_string (GVariant *value,
GString *string,
gboolean type_annotate)
{
if G_UNLIKELY (string == NULL)
string = g_string_new (NULL);
switch (g_variant_classify (value))
{
case G_VARIANT_CLASS_MAYBE:
if (type_annotate)
g_string_append_printf (string, "@%s ",
g_variant_get_type_string (value));
if (g_variant_n_children (value))
{
gchar *printed_child;
GVariant *element;
/* Nested maybes:
*
* Consider the case of the type "mmi". In this case we could
* write "just just 4", but "4" alone is totally unambiguous,
* so we try to drop "just" where possible.
*
* We have to be careful not to always drop "just", though,
* since "nothing" needs to be distinguishable from "just
* nothing". The case where we need to ensure we keep the
* "just" is actually exactly the case where we have a nested
* Nothing.
*
* Instead of searching for that nested Nothing, we just print
* the contained value into a separate string and see if we
* end up with "nothing" at the end of it. If so, we need to
* add "just" at our level.
*/
element = g_variant_get_child_value (value, 0);
printed_child = g_variant_print (element, FALSE);
g_variant_unref (element);
if (g_str_has_suffix (printed_child, "nothing"))
g_string_append (string, "just ");
g_string_append (string, printed_child);
g_free (printed_child);
}
else
g_string_append (string, "nothing");
break;
case G_VARIANT_CLASS_ARRAY:
/* it's an array so the first character of the type string is 'a'
*
* if the first two characters are 'ay' then it's a bytestring.
* under certain conditions we print those as strings.
*/
if (g_variant_get_type_string (value)[1] == 'y')
{
const gchar *str;
gsize size;
gsize i;
/* first determine if it is a byte string.
* that's when there's a single nul character: at the end.
*/
str = g_variant_get_data (value);
size = g_variant_get_size (value);
for (i = 0; i < size; i++)
if (str[i] == '\0')
break;
/* first nul byte is the last byte -> it's a byte string. */
if (i == size - 1)
{
gchar *escaped = g_strescape (str, NULL);
/* use double quotes only if a ' is in the string */
if (strchr (str, '\''))
g_string_append_printf (string, "b\"%s\"", escaped);
else
g_string_append_printf (string, "b'%s'", escaped);
g_free (escaped);
break;
}
else
/* fall through and handle normally... */;
}
/*
* if the first two characters are 'a{' then it's an array of
* dictionary entries (ie: a dictionary) so we print that
* differently.
*/
if (g_variant_get_type_string (value)[1] == '{')
/* dictionary */
{
const gchar *comma = "";
gsize n, i;
if ((n = g_variant_n_children (value)) == 0)
{
if (type_annotate)
g_string_append_printf (string, "@%s ",
g_variant_get_type_string (value));
g_string_append (string, "{}");
break;
}
g_string_append_c (string, '{');
for (i = 0; i < n; i++)
{
GVariant *entry, *key, *val;
g_string_append (string, comma);
comma = ", ";
entry = g_variant_get_child_value (value, i);
key = g_variant_get_child_value (entry, 0);
val = g_variant_get_child_value (entry, 1);
g_variant_unref (entry);
g_variant_print_string (key, string, type_annotate);
g_variant_unref (key);
g_string_append (string, ": ");
g_variant_print_string (val, string, type_annotate);
g_variant_unref (val);
type_annotate = FALSE;
}
g_string_append_c (string, '}');
}
else
/* normal (non-dictionary) array */
{
const gchar *comma = "";
gsize n, i;
if ((n = g_variant_n_children (value)) == 0)
{
if (type_annotate)
g_string_append_printf (string, "@%s ",
g_variant_get_type_string (value));
g_string_append (string, "[]");
break;
}
g_string_append_c (string, '[');
for (i = 0; i < n; i++)
{
GVariant *element;
g_string_append (string, comma);
comma = ", ";
element = g_variant_get_child_value (value, i);
g_variant_print_string (element, string, type_annotate);
g_variant_unref (element);
type_annotate = FALSE;
}
g_string_append_c (string, ']');
}
break;
case G_VARIANT_CLASS_TUPLE:
{
gsize n, i;
n = g_variant_n_children (value);
g_string_append_c (string, '(');
for (i = 0; i < n; i++)
{
GVariant *element;
element = g_variant_get_child_value (value, i);
g_variant_print_string (element, string, type_annotate);
g_string_append (string, ", ");
g_variant_unref (element);
}
/* for >1 item: remove final ", "
* for 1 item: remove final " ", but leave the ","
* for 0 items: there is only "(", so remove nothing
*/
g_string_truncate (string, string->len - (n > 0) - (n > 1));
g_string_append_c (string, ')');
}
break;
case G_VARIANT_CLASS_DICT_ENTRY:
{
GVariant *element;
g_string_append_c (string, '{');
element = g_variant_get_child_value (value, 0);
g_variant_print_string (element, string, type_annotate);
g_variant_unref (element);
g_string_append (string, ", ");
element = g_variant_get_child_value (value, 1);
g_variant_print_string (element, string, type_annotate);
g_variant_unref (element);
g_string_append_c (string, '}');
}
break;
case G_VARIANT_CLASS_VARIANT:
{
GVariant *child = g_variant_get_variant (value);
/* Always annotate types in nested variants, because they are
* (by nature) of variable type.
*/
g_string_append_c (string, '<');
g_variant_print_string (child, string, TRUE);
g_string_append_c (string, '>');
g_variant_unref (child);
}
break;
case G_VARIANT_CLASS_BOOLEAN:
if (g_variant_get_boolean (value))
g_string_append (string, "true");
else
g_string_append (string, "false");
break;
case G_VARIANT_CLASS_STRING:
{
const gchar *str = g_variant_get_string (value, NULL);
gunichar quote = strchr (str, '\'') ? '"' : '\'';
g_string_append_c (string, quote);
while (*str)
{
gunichar c = g_utf8_get_char (str);
if (c == quote || c == '\\')
g_string_append_c (string, '\\');
if (g_unichar_isprint (c))
g_string_append_unichar (string, c);
else
{
g_string_append_c (string, '\\');
if (c < 0x10000)
switch (c)
{
case '\a':
g_string_append_c (string, 'a');
break;
case '\b':
g_string_append_c (string, 'b');
break;
case '\f':
g_string_append_c (string, 'f');
break;
case '\n':
g_string_append_c (string, 'n');
break;
case '\r':
g_string_append_c (string, 'r');
break;
case '\t':
g_string_append_c (string, 't');
break;
case '\v':
g_string_append_c (string, 'v');
break;
default:
g_string_append_printf (string, "u%04x", c);
break;
}
else
g_string_append_printf (string, "U%08x", c);
}
str = g_utf8_next_char (str);
}
g_string_append_c (string, quote);
}
break;
case G_VARIANT_CLASS_BYTE:
if (type_annotate)
g_string_append (string, "byte ");
g_string_append_printf (string, "0x%02x",
g_variant_get_byte (value));
break;
case G_VARIANT_CLASS_INT16:
if (type_annotate)
g_string_append (string, "int16 ");
g_string_append_printf (string, "%"G_GINT16_FORMAT,
g_variant_get_int16 (value));
break;
case G_VARIANT_CLASS_UINT16:
if (type_annotate)
g_string_append (string, "uint16 ");
g_string_append_printf (string, "%"G_GUINT16_FORMAT,
g_variant_get_uint16 (value));
break;
case G_VARIANT_CLASS_INT32:
/* Never annotate this type because it is the default for numbers
* (and this is a *pretty* printer)
*/
g_string_append_printf (string, "%"G_GINT32_FORMAT,
g_variant_get_int32 (value));
break;
case G_VARIANT_CLASS_HANDLE:
if (type_annotate)
g_string_append (string, "handle ");
g_string_append_printf (string, "%"G_GINT32_FORMAT,
g_variant_get_handle (value));
break;
case G_VARIANT_CLASS_UINT32:
if (type_annotate)
g_string_append (string, "uint32 ");
g_string_append_printf (string, "%"G_GUINT32_FORMAT,
g_variant_get_uint32 (value));
break;
case G_VARIANT_CLASS_INT64:
if (type_annotate)
g_string_append (string, "int64 ");
g_string_append_printf (string, "%"G_GINT64_FORMAT,
g_variant_get_int64 (value));
break;
case G_VARIANT_CLASS_UINT64:
if (type_annotate)
g_string_append (string, "uint64 ");
g_string_append_printf (string, "%"G_GUINT64_FORMAT,
g_variant_get_uint64 (value));
break;
case G_VARIANT_CLASS_DOUBLE:
{
gchar buffer[100];
gint i;
g_ascii_dtostr (buffer, sizeof buffer, g_variant_get_double (value));
for (i = 0; buffer[i]; i++)
if (buffer[i] == '.' || buffer[i] == 'e' ||
buffer[i] == 'n' || buffer[i] == 'N')
break;
/* if there is no '.' or 'e' in the float then add one */
if (buffer[i] == '\0')
{
buffer[i++] = '.';
buffer[i++] = '0';
buffer[i++] = '\0';
}
g_string_append (string, buffer);
}
break;
case G_VARIANT_CLASS_OBJECT_PATH:
if (type_annotate)
g_string_append (string, "objectpath ");
g_string_append_printf (string, "\'%s\'",
g_variant_get_string (value, NULL));
break;
case G_VARIANT_CLASS_SIGNATURE:
if (type_annotate)
g_string_append (string, "signature ");
g_string_append_printf (string, "\'%s\'",
g_variant_get_string (value, NULL));
break;
default:
g_assert_not_reached ();
}
return string;
}
/**
* g_variant_print:
* @value: a #GVariant
* @type_annotate: %TRUE if type information should be included in
* the output
*
* Pretty-prints @value in the format understood by g_variant_parse().
*
* The format is described here.
*
* If @type_annotate is %TRUE, then type information is included in
* the output.
*
* Returns: (transfer full): a newly-allocated string holding the result.
*
* Since: 2.24
*/
gchar *
g_variant_print (GVariant *value,
gboolean type_annotate)
{
return g_string_free (g_variant_print_string (value, NULL, type_annotate),
FALSE);
};
/* Hash, Equal, Compare {{{1 */
/**
* g_variant_hash:
* @value: (type GVariant): a basic #GVariant value as a #gconstpointer
*
* Generates a hash value for a #GVariant instance.
*
* The output of this function is guaranteed to be the same for a given
* value only per-process. It may change between different processor
* architectures or even different versions of GLib. Do not use this
* function as a basis for building protocols or file formats.
*
* The type of @value is #gconstpointer only to allow use of this
* function with #GHashTable. @value must be a #GVariant.
*
* Returns: a hash value corresponding to @value
*
* Since: 2.24
**/
guint
g_variant_hash (gconstpointer value_)
{
GVariant *value = (GVariant *) value_;
switch (g_variant_classify (value))
{
case G_VARIANT_CLASS_STRING:
case G_VARIANT_CLASS_OBJECT_PATH:
case G_VARIANT_CLASS_SIGNATURE:
return g_str_hash (g_variant_get_string (value, NULL));
case G_VARIANT_CLASS_BOOLEAN:
/* this is a very odd thing to hash... */
return g_variant_get_boolean (value);
case G_VARIANT_CLASS_BYTE:
return g_variant_get_byte (value);
case G_VARIANT_CLASS_INT16:
case G_VARIANT_CLASS_UINT16:
{
const guint16 *ptr;
ptr = g_variant_get_data (value);
if (ptr)
return *ptr;
else
return 0;
}
case G_VARIANT_CLASS_INT32:
case G_VARIANT_CLASS_UINT32:
case G_VARIANT_CLASS_HANDLE:
{
const guint *ptr;
ptr = g_variant_get_data (value);
if (ptr)
return *ptr;
else
return 0;
}
case G_VARIANT_CLASS_INT64:
case G_VARIANT_CLASS_UINT64:
case G_VARIANT_CLASS_DOUBLE:
/* need a separate case for these guys because otherwise
* performance could be quite bad on big endian systems
*/
{
const guint *ptr;
ptr = g_variant_get_data (value);
if (ptr)
return ptr[0] + ptr[1];
else
return 0;
}
default:
g_return_val_if_fail (!g_variant_is_container (value), 0);
g_assert_not_reached ();
}
}
/**
* g_variant_equal:
* @one: (type GVariant): a #GVariant instance
* @two: (type GVariant): a #GVariant instance
*
* Checks if @one and @two have the same type and value.
*
* The types of @one and @two are #gconstpointer only to allow use of
* this function with #GHashTable. They must each be a #GVariant.
*
* Returns: %TRUE if @one and @two are equal
*
* Since: 2.24
**/
gboolean
g_variant_equal (gconstpointer one,
gconstpointer two)
{
gboolean equal;
g_return_val_if_fail (one != NULL && two != NULL, FALSE);
if (g_variant_get_type_info ((GVariant *) one) !=
g_variant_get_type_info ((GVariant *) two))
return FALSE;
/* if both values are trusted to be in their canonical serialised form
* then a simple memcmp() of their serialised data will answer the
* question.
*
* if not, then this might generate a false negative (since it is
* possible for two different byte sequences to represent the same
* value). for now we solve this by pretty-printing both values and
* comparing the result.
*/
if (g_variant_is_trusted ((GVariant *) one) &&
g_variant_is_trusted ((GVariant *) two))
{
gconstpointer data_one, data_two;
gsize size_one, size_two;
size_one = g_variant_get_size ((GVariant *) one);
size_two = g_variant_get_size ((GVariant *) two);
if (size_one != size_two)
return FALSE;
data_one = g_variant_get_data ((GVariant *) one);
data_two = g_variant_get_data ((GVariant *) two);
equal = memcmp (data_one, data_two, size_one) == 0;
}
else
{
gchar *strone, *strtwo;
strone = g_variant_print ((GVariant *) one, FALSE);
strtwo = g_variant_print ((GVariant *) two, FALSE);
equal = strcmp (strone, strtwo) == 0;
g_free (strone);
g_free (strtwo);
}
return equal;
}
/**
* g_variant_compare:
* @one: (type GVariant): a basic-typed #GVariant instance
* @two: (type GVariant): a #GVariant instance of the same type
*
* Compares @one and @two.
*
* The types of @one and @two are #gconstpointer only to allow use of
* this function with #GTree, #GPtrArray, etc. They must each be a
* #GVariant.
*
* Comparison is only defined for basic types (ie: booleans, numbers,
* strings). For booleans, %FALSE is less than %TRUE. Numbers are
* ordered in the usual way. Strings are in ASCII lexographical order.
*
* It is a programmer error to attempt to compare container values or
* two values that have types that are not exactly equal. For example,
* you cannot compare a 32-bit signed integer with a 32-bit unsigned
* integer. Also note that this function is not particularly
* well-behaved when it comes to comparison of doubles; in particular,
* the handling of incomparable values (ie: NaN) is undefined.
*
* If you only require an equality comparison, g_variant_equal() is more
* general.
*
* Returns: negative value if a < b;
* zero if a = b;
* positive value if a > b.
*
* Since: 2.26
**/
gint
g_variant_compare (gconstpointer one,
gconstpointer two)
{
GVariant *a = (GVariant *) one;
GVariant *b = (GVariant *) two;
g_return_val_if_fail (g_variant_classify (a) == g_variant_classify (b), 0);
switch (g_variant_classify (a))
{
case G_VARIANT_CLASS_BOOLEAN:
return g_variant_get_boolean (a) -
g_variant_get_boolean (b);
case G_VARIANT_CLASS_BYTE:
return ((gint) g_variant_get_byte (a)) -
((gint) g_variant_get_byte (b));
case G_VARIANT_CLASS_INT16:
return ((gint) g_variant_get_int16 (a)) -
((gint) g_variant_get_int16 (b));
case G_VARIANT_CLASS_UINT16:
return ((gint) g_variant_get_uint16 (a)) -
((gint) g_variant_get_uint16 (b));
case G_VARIANT_CLASS_INT32:
{
gint32 a_val = g_variant_get_int32 (a);
gint32 b_val = g_variant_get_int32 (b);
return (a_val == b_val) ? 0 : (a_val > b_val) ? 1 : -1;
}
case G_VARIANT_CLASS_UINT32:
{
guint32 a_val = g_variant_get_uint32 (a);
guint32 b_val = g_variant_get_uint32 (b);
return (a_val == b_val) ? 0 : (a_val > b_val) ? 1 : -1;
}
case G_VARIANT_CLASS_INT64:
{
gint64 a_val = g_variant_get_int64 (a);
gint64 b_val = g_variant_get_int64 (b);
return (a_val == b_val) ? 0 : (a_val > b_val) ? 1 : -1;
}
case G_VARIANT_CLASS_UINT64:
{
guint64 a_val = g_variant_get_uint64 (a);
guint64 b_val = g_variant_get_uint64 (b);
return (a_val == b_val) ? 0 : (a_val > b_val) ? 1 : -1;
}
case G_VARIANT_CLASS_DOUBLE:
{
gdouble a_val = g_variant_get_double (a);
gdouble b_val = g_variant_get_double (b);
return (a_val == b_val) ? 0 : (a_val > b_val) ? 1 : -1;
}
case G_VARIANT_CLASS_STRING:
case G_VARIANT_CLASS_OBJECT_PATH:
case G_VARIANT_CLASS_SIGNATURE:
return strcmp (g_variant_get_string (a, NULL),
g_variant_get_string (b, NULL));
default:
g_return_val_if_fail (!g_variant_is_container (a), 0);
g_assert_not_reached ();
}
}
/* GVariantIter {{{1 */
/**
* GVariantIter: (skip)
*
* #GVariantIter is an opaque data structure and can only be accessed
* using the following functions.
**/
struct stack_iter
{
GVariant *value;
gssize n, i;
const gchar *loop_format;
gsize padding[3];
gsize magic;
};
G_STATIC_ASSERT (sizeof (struct stack_iter) <= sizeof (GVariantIter));
struct heap_iter
{
struct stack_iter iter;
GVariant *value_ref;
gsize magic;
};
#define GVSI(i) ((struct stack_iter *) (i))
#define GVHI(i) ((struct heap_iter *) (i))
#define GVSI_MAGIC ((gsize) 3579507750u)
#define GVHI_MAGIC ((gsize) 1450270775u)
#define is_valid_iter(i) (i != NULL && \
GVSI(i)->magic == GVSI_MAGIC)
#define is_valid_heap_iter(i) (GVHI(i)->magic == GVHI_MAGIC && \
is_valid_iter(i))
/**
* g_variant_iter_new:
* @value: a container #GVariant
*
* Creates a heap-allocated #GVariantIter for iterating over the items
* in @value.
*
* Use g_variant_iter_free() to free the return value when you no longer
* need it.
*
* A reference is taken to @value and will be released only when
* g_variant_iter_free() is called.
*
* Returns: (transfer full): a new heap-allocated #GVariantIter
*
* Since: 2.24
**/
GVariantIter *
g_variant_iter_new (GVariant *value)
{
GVariantIter *iter;
iter = (GVariantIter *) g_slice_new (struct heap_iter);
GVHI(iter)->value_ref = g_variant_ref (value);
GVHI(iter)->magic = GVHI_MAGIC;
g_variant_iter_init (iter, value);
return iter;
}
/**
* g_variant_iter_init: (skip)
* @iter: a pointer to a #GVariantIter
* @value: a container #GVariant
*
* Initialises (without allocating) a #GVariantIter. @iter may be
* completely uninitialised prior to this call; its old value is
* ignored.
*
* The iterator remains valid for as long as @value exists, and need not
* be freed in any way.
*
* Returns: the number of items in @value
*
* Since: 2.24
**/
gsize
g_variant_iter_init (GVariantIter *iter,
GVariant *value)
{
GVSI(iter)->magic = GVSI_MAGIC;
GVSI(iter)->value = value;
GVSI(iter)->n = g_variant_n_children (value);
GVSI(iter)->i = -1;
GVSI(iter)->loop_format = NULL;
return GVSI(iter)->n;
}
/**
* g_variant_iter_copy:
* @iter: a #GVariantIter
*
* Creates a new heap-allocated #GVariantIter to iterate over the
* container that was being iterated over by @iter. Iteration begins on
* the new iterator from the current position of the old iterator but
* the two copies are independent past that point.
*
* Use g_variant_iter_free() to free the return value when you no longer
* need it.
*
* A reference is taken to the container that @iter is iterating over
* and will be releated only when g_variant_iter_free() is called.
*
* Returns: (transfer full): a new heap-allocated #GVariantIter
*
* Since: 2.24
**/
GVariantIter *
g_variant_iter_copy (GVariantIter *iter)
{
GVariantIter *copy;
g_return_val_if_fail (is_valid_iter (iter), 0);
copy = g_variant_iter_new (GVSI(iter)->value);
GVSI(copy)->i = GVSI(iter)->i;
return copy;
}
/**
* g_variant_iter_n_children:
* @iter: a #GVariantIter
*
* Queries the number of child items in the container that we are
* iterating over. This is the total number of items -- not the number
* of items remaining.
*
* This function might be useful for preallocation of arrays.
*
* Returns: the number of children in the container
*
* Since: 2.24
**/
gsize
g_variant_iter_n_children (GVariantIter *iter)
{
g_return_val_if_fail (is_valid_iter (iter), 0);
return GVSI(iter)->n;
}
/**
* g_variant_iter_free:
* @iter: (transfer full): a heap-allocated #GVariantIter
*
* Frees a heap-allocated #GVariantIter. Only call this function on
* iterators that were returned by g_variant_iter_new() or
* g_variant_iter_copy().
*
* Since: 2.24
**/
void
g_variant_iter_free (GVariantIter *iter)
{
g_return_if_fail (is_valid_heap_iter (iter));
g_variant_unref (GVHI(iter)->value_ref);
GVHI(iter)->magic = 0;
g_slice_free (struct heap_iter, GVHI(iter));
}
/**
* g_variant_iter_next_value:
* @iter: a #GVariantIter
*
* Gets the next item in the container. If no more items remain then
* %NULL is returned.
*
* Use g_variant_unref() to drop your reference on the return value when
* you no longer need it.
*
*
* Iterating with g_variant_iter_next_value()
*
* /* recursively iterate a container */
* void
* iterate_container_recursive (GVariant *container)
* {
* GVariantIter iter;
* GVariant *child;
*
* g_variant_iter_init (&iter, container);
* while ((child = g_variant_iter_next_value (&iter)))
* {
* g_print ("type '%s'\n", g_variant_get_type_string (child));
*
* if (g_variant_is_container (child))
* iterate_container_recursive (child);
*
* g_variant_unref (child);
* }
* }
*
*
*
* Returns: (allow-none) (transfer full): a #GVariant, or %NULL
*
* Since: 2.24
**/
GVariant *
g_variant_iter_next_value (GVariantIter *iter)
{
g_return_val_if_fail (is_valid_iter (iter), FALSE);
if G_UNLIKELY (GVSI(iter)->i >= GVSI(iter)->n)
{
g_critical ("g_variant_iter_next_value: must not be called again "
"after NULL has already been returned.");
return NULL;
}
GVSI(iter)->i++;
if (GVSI(iter)->i < GVSI(iter)->n)
return g_variant_get_child_value (GVSI(iter)->value, GVSI(iter)->i);
return NULL;
}
/* GVariantBuilder {{{1 */
/**
* GVariantBuilder:
*
* A utility type for constructing container-type #GVariant instances.
*
* This is an opaque structure and may only be accessed using the
* following functions.
*
* #GVariantBuilder is not threadsafe in any way. Do not attempt to
* access it from more than one thread.
**/
struct stack_builder
{
GVariantBuilder *parent;
GVariantType *type;
/* type constraint explicitly specified by 'type'.
* for tuple types, this moves along as we add more items.
*/
const GVariantType *expected_type;
/* type constraint implied by previous array item.
*/
const GVariantType *prev_item_type;
/* constraints on the number of children. max = -1 for unlimited. */
gsize min_items;
gsize max_items;
/* dynamically-growing pointer array */
GVariant **children;
gsize allocated_children;
gsize offset;
/* set to '1' if all items in the container will have the same type
* (ie: maybe, array, variant) '0' if not (ie: tuple, dict entry)
*/
guint uniform_item_types : 1;
/* set to '1' initially and changed to '0' if an untrusted value is
* added
*/
guint trusted : 1;
gsize magic;
};
G_STATIC_ASSERT (sizeof (struct stack_builder) <= sizeof (GVariantBuilder));
struct heap_builder
{
GVariantBuilder builder;
gsize magic;
gint ref_count;
};
#define GVSB(b) ((struct stack_builder *) (b))
#define GVHB(b) ((struct heap_builder *) (b))
#define GVSB_MAGIC ((gsize) 1033660112u)
#define GVHB_MAGIC ((gsize) 3087242682u)
#define is_valid_builder(b) (b != NULL && \
GVSB(b)->magic == GVSB_MAGIC)
#define is_valid_heap_builder(b) (GVHB(b)->magic == GVHB_MAGIC)
/**
* g_variant_builder_new:
* @type: a container type
*
* Allocates and initialises a new #GVariantBuilder.
*
* You should call g_variant_builder_unref() on the return value when it
* is no longer needed. The memory will not be automatically freed by
* any other call.
*
* In most cases it is easier to place a #GVariantBuilder directly on
* the stack of the calling function and initialise it with
* g_variant_builder_init().
*
* Returns: (transfer full): a #GVariantBuilder
*
* Since: 2.24
**/
GVariantBuilder *
g_variant_builder_new (const GVariantType *type)
{
GVariantBuilder *builder;
builder = (GVariantBuilder *) g_slice_new (struct heap_builder);
g_variant_builder_init (builder, type);
GVHB(builder)->magic = GVHB_MAGIC;
GVHB(builder)->ref_count = 1;
return builder;
}
/**
* g_variant_builder_unref:
* @builder: (transfer full): a #GVariantBuilder allocated by g_variant_builder_new()
*
* Decreases the reference count on @builder.
*
* In the event that there are no more references, releases all memory
* associated with the #GVariantBuilder.
*
* Don't call this on stack-allocated #GVariantBuilder instances or bad
* things will happen.
*
* Since: 2.24
**/
void
g_variant_builder_unref (GVariantBuilder *builder)
{
g_return_if_fail (is_valid_heap_builder (builder));
if (--GVHB(builder)->ref_count)
return;
g_variant_builder_clear (builder);
GVHB(builder)->magic = 0;
g_slice_free (struct heap_builder, GVHB(builder));
}
/**
* g_variant_builder_ref:
* @builder: a #GVariantBuilder allocated by g_variant_builder_new()
*
* Increases the reference count on @builder.
*
* Don't call this on stack-allocated #GVariantBuilder instances or bad
* things will happen.
*
* Returns: (transfer full): a new reference to @builder
*
* Since: 2.24
**/
GVariantBuilder *
g_variant_builder_ref (GVariantBuilder *builder)
{
g_return_val_if_fail (is_valid_heap_builder (builder), NULL);
GVHB(builder)->ref_count++;
return builder;
}
/**
* g_variant_builder_clear: (skip)
* @builder: a #GVariantBuilder
*
* Releases all memory associated with a #GVariantBuilder without
* freeing the #GVariantBuilder structure itself.
*
* It typically only makes sense to do this on a stack-allocated
* #GVariantBuilder if you want to abort building the value part-way
* through. This function need not be called if you call
* g_variant_builder_end() and it also doesn't need to be called on
* builders allocated with g_variant_builder_new (see
* g_variant_builder_unref() for that).
*
* This function leaves the #GVariantBuilder structure set to all-zeros.
* It is valid to call this function on either an initialised
* #GVariantBuilder or one that is set to all-zeros but it is not valid
* to call this function on uninitialised memory.
*
* Since: 2.24
**/
void
g_variant_builder_clear (GVariantBuilder *builder)
{
gsize i;
if (GVSB(builder)->magic == 0)
/* all-zeros case */
return;
g_return_if_fail (is_valid_builder (builder));
g_variant_type_free (GVSB(builder)->type);
for (i = 0; i < GVSB(builder)->offset; i++)
g_variant_unref (GVSB(builder)->children[i]);
g_free (GVSB(builder)->children);
if (GVSB(builder)->parent)
{
g_variant_builder_clear (GVSB(builder)->parent);
g_slice_free (GVariantBuilder, GVSB(builder)->parent);
}
memset (builder, 0, sizeof (GVariantBuilder));
}
/**
* g_variant_builder_init: (skip)
* @builder: a #GVariantBuilder
* @type: a container type
*
* Initialises a #GVariantBuilder structure.
*
* @type must be non-%NULL. It specifies the type of container to
* construct. It can be an indefinite type such as
* %G_VARIANT_TYPE_ARRAY or a definite type such as "as" or "(ii)".
* Maybe, array, tuple, dictionary entry and variant-typed values may be
* constructed.
*
* After the builder is initialised, values are added using
* g_variant_builder_add_value() or g_variant_builder_add().
*
* After all the child values are added, g_variant_builder_end() frees
* the memory associated with the builder and returns the #GVariant that
* was created.
*
* This function completely ignores the previous contents of @builder.
* On one hand this means that it is valid to pass in completely
* uninitialised memory. On the other hand, this means that if you are
* initialising over top of an existing #GVariantBuilder you need to
* first call g_variant_builder_clear() in order to avoid leaking
* memory.
*
* You must not call g_variant_builder_ref() or
* g_variant_builder_unref() on a #GVariantBuilder that was initialised
* with this function. If you ever pass a reference to a
* #GVariantBuilder outside of the control of your own code then you
* should assume that the person receiving that reference may try to use
* reference counting; you should use g_variant_builder_new() instead of
* this function.
*
* Since: 2.24
**/
void
g_variant_builder_init (GVariantBuilder *builder,
const GVariantType *type)
{
g_return_if_fail (type != NULL);
g_return_if_fail (g_variant_type_is_container (type));
memset (builder, 0, sizeof (GVariantBuilder));
GVSB(builder)->type = g_variant_type_copy (type);
GVSB(builder)->magic = GVSB_MAGIC;
GVSB(builder)->trusted = TRUE;
switch (*(const gchar *) type)
{
case G_VARIANT_CLASS_VARIANT:
GVSB(builder)->uniform_item_types = TRUE;
GVSB(builder)->allocated_children = 1;
GVSB(builder)->expected_type = NULL;
GVSB(builder)->min_items = 1;
GVSB(builder)->max_items = 1;
break;
case G_VARIANT_CLASS_ARRAY:
GVSB(builder)->uniform_item_types = TRUE;
GVSB(builder)->allocated_children = 8;
GVSB(builder)->expected_type =
g_variant_type_element (GVSB(builder)->type);
GVSB(builder)->min_items = 0;
GVSB(builder)->max_items = -1;
break;
case G_VARIANT_CLASS_MAYBE:
GVSB(builder)->uniform_item_types = TRUE;
GVSB(builder)->allocated_children = 1;
GVSB(builder)->expected_type =
g_variant_type_element (GVSB(builder)->type);
GVSB(builder)->min_items = 0;
GVSB(builder)->max_items = 1;
break;
case G_VARIANT_CLASS_DICT_ENTRY:
GVSB(builder)->uniform_item_types = FALSE;
GVSB(builder)->allocated_children = 2;
GVSB(builder)->expected_type =
g_variant_type_key (GVSB(builder)->type);
GVSB(builder)->min_items = 2;
GVSB(builder)->max_items = 2;
break;
case 'r': /* G_VARIANT_TYPE_TUPLE was given */
GVSB(builder)->uniform_item_types = FALSE;
GVSB(builder)->allocated_children = 8;
GVSB(builder)->expected_type = NULL;
GVSB(builder)->min_items = 0;
GVSB(builder)->max_items = -1;
break;
case G_VARIANT_CLASS_TUPLE: /* a definite tuple type was given */
GVSB(builder)->allocated_children = g_variant_type_n_items (type);
GVSB(builder)->expected_type =
g_variant_type_first (GVSB(builder)->type);
GVSB(builder)->min_items = GVSB(builder)->allocated_children;
GVSB(builder)->max_items = GVSB(builder)->allocated_children;
GVSB(builder)->uniform_item_types = FALSE;
break;
default:
g_assert_not_reached ();
}
GVSB(builder)->children = g_new (GVariant *,
GVSB(builder)->allocated_children);
}
static void
g_variant_builder_make_room (struct stack_builder *builder)
{
if (builder->offset == builder->allocated_children)
{
builder->allocated_children *= 2;
builder->children = g_renew (GVariant *, builder->children,
builder->allocated_children);
}
}
/**
* g_variant_builder_add_value:
* @builder: a #GVariantBuilder
* @value: a #GVariant
*
* Adds @value to @builder.
*
* It is an error to call this function in any way that would create an
* inconsistent value to be constructed. Some examples of this are
* putting different types of items into an array, putting the wrong
* types or number of items in a tuple, putting more than one value into
* a variant, etc.
*
* If @value is a floating reference (see g_variant_ref_sink()),
* the @builder instance takes ownership of @value.
*
* Since: 2.24
**/
void
g_variant_builder_add_value (GVariantBuilder *builder,
GVariant *value)
{
g_return_if_fail (is_valid_builder (builder));
g_return_if_fail (GVSB(builder)->offset < GVSB(builder)->max_items);
g_return_if_fail (!GVSB(builder)->expected_type ||
g_variant_is_of_type (value,
GVSB(builder)->expected_type));
g_return_if_fail (!GVSB(builder)->prev_item_type ||
g_variant_is_of_type (value,
GVSB(builder)->prev_item_type));
GVSB(builder)->trusted &= g_variant_is_trusted (value);
if (!GVSB(builder)->uniform_item_types)
{
/* advance our expected type pointers */
if (GVSB(builder)->expected_type)
GVSB(builder)->expected_type =
g_variant_type_next (GVSB(builder)->expected_type);
if (GVSB(builder)->prev_item_type)
GVSB(builder)->prev_item_type =
g_variant_type_next (GVSB(builder)->prev_item_type);
}
else
GVSB(builder)->prev_item_type = g_variant_get_type (value);
g_variant_builder_make_room (GVSB(builder));
GVSB(builder)->children[GVSB(builder)->offset++] =
g_variant_ref_sink (value);
}
/**
* g_variant_builder_open:
* @builder: a #GVariantBuilder
* @type: a #GVariantType
*
* Opens a subcontainer inside the given @builder. When done adding
* items to the subcontainer, g_variant_builder_close() must be called.
*
* It is an error to call this function in any way that would cause an
* inconsistent value to be constructed (ie: adding too many values or
* a value of an incorrect type).
*
* Since: 2.24
**/
void
g_variant_builder_open (GVariantBuilder *builder,
const GVariantType *type)
{
GVariantBuilder *parent;
g_return_if_fail (is_valid_builder (builder));
g_return_if_fail (GVSB(builder)->offset < GVSB(builder)->max_items);
g_return_if_fail (!GVSB(builder)->expected_type ||
g_variant_type_is_subtype_of (type,
GVSB(builder)->expected_type));
g_return_if_fail (!GVSB(builder)->prev_item_type ||
g_variant_type_is_subtype_of (GVSB(builder)->prev_item_type,
type));
parent = g_slice_dup (GVariantBuilder, builder);
g_variant_builder_init (builder, type);
GVSB(builder)->parent = parent;
/* push the prev_item_type down into the subcontainer */
if (GVSB(parent)->prev_item_type)
{
if (!GVSB(builder)->uniform_item_types)
/* tuples and dict entries */
GVSB(builder)->prev_item_type =
g_variant_type_first (GVSB(parent)->prev_item_type);
else if (!g_variant_type_is_variant (GVSB(builder)->type))
/* maybes and arrays */
GVSB(builder)->prev_item_type =
g_variant_type_element (GVSB(parent)->prev_item_type);
}
}
/**
* g_variant_builder_close:
* @builder: a #GVariantBuilder
*
* Closes the subcontainer inside the given @builder that was opened by
* the most recent call to g_variant_builder_open().
*
* It is an error to call this function in any way that would create an
* inconsistent value to be constructed (ie: too few values added to the
* subcontainer).
*
* Since: 2.24
**/
void
g_variant_builder_close (GVariantBuilder *builder)
{
GVariantBuilder *parent;
g_return_if_fail (is_valid_builder (builder));
g_return_if_fail (GVSB(builder)->parent != NULL);
parent = GVSB(builder)->parent;
GVSB(builder)->parent = NULL;
g_variant_builder_add_value (parent, g_variant_builder_end (builder));
*builder = *parent;
g_slice_free (GVariantBuilder, parent);
}
/*< private >
* g_variant_make_maybe_type:
* @element: a #GVariant
*
* Return the type of a maybe containing @element.
*/
static GVariantType *
g_variant_make_maybe_type (GVariant *element)
{
return g_variant_type_new_maybe (g_variant_get_type (element));
}
/*< private >
* g_variant_make_array_type:
* @element: a #GVariant
*
* Return the type of an array containing @element.
*/
static GVariantType *
g_variant_make_array_type (GVariant *element)
{
return g_variant_type_new_array (g_variant_get_type (element));
}
/**
* g_variant_builder_end:
* @builder: a #GVariantBuilder
*
* Ends the builder process and returns the constructed value.
*
* It is not permissible to use @builder in any way after this call
* except for reference counting operations (in the case of a
* heap-allocated #GVariantBuilder) or by reinitialising it with
* g_variant_builder_init() (in the case of stack-allocated).
*
* It is an error to call this function in any way that would create an
* inconsistent value to be constructed (ie: insufficient number of
* items added to a container with a specific number of children
* required). It is also an error to call this function if the builder
* was created with an indefinite array or maybe type and no children
* have been added; in this case it is impossible to infer the type of
* the empty array.
*
* Returns: (transfer none): a new, floating, #GVariant
*
* Since: 2.24
**/
GVariant *
g_variant_builder_end (GVariantBuilder *builder)
{
GVariantType *my_type;
GVariant *value;
g_return_val_if_fail (is_valid_builder (builder), NULL);
g_return_val_if_fail (GVSB(builder)->offset >= GVSB(builder)->min_items,
NULL);
g_return_val_if_fail (!GVSB(builder)->uniform_item_types ||
GVSB(builder)->prev_item_type != NULL ||
g_variant_type_is_definite (GVSB(builder)->type),
NULL);
if (g_variant_type_is_definite (GVSB(builder)->type))
my_type = g_variant_type_copy (GVSB(builder)->type);
else if (g_variant_type_is_maybe (GVSB(builder)->type))
my_type = g_variant_make_maybe_type (GVSB(builder)->children[0]);
else if (g_variant_type_is_array (GVSB(builder)->type))
my_type = g_variant_make_array_type (GVSB(builder)->children[0]);
else if (g_variant_type_is_tuple (GVSB(builder)->type))
my_type = g_variant_make_tuple_type (GVSB(builder)->children,
GVSB(builder)->offset);
else if (g_variant_type_is_dict_entry (GVSB(builder)->type))
my_type = g_variant_make_dict_entry_type (GVSB(builder)->children[0],
GVSB(builder)->children[1]);
else
g_assert_not_reached ();
value = g_variant_new_from_children (my_type,
g_renew (GVariant *,
GVSB(builder)->children,
GVSB(builder)->offset),
GVSB(builder)->offset,
GVSB(builder)->trusted);
GVSB(builder)->children = NULL;
GVSB(builder)->offset = 0;
g_variant_builder_clear (builder);
g_variant_type_free (my_type);
return value;
}
/* Format strings {{{1 */
/*< private >
* g_variant_format_string_scan:
* @string: a string that may be prefixed with a format string
* @limit: (allow-none) (default NULL): a pointer to the end of @string,
* or %NULL
* @endptr: (allow-none) (default NULL): location to store the end pointer,
* or %NULL
*
* Checks the string pointed to by @string for starting with a properly
* formed #GVariant varargs format string. If no valid format string is
* found then %FALSE is returned.
*
* If @string does start with a valid format string then %TRUE is
* returned. If @endptr is non-%NULL then it is updated to point to the
* first character after the format string.
*
* If @limit is non-%NULL then @limit (and any charater after it) will
* not be accessed and the effect is otherwise equivalent to if the
* character at @limit were nul.
*
* See the section on GVariant
* Format Strings.
*
* Returns: %TRUE if there was a valid format string
*
* Since: 2.24
*/
gboolean
g_variant_format_string_scan (const gchar *string,
const gchar *limit,
const gchar **endptr)
{
#define next_char() (string == limit ? '\0' : *string++)
#define peek_char() (string == limit ? '\0' : *string)
char c;
switch (next_char())
{
case 'b': case 'y': case 'n': case 'q': case 'i': case 'u':
case 'x': case 't': case 'h': case 'd': case 's': case 'o':
case 'g': case 'v': case '*': case '?': case 'r':
break;
case 'm':
return g_variant_format_string_scan (string, limit, endptr);
case 'a':
case '@':
return g_variant_type_string_scan (string, limit, endptr);
case '(':
while (peek_char() != ')')
if (!g_variant_format_string_scan (string, limit, &string))
return FALSE;
next_char(); /* consume ')' */
break;
case '{':
c = next_char();
if (c == '&')
{
c = next_char ();
if (c != 's' && c != 'o' && c != 'g')
return FALSE;
}
else
{
if (c == '@')
c = next_char ();
/* ISO/IEC 9899:1999 (C99) §7.21.5.2:
* The terminating null character is considered to be
* part of the string.
*/
if (c != '\0' && strchr ("bynqiuxthdsog?", c) == NULL)
return FALSE;
}
if (!g_variant_format_string_scan (string, limit, &string))
return FALSE;
if (next_char() != '}')
return FALSE;
break;
case '^':
if ((c = next_char()) == 'a')
{
if ((c = next_char()) == '&')
{
if ((c = next_char()) == 'a')
{
if ((c = next_char()) == 'y')
break; /* '^a&ay' */
}
else if (c == 's' || c == 'o')
break; /* '^a&s', '^a&o' */
}
else if (c == 'a')
{
if ((c = next_char()) == 'y')
break; /* '^aay' */
}
else if (c == 's' || c == 'o')
break; /* '^as', '^ao' */
else if (c == 'y')
break; /* '^ay' */
}
else if (c == '&')
{
if ((c = next_char()) == 'a')
{
if ((c = next_char()) == 'y')
break; /* '^&ay' */
}
}
return FALSE;
case '&':
c = next_char();
if (c != 's' && c != 'o' && c != 'g')
return FALSE;
break;
default:
return FALSE;
}
if (endptr != NULL)
*endptr = string;
#undef next_char
#undef peek_char
return TRUE;
}
/**
* g_variant_check_format_string:
* @value: a #GVariant
* @format_string: a valid #GVariant format string
* @copy_only: %TRUE to ensure the format string makes deep copies
*
* Checks if calling g_variant_get() with @format_string on @value would
* be valid from a type-compatibility standpoint. @format_string is
* assumed to be a valid format string (from a syntactic standpoint).
*
* If @copy_only is %TRUE then this function additionally checks that it
* would be safe to call g_variant_unref() on @value immediately after
* the call to g_variant_get() without invalidating the result. This is
* only possible if deep copies are made (ie: there are no pointers to
* the data inside of the soon-to-be-freed #GVariant instance). If this
* check fails then a g_critical() is printed and %FALSE is returned.
*
* This function is meant to be used by functions that wish to provide
* varargs accessors to #GVariant values of uncertain values (eg:
* g_variant_lookup() or g_menu_model_get_item_attribute()).
*
* Returns: %TRUE if @format_string is safe to use
*
* Since: 2.34
*/
gboolean
g_variant_check_format_string (GVariant *value,
const gchar *format_string,
gboolean copy_only)
{
const gchar *original_format = format_string;
const gchar *type_string;
/* Interesting factoid: assuming a format string is valid, it can be
* converted to a type string by removing all '@' '&' and '^'
* characters.
*
* Instead of doing that, we can just skip those characters when
* comparing it to the type string of @value.
*
* For the copy-only case we can just drop the '&' from the list of
* characters to skip over. A '&' will never appear in a type string
* so we know that it won't be possible to return %TRUE if it is in a
* format string.
*/
type_string = g_variant_get_type_string (value);
while (*type_string || *format_string)
{
gchar format = *format_string++;
switch (format)
{
case '&':
if G_UNLIKELY (copy_only)
{
/* for the love of all that is good, please don't mark this string for translation... */
g_critical ("g_variant_check_format_string() is being called by a function with a GVariant varargs "
"interface to validate the passed format string for type safety. The passed format "
"(%s) contains a '&' character which would result in a pointer being returned to the "
"data inside of a GVariant instance that may no longer exist by the time the function "
"returns. Modify your code to use a format string without '&'.", original_format);
return FALSE;
}
/* fall through */
case '^':
case '@':
/* ignore these 2 (or 3) */
continue;
case '?':
/* attempt to consume one of 'bynqiuxthdsog' */
{
char s = *type_string++;
if (s == '\0' || strchr ("bynqiuxthdsog", s) == NULL)
return FALSE;
}
continue;
case 'r':
/* ensure it's a tuple */
if (*type_string != '(')
return FALSE;
/* fall through */
case '*':
/* consume a full type string for the '*' or 'r' */
if (!g_variant_type_string_scan (type_string, NULL, &type_string))
return FALSE;
continue;
default:
/* attempt to consume exactly one character equal to the format */
if (format != *type_string++)
return FALSE;
}
}
return TRUE;
}
/*< private >
* g_variant_format_string_scan_type:
* @string: a string that may be prefixed with a format string
* @limit: (allow-none) (default NULL): a pointer to the end of @string,
* or %NULL
* @endptr: (allow-none) (default NULL): location to store the end pointer,
* or %NULL
*
* If @string starts with a valid format string then this function will
* return the type that the format string corresponds to. Otherwise
* this function returns %NULL.
*
* Use g_variant_type_free() to free the return value when you no longer
* need it.
*
* This function is otherwise exactly like
* g_variant_format_string_scan().
*
* Returns: (allow-none): a #GVariantType if there was a valid format string
*
* Since: 2.24
*/
GVariantType *
g_variant_format_string_scan_type (const gchar *string,
const gchar *limit,
const gchar **endptr)
{
const gchar *my_end;
gchar *dest;
gchar *new;
if (endptr == NULL)
endptr = &my_end;
if (!g_variant_format_string_scan (string, limit, endptr))
return NULL;
dest = new = g_malloc (*endptr - string + 1);
while (string != *endptr)
{
if (*string != '@' && *string != '&' && *string != '^')
*dest++ = *string;
string++;
}
*dest = '\0';
return (GVariantType *) G_VARIANT_TYPE (new);
}
static gboolean
valid_format_string (const gchar *format_string,
gboolean single,
GVariant *value)
{
const gchar *endptr;
GVariantType *type;
type = g_variant_format_string_scan_type (format_string, NULL, &endptr);
if G_UNLIKELY (type == NULL || (single && *endptr != '\0'))
{
if (single)
g_critical ("'%s' is not a valid GVariant format string",
format_string);
else
g_critical ("'%s' does not have a valid GVariant format "
"string as a prefix", format_string);
if (type != NULL)
g_variant_type_free (type);
return FALSE;
}
if G_UNLIKELY (value && !g_variant_is_of_type (value, type))
{
gchar *fragment;
gchar *typestr;
fragment = g_strndup (format_string, endptr - format_string);
typestr = g_variant_type_dup_string (type);
g_critical ("the GVariant format string '%s' has a type of "
"'%s' but the given value has a type of '%s'",
fragment, typestr, g_variant_get_type_string (value));
g_variant_type_free (type);
g_free (fragment);
g_free (typestr);
return FALSE;
}
g_variant_type_free (type);
return TRUE;
}
/* Variable Arguments {{{1 */
/* We consider 2 main classes of format strings:
*
* - recursive format strings
* these are ones that result in recursion and the collection of
* possibly more than one argument. Maybe types, tuples,
* dictionary entries.
*
* - leaf format string
* these result in the collection of a single argument.
*
* Leaf format strings are further subdivided into two categories:
*
* - single non-null pointer ("nnp")
* these either collect or return a single non-null pointer.
*
* - other
* these collect or return something else (bool, number, etc).
*
* Based on the above, the varargs handling code is split into 4 main parts:
*
* - nnp handling code
* - leaf handling code (which may invoke nnp code)
* - generic handling code (may be recursive, may invoke leaf code)
* - user-facing API (which invokes the generic code)
*
* Each section implements some of the following functions:
*
* - skip:
* collect the arguments for the format string as if
* g_variant_new() had been called, but do nothing with them. used
* for skipping over arguments when constructing a Nothing maybe
* type.
*
* - new:
* create a GVariant *
*
* - get:
* unpack a GVariant *
*
* - free (nnp only):
* free a previously allocated item
*/
static gboolean
g_variant_format_string_is_leaf (const gchar *str)
{
return str[0] != 'm' && str[0] != '(' && str[0] != '{';
}
static gboolean
g_variant_format_string_is_nnp (const gchar *str)
{
return str[0] == 'a' || str[0] == 's' || str[0] == 'o' || str[0] == 'g' ||
str[0] == '^' || str[0] == '@' || str[0] == '*' || str[0] == '?' ||
str[0] == 'r' || str[0] == 'v' || str[0] == '&';
}
/* Single non-null pointer ("nnp") {{{2 */
static void
g_variant_valist_free_nnp (const gchar *str,
gpointer ptr)
{
switch (*str)
{
case 'a':
g_variant_iter_free (ptr);
break;
case '^':
if (str[2] != '&') /* '^as', '^ao' */
g_strfreev (ptr);
else /* '^a&s', '^a&o' */
g_free (ptr);
break;
case 's':
case 'o':
case 'g':
g_free (ptr);
break;
case '@':
case '*':
case '?':
case 'v':
g_variant_unref (ptr);
break;
case '&':
break;
default:
g_assert_not_reached ();
}
}
static gchar
g_variant_scan_convenience (const gchar **str,
gboolean *constant,
guint *arrays)
{
*constant = FALSE;
*arrays = 0;
for (;;)
{
char c = *(*str)++;
if (c == '&')
*constant = TRUE;
else if (c == 'a')
(*arrays)++;
else
return c;
}
}
static GVariant *
g_variant_valist_new_nnp (const gchar **str,
gpointer ptr)
{
if (**str == '&')
(*str)++;
switch (*(*str)++)
{
case 'a':
if (ptr != NULL)
{
const GVariantType *type;
GVariant *value;
value = g_variant_builder_end (ptr);
type = g_variant_get_type (value);
if G_UNLIKELY (!g_variant_type_is_array (type))
g_error ("g_variant_new: expected array GVariantBuilder but "
"the built value has type '%s'",
g_variant_get_type_string (value));
type = g_variant_type_element (type);
if G_UNLIKELY (!g_variant_type_is_subtype_of (type, (GVariantType *) *str))
g_error ("g_variant_new: expected GVariantBuilder array element "
"type '%s' but the built value has element type '%s'",
g_variant_type_dup_string ((GVariantType *) *str),
g_variant_get_type_string (value) + 1);
g_variant_type_string_scan (*str, NULL, str);
return value;
}
else
/* special case: NULL pointer for empty array */
{
const GVariantType *type = (GVariantType *) *str;
g_variant_type_string_scan (*str, NULL, str);
if G_UNLIKELY (!g_variant_type_is_definite (type))
g_error ("g_variant_new: NULL pointer given with indefinite "
"array type; unable to determine which type of empty "
"array to construct.");
return g_variant_new_array (type, NULL, 0);
}
case 's':
{
GVariant *value;
value = g_variant_new_string (ptr);
if (value == NULL)
value = g_variant_new_string ("[Invalid UTF-8]");
return value;
}
case 'o':
return g_variant_new_object_path (ptr);
case 'g':
return g_variant_new_signature (ptr);
case '^':
{
gboolean constant;
guint arrays;
gchar type;
type = g_variant_scan_convenience (str, &constant, &arrays);
if (type == 's')
return g_variant_new_strv (ptr, -1);
if (type == 'o')
return g_variant_new_objv (ptr, -1);
if (arrays > 1)
return g_variant_new_bytestring_array (ptr, -1);
return g_variant_new_bytestring (ptr);
}
case '@':
if G_UNLIKELY (!g_variant_is_of_type (ptr, (GVariantType *) *str))
g_error ("g_variant_new: expected GVariant of type '%s' but "
"received value has type '%s'",
g_variant_type_dup_string ((GVariantType *) *str),
g_variant_get_type_string (ptr));
g_variant_type_string_scan (*str, NULL, str);
return ptr;
case '*':
return ptr;
case '?':
if G_UNLIKELY (!g_variant_type_is_basic (g_variant_get_type (ptr)))
g_error ("g_variant_new: format string '?' expects basic-typed "
"GVariant, but received value has type '%s'",
g_variant_get_type_string (ptr));
return ptr;
case 'r':
if G_UNLIKELY (!g_variant_type_is_tuple (g_variant_get_type (ptr)))
g_error ("g_variant_new: format string 'r' expects tuple-typed "
"GVariant, but received value has type '%s'",
g_variant_get_type_string (ptr));
return ptr;
case 'v':
return g_variant_new_variant (ptr);
default:
g_assert_not_reached ();
}
}
static gpointer
g_variant_valist_get_nnp (const gchar **str,
GVariant *value)
{
switch (*(*str)++)
{
case 'a':
g_variant_type_string_scan (*str, NULL, str);
return g_variant_iter_new (value);
case '&':
(*str)++;
return (gchar *) g_variant_get_string (value, NULL);
case 's':
case 'o':
case 'g':
return g_variant_dup_string (value, NULL);
case '^':
{
gboolean constant;
guint arrays;
gchar type;
type = g_variant_scan_convenience (str, &constant, &arrays);
if (type == 's')
{
if (constant)
return g_variant_get_strv (value, NULL);
else
return g_variant_dup_strv (value, NULL);
}
else if (type == 'o')
{
if (constant)
return g_variant_get_objv (value, NULL);
else
return g_variant_dup_objv (value, NULL);
}
else if (arrays > 1)
{
if (constant)
return g_variant_get_bytestring_array (value, NULL);
else
return g_variant_dup_bytestring_array (value, NULL);
}
else
{
if (constant)
return (gchar *) g_variant_get_bytestring (value);
else
return g_variant_dup_bytestring (value, NULL);
}
}
case '@':
g_variant_type_string_scan (*str, NULL, str);
/* fall through */
case '*':
case '?':
case 'r':
return g_variant_ref (value);
case 'v':
return g_variant_get_variant (value);
default:
g_assert_not_reached ();
}
}
/* Leaves {{{2 */
static void
g_variant_valist_skip_leaf (const gchar **str,
va_list *app)
{
if (g_variant_format_string_is_nnp (*str))
{
g_variant_format_string_scan (*str, NULL, str);
va_arg (*app, gpointer);
return;
}
switch (*(*str)++)
{
case 'b':
case 'y':
case 'n':
case 'q':
case 'i':
case 'u':
case 'h':
va_arg (*app, int);
return;
case 'x':
case 't':
va_arg (*app, guint64);
return;
case 'd':
va_arg (*app, gdouble);
return;
default:
g_assert_not_reached ();
}
}
static GVariant *
g_variant_valist_new_leaf (const gchar **str,
va_list *app)
{
if (g_variant_format_string_is_nnp (*str))
return g_variant_valist_new_nnp (str, va_arg (*app, gpointer));
switch (*(*str)++)
{
case 'b':
return g_variant_new_boolean (va_arg (*app, gboolean));
case 'y':
return g_variant_new_byte (va_arg (*app, guint));
case 'n':
return g_variant_new_int16 (va_arg (*app, gint));
case 'q':
return g_variant_new_uint16 (va_arg (*app, guint));
case 'i':
return g_variant_new_int32 (va_arg (*app, gint));
case 'u':
return g_variant_new_uint32 (va_arg (*app, guint));
case 'x':
return g_variant_new_int64 (va_arg (*app, gint64));
case 't':
return g_variant_new_uint64 (va_arg (*app, guint64));
case 'h':
return g_variant_new_handle (va_arg (*app, gint));
case 'd':
return g_variant_new_double (va_arg (*app, gdouble));
default:
g_assert_not_reached ();
}
}
/* The code below assumes this */
G_STATIC_ASSERT (sizeof (gboolean) == sizeof (guint32));
G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
static void
g_variant_valist_get_leaf (const gchar **str,
GVariant *value,
gboolean free,
va_list *app)
{
gpointer ptr = va_arg (*app, gpointer);
if (ptr == NULL)
{
g_variant_format_string_scan (*str, NULL, str);
return;
}
if (g_variant_format_string_is_nnp (*str))
{
gpointer *nnp = (gpointer *) ptr;
if (free && *nnp != NULL)
g_variant_valist_free_nnp (*str, *nnp);
*nnp = NULL;
if (value != NULL)
*nnp = g_variant_valist_get_nnp (str, value);
else
g_variant_format_string_scan (*str, NULL, str);
return;
}
if (value != NULL)
{
switch (*(*str)++)
{
case 'b':
*(gboolean *) ptr = g_variant_get_boolean (value);
return;
case 'y':
*(guchar *) ptr = g_variant_get_byte (value);
return;
case 'n':
*(gint16 *) ptr = g_variant_get_int16 (value);
return;
case 'q':
*(guint16 *) ptr = g_variant_get_uint16 (value);
return;
case 'i':
*(gint32 *) ptr = g_variant_get_int32 (value);
return;
case 'u':
*(guint32 *) ptr = g_variant_get_uint32 (value);
return;
case 'x':
*(gint64 *) ptr = g_variant_get_int64 (value);
return;
case 't':
*(guint64 *) ptr = g_variant_get_uint64 (value);
return;
case 'h':
*(gint32 *) ptr = g_variant_get_handle (value);
return;
case 'd':
*(gdouble *) ptr = g_variant_get_double (value);
return;
}
}
else
{
switch (*(*str)++)
{
case 'y':
*(guchar *) ptr = 0;
return;
case 'n':
case 'q':
*(guint16 *) ptr = 0;
return;
case 'i':
case 'u':
case 'h':
case 'b':
*(guint32 *) ptr = 0;
return;
case 'x':
case 't':
case 'd':
*(guint64 *) ptr = 0;
return;
}
}
g_assert_not_reached ();
}
/* Generic (recursive) {{{2 */
static void
g_variant_valist_skip (const gchar **str,
va_list *app)
{
if (g_variant_format_string_is_leaf (*str))
g_variant_valist_skip_leaf (str, app);
else if (**str == 'm') /* maybe */
{
(*str)++;
if (!g_variant_format_string_is_nnp (*str))
va_arg (*app, gboolean);
g_variant_valist_skip (str, app);
}
else /* tuple, dictionary entry */
{
g_assert (**str == '(' || **str == '{');
(*str)++;
while (**str != ')' && **str != '}')
g_variant_valist_skip (str, app);
(*str)++;
}
}
static GVariant *
g_variant_valist_new (const gchar **str,
va_list *app)
{
if (g_variant_format_string_is_leaf (*str))
return g_variant_valist_new_leaf (str, app);
if (**str == 'm') /* maybe */
{
GVariantType *type = NULL;
GVariant *value = NULL;
(*str)++;
if (g_variant_format_string_is_nnp (*str))
{
gpointer nnp = va_arg (*app, gpointer);
if (nnp != NULL)
value = g_variant_valist_new_nnp (str, nnp);
else
type = g_variant_format_string_scan_type (*str, NULL, str);
}
else
{
gboolean just = va_arg (*app, gboolean);
if (just)
value = g_variant_valist_new (str, app);
else
{
type = g_variant_format_string_scan_type (*str, NULL, NULL);
g_variant_valist_skip (str, app);
}
}
value = g_variant_new_maybe (type, value);
if (type != NULL)
g_variant_type_free (type);
return value;
}
else /* tuple, dictionary entry */
{
GVariantBuilder b;
if (**str == '(')
g_variant_builder_init (&b, G_VARIANT_TYPE_TUPLE);
else
{
g_assert (**str == '{');
g_variant_builder_init (&b, G_VARIANT_TYPE_DICT_ENTRY);
}
(*str)++; /* '(' */
while (**str != ')' && **str != '}')
g_variant_builder_add_value (&b, g_variant_valist_new (str, app));
(*str)++; /* ')' */
return g_variant_builder_end (&b);
}
}
static void
g_variant_valist_get (const gchar **str,
GVariant *value,
gboolean free,
va_list *app)
{
if (g_variant_format_string_is_leaf (*str))
g_variant_valist_get_leaf (str, value, free, app);
else if (**str == 'm')
{
(*str)++;
if (value != NULL)
value = g_variant_get_maybe (value);
if (!g_variant_format_string_is_nnp (*str))
{
gboolean *ptr = va_arg (*app, gboolean *);
if (ptr != NULL)
*ptr = value != NULL;
}
g_variant_valist_get (str, value, free, app);
if (value != NULL)
g_variant_unref (value);
}
else /* tuple, dictionary entry */
{
gint index = 0;
g_assert (**str == '(' || **str == '{');
(*str)++;
while (**str != ')' && **str != '}')
{
if (value != NULL)
{
GVariant *child = g_variant_get_child_value (value, index++);
g_variant_valist_get (str, child, free, app);
g_variant_unref (child);
}
else
g_variant_valist_get (str, NULL, free, app);
}
(*str)++;
}
}
/* User-facing API {{{2 */
/**
* g_variant_new: (skip)
* @format_string: a #GVariant format string
* @...: arguments, as per @format_string
*
* Creates a new #GVariant instance.
*
* Think of this function as an analogue to g_strdup_printf().
*
* The type of the created instance and the arguments that are
* expected by this function are determined by @format_string. See the
* section on GVariant Format
* Strings. Please note that the syntax of the format string is
* very likely to be extended in the future.
*
* The first character of the format string must not be '*' '?' '@' or
* 'r'; in essence, a new #GVariant must always be constructed by this
* function (and not merely passed through it unmodified).
*
* Returns: a new floating #GVariant instance
*
* Since: 2.24
**/
GVariant *
g_variant_new (const gchar *format_string,
...)
{
GVariant *value;
va_list ap;
g_return_val_if_fail (valid_format_string (format_string, TRUE, NULL) &&
format_string[0] != '?' && format_string[0] != '@' &&
format_string[0] != '*' && format_string[0] != 'r',
NULL);
va_start (ap, format_string);
value = g_variant_new_va (format_string, NULL, &ap);
va_end (ap);
return value;
}
/**
* g_variant_new_va: (skip)
* @format_string: a string that is prefixed with a format string
* @endptr: (allow-none) (default NULL): location to store the end pointer,
* or %NULL
* @app: a pointer to a #va_list
*
* This function is intended to be used by libraries based on
* #GVariant that want to provide g_variant_new()-like functionality
* to their users.
*
* The API is more general than g_variant_new() to allow a wider range
* of possible uses.
*
* @format_string must still point to a valid format string, but it only
* needs to be nul-terminated if @endptr is %NULL. If @endptr is
* non-%NULL then it is updated to point to the first character past the
* end of the format string.
*
* @app is a pointer to a #va_list. The arguments, according to
* @format_string, are collected from this #va_list and the list is left
* pointing to the argument following the last.
*
* These two generalisations allow mixing of multiple calls to
* g_variant_new_va() and g_variant_get_va() within a single actual
* varargs call by the user.
*
* The return value will be floating if it was a newly created GVariant
* instance (for example, if the format string was "(ii)"). In the case
* that the format_string was '*', '?', 'r', or a format starting with
* '@' then the collected #GVariant pointer will be returned unmodified,
* without adding any additional references.
*
* In order to behave correctly in all cases it is necessary for the
* calling function to g_variant_ref_sink() the return result before
* returning control to the user that originally provided the pointer.
* At this point, the caller will have their own full reference to the
* result. This can also be done by adding the result to a container,
* or by passing it to another g_variant_new() call.
*
* Returns: a new, usually floating, #GVariant
*
* Since: 2.24
**/
GVariant *
g_variant_new_va (const gchar *format_string,
const gchar **endptr,
va_list *app)
{
GVariant *value;
g_return_val_if_fail (valid_format_string (format_string, !endptr, NULL),
NULL);
g_return_val_if_fail (app != NULL, NULL);
value = g_variant_valist_new (&format_string, app);
if (endptr != NULL)
*endptr = format_string;
return value;
}
/**
* g_variant_get: (skip)
* @value: a #GVariant instance
* @format_string: a #GVariant format string
* @...: arguments, as per @format_string
*
* Deconstructs a #GVariant instance.
*
* Think of this function as an analogue to scanf().
*
* The arguments that are expected by this function are entirely
* determined by @format_string. @format_string also restricts the
* permissible types of @value. It is an error to give a value with
* an incompatible type. See the section on GVariant Format Strings.
* Please note that the syntax of the format string is very likely to be
* extended in the future.
*
* @format_string determines the C types that are used for unpacking
* the values and also determines if the values are copied or borrowed,
* see the section on
* GVariant Format Strings.
*
* Since: 2.24
**/
void
g_variant_get (GVariant *value,
const gchar *format_string,
...)
{
va_list ap;
g_return_if_fail (valid_format_string (format_string, TRUE, value));
/* if any direct-pointer-access formats are in use, flatten first */
if (strchr (format_string, '&'))
g_variant_get_data (value);
va_start (ap, format_string);
g_variant_get_va (value, format_string, NULL, &ap);
va_end (ap);
}
/**
* g_variant_get_va: (skip)
* @value: a #GVariant
* @format_string: a string that is prefixed with a format string
* @endptr: (allow-none) (default NULL): location to store the end pointer,
* or %NULL
* @app: a pointer to a #va_list
*
* This function is intended to be used by libraries based on #GVariant
* that want to provide g_variant_get()-like functionality to their
* users.
*
* The API is more general than g_variant_get() to allow a wider range
* of possible uses.
*
* @format_string must still point to a valid format string, but it only
* need to be nul-terminated if @endptr is %NULL. If @endptr is
* non-%NULL then it is updated to point to the first character past the
* end of the format string.
*
* @app is a pointer to a #va_list. The arguments, according to
* @format_string, are collected from this #va_list and the list is left
* pointing to the argument following the last.
*
* These two generalisations allow mixing of multiple calls to
* g_variant_new_va() and g_variant_get_va() within a single actual
* varargs call by the user.
*
* @format_string determines the C types that are used for unpacking
* the values and also determines if the values are copied or borrowed,
* see the section on
* GVariant Format Strings.
*
* Since: 2.24
**/
void
g_variant_get_va (GVariant *value,
const gchar *format_string,
const gchar **endptr,
va_list *app)
{
g_return_if_fail (valid_format_string (format_string, !endptr, value));
g_return_if_fail (value != NULL);
g_return_if_fail (app != NULL);
/* if any direct-pointer-access formats are in use, flatten first */
if (strchr (format_string, '&'))
g_variant_get_data (value);
g_variant_valist_get (&format_string, value, FALSE, app);
if (endptr != NULL)
*endptr = format_string;
}
/* Varargs-enabled Utility Functions {{{1 */
/**
* g_variant_builder_add: (skp)
* @builder: a #GVariantBuilder
* @format_string: a #GVariant varargs format string
* @...: arguments, as per @format_string
*
* Adds to a #GVariantBuilder.
*
* This call is a convenience wrapper that is exactly equivalent to
* calling g_variant_new() followed by g_variant_builder_add_value().
*
* This function might be used as follows:
*
*
* GVariant *
* make_pointless_dictionary (void)
* {
* GVariantBuilder *builder;
* int i;
*
* builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
* for (i = 0; i < 16; i++)
* {
* gchar buf[3];
*
* sprintf (buf, "%d", i);
* g_variant_builder_add (builder, "{is}", i, buf);
* }
*
* return g_variant_builder_end (builder);
* }
*
*
* Since: 2.24
**/
void
g_variant_builder_add (GVariantBuilder *builder,
const gchar *format_string,
...)
{
GVariant *variant;
va_list ap;
va_start (ap, format_string);
variant = g_variant_new_va (format_string, NULL, &ap);
va_end (ap);
g_variant_builder_add_value (builder, variant);
}
/**
* g_variant_get_child: (skip)
* @value: a container #GVariant
* @index_: the index of the child to deconstruct
* @format_string: a #GVariant format string
* @...: arguments, as per @format_string
*
* Reads a child item out of a container #GVariant instance and
* deconstructs it according to @format_string. This call is
* essentially a combination of g_variant_get_child_value() and
* g_variant_get().
*
* @format_string determines the C types that are used for unpacking
* the values and also determines if the values are copied or borrowed,
* see the section on
* GVariant Format Strings.
*
* Since: 2.24
**/
void
g_variant_get_child (GVariant *value,
gsize index_,
const gchar *format_string,
...)
{
GVariant *child;
va_list ap;
child = g_variant_get_child_value (value, index_);
g_return_if_fail (valid_format_string (format_string, TRUE, child));
va_start (ap, format_string);
g_variant_get_va (child, format_string, NULL, &ap);
va_end (ap);
g_variant_unref (child);
}
/**
* g_variant_iter_next: (skip)
* @iter: a #GVariantIter
* @format_string: a GVariant format string
* @...: the arguments to unpack the value into
*
* Gets the next item in the container and unpacks it into the variable
* argument list according to @format_string, returning %TRUE.
*
* If no more items remain then %FALSE is returned.
*
* All of the pointers given on the variable arguments list of this
* function are assumed to point at uninitialised memory. It is the
* responsibility of the caller to free all of the values returned by
* the unpacking process.
*
* See the section on GVariant
* Format Strings.
*
*
* Memory management with g_variant_iter_next()
*
* /* Iterates a dictionary of type 'a{sv}' */
* void
* iterate_dictionary (GVariant *dictionary)
* {
* GVariantIter iter;
* GVariant *value;
* gchar *key;
*
* g_variant_iter_init (&iter, dictionary);
* while (g_variant_iter_next (&iter, "{sv}", &key, &value))
* {
* g_print ("Item '%s' has type '%s'\n", key,
* g_variant_get_type_string (value));
*
* /* must free data for ourselves */
* g_variant_unref (value);
* g_free (key);
* }
* }
*
*
*
* For a solution that is likely to be more convenient to C programmers
* when dealing with loops, see g_variant_iter_loop().
*
* @format_string determines the C types that are used for unpacking
* the values and also determines if the values are copied or borrowed,
* see the section on
* GVariant Format Strings.
*
* Returns: %TRUE if a value was unpacked, or %FALSE if there as no value
*
* Since: 2.24
**/
gboolean
g_variant_iter_next (GVariantIter *iter,
const gchar *format_string,
...)
{
GVariant *value;
value = g_variant_iter_next_value (iter);
g_return_val_if_fail (valid_format_string (format_string, TRUE, value),
FALSE);
if (value != NULL)
{
va_list ap;
va_start (ap, format_string);
g_variant_valist_get (&format_string, value, FALSE, &ap);
va_end (ap);
g_variant_unref (value);
}
return value != NULL;
}
/**
* g_variant_iter_loop: (skip)
* @iter: a #GVariantIter
* @format_string: a GVariant format string
* @...: the arguments to unpack the value into
*
* Gets the next item in the container and unpacks it into the variable
* argument list according to @format_string, returning %TRUE.
*
* If no more items remain then %FALSE is returned.
*
* On the first call to this function, the pointers appearing on the
* variable argument list are assumed to point at uninitialised memory.
* On the second and later calls, it is assumed that the same pointers
* will be given and that they will point to the memory as set by the
* previous call to this function. This allows the previous values to
* be freed, as appropriate.
*
* This function is intended to be used with a while loop as
* demonstrated in the following example. This function can only be
* used when iterating over an array. It is only valid to call this
* function with a string constant for the format string and the same
* string constant must be used each time. Mixing calls to this
* function and g_variant_iter_next() or g_variant_iter_next_value() on
* the same iterator causes undefined behavior.
*
* If you break out of a such a while loop using g_variant_iter_loop() then
* you must free or unreference all the unpacked values as you would with
* g_variant_get(). Failure to do so will cause a memory leak.
*
* See the section on GVariant
* Format Strings.
*
*
* Memory management with g_variant_iter_loop()
*
* /* Iterates a dictionary of type 'a{sv}' */
* void
* iterate_dictionary (GVariant *dictionary)
* {
* GVariantIter iter;
* GVariant *value;
* gchar *key;
*
* g_variant_iter_init (&iter, dictionary);
* while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
* {
* g_print ("Item '%s' has type '%s'\n", key,
* g_variant_get_type_string (value));
*
* /* no need to free 'key' and 'value' here */
* /* unless breaking out of this loop */
* }
* }
*
*
*
* For most cases you should use g_variant_iter_next().
*
* This function is really only useful when unpacking into #GVariant or
* #GVariantIter in order to allow you to skip the call to
* g_variant_unref() or g_variant_iter_free().
*
* For example, if you are only looping over simple integer and string
* types, g_variant_iter_next() is definitely preferred. For string
* types, use the '&' prefix to avoid allocating any memory at all (and
* thereby avoiding the need to free anything as well).
*
* @format_string determines the C types that are used for unpacking
* the values and also determines if the values are copied or borrowed,
* see the section on
* GVariant Format Strings.
*
* Returns: %TRUE if a value was unpacked, or %FALSE if there was no
* value
*
* Since: 2.24
**/
gboolean
g_variant_iter_loop (GVariantIter *iter,
const gchar *format_string,
...)
{
gboolean first_time = GVSI(iter)->loop_format == NULL;
GVariant *value;
va_list ap;
g_return_val_if_fail (first_time ||
format_string == GVSI(iter)->loop_format,
FALSE);
if (first_time)
{
TYPE_CHECK (GVSI(iter)->value, G_VARIANT_TYPE_ARRAY, FALSE);
GVSI(iter)->loop_format = format_string;
if (strchr (format_string, '&'))
g_variant_get_data (GVSI(iter)->value);
}
value = g_variant_iter_next_value (iter);
g_return_val_if_fail (!first_time ||
valid_format_string (format_string, TRUE, value),
FALSE);
va_start (ap, format_string);
g_variant_valist_get (&format_string, value, !first_time, &ap);
va_end (ap);
if (value != NULL)
g_variant_unref (value);
return value != NULL;
}
/* Serialised data {{{1 */
static GVariant *
g_variant_deep_copy (GVariant *value)
{
switch (g_variant_classify (value))
{
case G_VARIANT_CLASS_MAYBE:
case G_VARIANT_CLASS_ARRAY:
case G_VARIANT_CLASS_TUPLE:
case G_VARIANT_CLASS_DICT_ENTRY:
case G_VARIANT_CLASS_VARIANT:
{
GVariantBuilder builder;
GVariantIter iter;
GVariant *child;
g_variant_builder_init (&builder, g_variant_get_type (value));
g_variant_iter_init (&iter, value);
while ((child = g_variant_iter_next_value (&iter)))
{
g_variant_builder_add_value (&builder, g_variant_deep_copy (child));
g_variant_unref (child);
}
return g_variant_builder_end (&builder);
}
case G_VARIANT_CLASS_BOOLEAN:
return g_variant_new_boolean (g_variant_get_boolean (value));
case G_VARIANT_CLASS_BYTE:
return g_variant_new_byte (g_variant_get_byte (value));
case G_VARIANT_CLASS_INT16:
return g_variant_new_int16 (g_variant_get_int16 (value));
case G_VARIANT_CLASS_UINT16:
return g_variant_new_uint16 (g_variant_get_uint16 (value));
case G_VARIANT_CLASS_INT32:
return g_variant_new_int32 (g_variant_get_int32 (value));
case G_VARIANT_CLASS_UINT32:
return g_variant_new_uint32 (g_variant_get_uint32 (value));
case G_VARIANT_CLASS_INT64:
return g_variant_new_int64 (g_variant_get_int64 (value));
case G_VARIANT_CLASS_UINT64:
return g_variant_new_uint64 (g_variant_get_uint64 (value));
case G_VARIANT_CLASS_HANDLE:
return g_variant_new_handle (g_variant_get_handle (value));
case G_VARIANT_CLASS_DOUBLE:
return g_variant_new_double (g_variant_get_double (value));
case G_VARIANT_CLASS_STRING:
return g_variant_new_string (g_variant_get_string (value, NULL));
case G_VARIANT_CLASS_OBJECT_PATH:
return g_variant_new_object_path (g_variant_get_string (value, NULL));
case G_VARIANT_CLASS_SIGNATURE:
return g_variant_new_signature (g_variant_get_string (value, NULL));
}
g_assert_not_reached ();
}
/**
* g_variant_get_normal_form:
* @value: a #GVariant
*
* Gets a #GVariant instance that has the same value as @value and is
* trusted to be in normal form.
*
* If @value is already trusted to be in normal form then a new
* reference to @value is returned.
*
* If @value is not already trusted, then it is scanned to check if it
* is in normal form. If it is found to be in normal form then it is
* marked as trusted and a new reference to it is returned.
*
* If @value is found not to be in normal form then a new trusted
* #GVariant is created with the same value as @value.
*
* It makes sense to call this function if you've received #GVariant
* data from untrusted sources and you want to ensure your serialised
* output is definitely in normal form.
*
* Returns: (transfer full): a trusted #GVariant
*
* Since: 2.24
**/
GVariant *
g_variant_get_normal_form (GVariant *value)
{
GVariant *trusted;
if (g_variant_is_normal_form (value))
return g_variant_ref (value);
trusted = g_variant_deep_copy (value);
g_assert (g_variant_is_trusted (trusted));
return g_variant_ref_sink (trusted);
}
/**
* g_variant_byteswap:
* @value: a #GVariant
*
* Performs a byteswapping operation on the contents of @value. The
* result is that all multi-byte numeric data contained in @value is
* byteswapped. That includes 16, 32, and 64bit signed and unsigned
* integers as well as file handles and double precision floating point
* values.
*
* This function is an identity mapping on any value that does not
* contain multi-byte numeric data. That include strings, booleans,
* bytes and containers containing only these things (recursively).
*
* The returned value is always in normal form and is marked as trusted.
*
* Returns: (transfer full): the byteswapped form of @value
*
* Since: 2.24
**/
GVariant *
g_variant_byteswap (GVariant *value)
{
GVariantTypeInfo *type_info;
guint alignment;
GVariant *new;
type_info = g_variant_get_type_info (value);
g_variant_type_info_query (type_info, &alignment, NULL);
if (alignment)
/* (potentially) contains multi-byte numeric data */
{
GVariantSerialised serialised;
GVariant *trusted;
GBytes *bytes;
trusted = g_variant_get_normal_form (value);
serialised.type_info = g_variant_get_type_info (trusted);
serialised.size = g_variant_get_size (trusted);
serialised.data = g_malloc (serialised.size);
g_variant_store (trusted, serialised.data);
g_variant_unref (trusted);
g_variant_serialised_byteswap (serialised);
bytes = g_bytes_new_take (serialised.data, serialised.size);
new = g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE);
g_bytes_unref (bytes);
}
else
/* contains no multi-byte data */
new = value;
return g_variant_ref_sink (new);
}
/**
* g_variant_new_from_data:
* @type: a definite #GVariantType
* @data: (array length=size) (element-type guint8): the serialised data
* @size: the size of @data
* @trusted: %TRUE if @data is definitely in normal form
* @notify: (scope async): function to call when @data is no longer needed
* @user_data: data for @notify
*
* Creates a new #GVariant instance from serialised data.
*
* @type is the type of #GVariant instance that will be constructed.
* The interpretation of @data depends on knowing the type.
*
* @data is not modified by this function and must remain valid with an
* unchanging value until such a time as @notify is called with
* @user_data. If the contents of @data change before that time then
* the result is undefined.
*
* If @data is trusted to be serialised data in normal form then
* @trusted should be %TRUE. This applies to serialised data created
* within this process or read from a trusted location on the disk (such
* as a file installed in /usr/lib alongside your application). You
* should set trusted to %FALSE if @data is read from the network, a
* file in the user's home directory, etc.
*
* If @data was not stored in this machine's native endianness, any multi-byte
* numeric values in the returned variant will also be in non-native
* endianness. g_variant_byteswap() can be used to recover the original values.
*
* @notify will be called with @user_data when @data is no longer
* needed. The exact time of this call is unspecified and might even be
* before this function returns.
*
* Returns: (transfer none): a new floating #GVariant of type @type
*
* Since: 2.24
**/
GVariant *
g_variant_new_from_data (const GVariantType *type,
gconstpointer data,
gsize size,
gboolean trusted,
GDestroyNotify notify,
gpointer user_data)
{
GVariant *value;
GBytes *bytes;
g_return_val_if_fail (g_variant_type_is_definite (type), NULL);
g_return_val_if_fail (data != NULL || size == 0, NULL);
if (notify)
bytes = g_bytes_new_with_free_func (data, size, notify, user_data);
else
bytes = g_bytes_new_static (data, size);
value = g_variant_new_from_bytes (type, bytes, trusted);
g_bytes_unref (bytes);
return value;
}
/* Epilogue {{{1 */
/* vim:set foldmethod=marker: */
pkg-config-0.29.1/glib/glib/gmarkup.h 0000664 0001750 0001750 00000024576 12651243552 014246 0000000 0000000 /* gmarkup.h - Simple XML-like string parser/writer
*
* Copyright 2000 Red Hat, Inc.
*
* GLib 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 of the
* License, or (at your option) any later version.
*
* GLib 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 GLib; see the file COPYING.LIB. If not,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __G_MARKUP_H__
#define __G_MARKUP_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
#include
#include
G_BEGIN_DECLS
/**
* GMarkupError:
* @G_MARKUP_ERROR_BAD_UTF8: text being parsed was not valid UTF-8
* @G_MARKUP_ERROR_EMPTY: document contained nothing, or only whitespace
* @G_MARKUP_ERROR_PARSE: document was ill-formed
* @G_MARKUP_ERROR_UNKNOWN_ELEMENT: error should be set by #GMarkupParser
* functions; element wasn't known
* @G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE: error should be set by #GMarkupParser
* functions; attribute wasn't known
* @G_MARKUP_ERROR_INVALID_CONTENT: error should be set by #GMarkupParser
* functions; content was invalid
* @G_MARKUP_ERROR_MISSING_ATTRIBUTE: error should be set by #GMarkupParser
* functions; a required attribute was missing
*
* Error codes returned by markup parsing.
*/
typedef enum
{
G_MARKUP_ERROR_BAD_UTF8,
G_MARKUP_ERROR_EMPTY,
G_MARKUP_ERROR_PARSE,
/* The following are primarily intended for specific GMarkupParser
* implementations to set.
*/
G_MARKUP_ERROR_UNKNOWN_ELEMENT,
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
G_MARKUP_ERROR_INVALID_CONTENT,
G_MARKUP_ERROR_MISSING_ATTRIBUTE
} GMarkupError;
/**
* G_MARKUP_ERROR:
*
* Error domain for markup parsing.
* Errors in this domain will be from the #GMarkupError enumeration.
* See #GError for information on error domains.
*/
#define G_MARKUP_ERROR g_markup_error_quark ()
GLIB_AVAILABLE_IN_ALL
GQuark g_markup_error_quark (void);
/**
* GMarkupParseFlags:
* @G_MARKUP_DO_NOT_USE_THIS_UNSUPPORTED_FLAG: flag you should not use
* @G_MARKUP_TREAT_CDATA_AS_TEXT: When this flag is set, CDATA marked
* sections are not passed literally to the @passthrough function of
* the parser. Instead, the content of the section (without the
* <![CDATA[ and ]]>) is
* passed to the @text function. This flag was added in GLib 2.12
* @G_MARKUP_PREFIX_ERROR_POSITION: Normally errors caught by GMarkup
* itself have line/column information prefixed to them to let the
* caller know the location of the error. When this flag is set the
* location information is also prefixed to errors generated by the
* #GMarkupParser implementation functions
*
* Flags that affect the behaviour of the parser.
*/
typedef enum
{
G_MARKUP_DO_NOT_USE_THIS_UNSUPPORTED_FLAG = 1 << 0,
G_MARKUP_TREAT_CDATA_AS_TEXT = 1 << 1,
G_MARKUP_PREFIX_ERROR_POSITION = 1 << 2
} GMarkupParseFlags;
/**
* GMarkupParseContext:
*
* A parse context is used to parse a stream of bytes that
* you expect to contain marked-up text.
*
* See g_markup_parse_context_new(), #GMarkupParser, and so
* on for more details.
*/
typedef struct _GMarkupParseContext GMarkupParseContext;
typedef struct _GMarkupParser GMarkupParser;
/**
* GMarkupParser:
* @start_element: Callback to invoke when the opening tag of an element
* is seen.
* @end_element: Callback to invoke when the closing tag of an element
* is seen. Note that this is also called for empty tags like
* <empty/>.
* @text: Callback to invoke when some text is seen (text is always
* inside an element). Note that the text of an element may be spread
* over multiple calls of this function. If the
* %G_MARKUP_TREAT_CDATA_AS_TEXT flag is set, this function is also
* called for the content of CDATA marked sections.
* @passthrough: Callback to invoke for comments, processing instructions
* and doctype declarations; if you're re-writing the parsed document,
* write the passthrough text back out in the same position. If the
* %G_MARKUP_TREAT_CDATA_AS_TEXT flag is not set, this function is also
* called for CDATA marked sections.
* @error: Callback to invoke when an error occurs.
*
* Any of the fields in #GMarkupParser can be %NULL, in which case they
* will be ignored. Except for the @error function, any of these callbacks
* can set an error; in particular the %G_MARKUP_ERROR_UNKNOWN_ELEMENT,
* %G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, and %G_MARKUP_ERROR_INVALID_CONTENT
* errors are intended to be set from these callbacks. If you set an error
* from a callback, g_markup_parse_context_parse() will report that error
* back to its caller.
*/
struct _GMarkupParser
{
/* Called for open tags */
void (*start_element) (GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
const gchar **attribute_values,
gpointer user_data,
GError **error);
/* Called for close tags */
void (*end_element) (GMarkupParseContext *context,
const gchar *element_name,
gpointer user_data,
GError **error);
/* Called for character data */
/* text is not nul-terminated */
void (*text) (GMarkupParseContext *context,
const gchar *text,
gsize text_len,
gpointer user_data,
GError **error);
/* Called for strings that should be re-saved verbatim in this same
* position, but are not otherwise interpretable. At the moment
* this includes comments and processing instructions.
*/
/* text is not nul-terminated. */
void (*passthrough) (GMarkupParseContext *context,
const gchar *passthrough_text,
gsize text_len,
gpointer user_data,
GError **error);
/* Called on error, including one set by other
* methods in the vtable. The GError should not be freed.
*/
void (*error) (GMarkupParseContext *context,
GError *error,
gpointer user_data);
};
GLIB_AVAILABLE_IN_ALL
GMarkupParseContext *g_markup_parse_context_new (const GMarkupParser *parser,
GMarkupParseFlags flags,
gpointer user_data,
GDestroyNotify user_data_dnotify);
GLIB_AVAILABLE_IN_2_36
GMarkupParseContext *g_markup_parse_context_ref (GMarkupParseContext *context);
GLIB_AVAILABLE_IN_2_36
void g_markup_parse_context_unref (GMarkupParseContext *context);
GLIB_AVAILABLE_IN_ALL
void g_markup_parse_context_free (GMarkupParseContext *context);
GLIB_AVAILABLE_IN_ALL
gboolean g_markup_parse_context_parse (GMarkupParseContext *context,
const gchar *text,
gssize text_len,
GError **error);
GLIB_AVAILABLE_IN_ALL
void g_markup_parse_context_push (GMarkupParseContext *context,
const GMarkupParser *parser,
gpointer user_data);
GLIB_AVAILABLE_IN_ALL
gpointer g_markup_parse_context_pop (GMarkupParseContext *context);
GLIB_AVAILABLE_IN_ALL
gboolean g_markup_parse_context_end_parse (GMarkupParseContext *context,
GError **error);
GLIB_AVAILABLE_IN_ALL
const gchar * g_markup_parse_context_get_element (GMarkupParseContext *context);
GLIB_AVAILABLE_IN_ALL
const GSList * g_markup_parse_context_get_element_stack (GMarkupParseContext *context);
/* For user-constructed error messages, has no precise semantics */
GLIB_AVAILABLE_IN_ALL
void g_markup_parse_context_get_position (GMarkupParseContext *context,
gint *line_number,
gint *char_number);
GLIB_AVAILABLE_IN_ALL
gpointer g_markup_parse_context_get_user_data (GMarkupParseContext *context);
/* useful when saving */
GLIB_AVAILABLE_IN_ALL
gchar* g_markup_escape_text (const gchar *text,
gssize length);
GLIB_AVAILABLE_IN_ALL
gchar *g_markup_printf_escaped (const char *format,
...) G_GNUC_PRINTF (1, 2);
GLIB_AVAILABLE_IN_ALL
gchar *g_markup_vprintf_escaped (const char *format,
va_list args) G_GNUC_PRINTF(1, 0);
typedef enum
{
G_MARKUP_COLLECT_INVALID,
G_MARKUP_COLLECT_STRING,
G_MARKUP_COLLECT_STRDUP,
G_MARKUP_COLLECT_BOOLEAN,
G_MARKUP_COLLECT_TRISTATE,
G_MARKUP_COLLECT_OPTIONAL = (1 << 16)
} GMarkupCollectType;
/* useful from start_element */
GLIB_AVAILABLE_IN_ALL
gboolean g_markup_collect_attributes (const gchar *element_name,
const gchar **attribute_names,
const gchar **attribute_values,
GError **error,
GMarkupCollectType first_type,
const gchar *first_attr,
...);
G_END_DECLS
#endif /* __G_MARKUP_H__ */
pkg-config-0.29.1/glib/glib/gshell.c 0000664 0001750 0001750 00000047657 12651243552 014056 0000000 0000000 /* gshell.c - Shell-related utilities
*
* Copyright 2000 Red Hat, Inc.
* g_execvpe implementation based on GNU libc execvp:
* Copyright 1991, 92, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
*
* GLib 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 of the
* License, or (at your option) any later version.
*
* GLib 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 GLib; see the file COPYING.LIB. If not, write
* to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include
#include "gshell.h"
#include "gslist.h"
#include "gstrfuncs.h"
#include "gstring.h"
#include "gtestutils.h"
#include "glibintl.h"
#include "gthread.h"
/**
* SECTION:shell
* @title: Shell-related Utilities
* @short_description: shell-like commandline handling
**/
/**
* G_SHELL_ERROR:
*
* Error domain for shell functions. Errors in this domain will be from
* the #GShellError enumeration. See #GError for information on error
* domains.
**/
/**
* GShellError:
* @G_SHELL_ERROR_BAD_QUOTING: Mismatched or otherwise mangled quoting.
* @G_SHELL_ERROR_EMPTY_STRING: String to be parsed was empty.
* @G_SHELL_ERROR_FAILED: Some other error.
*
* Error codes returned by shell functions.
**/
G_DEFINE_QUARK (g-shell-error-quark, g_shell_error)
/* Single quotes preserve the literal string exactly. escape
* sequences are not allowed; not even \' - if you want a '
* in the quoted text, you have to do something like 'foo'\''bar'
*
* Double quotes allow $ ` " \ and newline to be escaped with backslash.
* Otherwise double quotes preserve things literally.
*/
static gboolean
unquote_string_inplace (gchar* str, gchar** end, GError** err)
{
gchar* dest;
gchar* s;
gchar quote_char;
g_return_val_if_fail(end != NULL, FALSE);
g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
g_return_val_if_fail(str != NULL, FALSE);
dest = s = str;
quote_char = *s;
if (!(*s == '"' || *s == '\''))
{
g_set_error_literal (err,
G_SHELL_ERROR,
G_SHELL_ERROR_BAD_QUOTING,
_("Quoted text doesn't begin with a quotation mark"));
*end = str;
return FALSE;
}
/* Skip the initial quote mark */
++s;
if (quote_char == '"')
{
while (*s)
{
g_assert(s > dest); /* loop invariant */
switch (*s)
{
case '"':
/* End of the string, return now */
*dest = '\0';
++s;
*end = s;
return TRUE;
break;
case '\\':
/* Possible escaped quote or \ */
++s;
switch (*s)
{
case '"':
case '\\':
case '`':
case '$':
case '\n':
*dest = *s;
++s;
++dest;
break;
default:
/* not an escaped char */
*dest = '\\';
++dest;
/* ++s already done. */
break;
}
break;
default:
*dest = *s;
++dest;
++s;
break;
}
g_assert(s > dest); /* loop invariant */
}
}
else
{
while (*s)
{
g_assert(s > dest); /* loop invariant */
if (*s == '\'')
{
/* End of the string, return now */
*dest = '\0';
++s;
*end = s;
return TRUE;
}
else
{
*dest = *s;
++dest;
++s;
}
g_assert(s > dest); /* loop invariant */
}
}
/* If we reach here this means the close quote was never encountered */
*dest = '\0';
g_set_error_literal (err,
G_SHELL_ERROR,
G_SHELL_ERROR_BAD_QUOTING,
_("Unmatched quotation mark in command line or other shell-quoted text"));
*end = s;
return FALSE;
}
/**
* g_shell_quote:
* @unquoted_string: a literal string
*
* Quotes a string so that the shell (/bin/sh) will interpret the
* quoted string to mean @unquoted_string. If you pass a filename to
* the shell, for example, you should first quote it with this
* function. The return value must be freed with g_free(). The
* quoting style used is undefined (single or double quotes may be
* used).
*
* Return value: quoted string
**/
gchar*
g_shell_quote (const gchar *unquoted_string)
{
/* We always use single quotes, because the algorithm is cheesier.
* We could use double if we felt like it, that might be more
* human-readable.
*/
const gchar *p;
GString *dest;
g_return_val_if_fail (unquoted_string != NULL, NULL);
dest = g_string_new ("'");
p = unquoted_string;
/* could speed this up a lot by appending chunks of text at a
* time.
*/
while (*p)
{
/* Replace literal ' with a close ', a \', and a open ' */
if (*p == '\'')
g_string_append (dest, "'\\''");
else
g_string_append_c (dest, *p);
++p;
}
/* close the quote */
g_string_append_c (dest, '\'');
return g_string_free (dest, FALSE);
}
/**
* g_shell_unquote:
* @quoted_string: shell-quoted string
* @error: error return location or NULL
*
* Unquotes a string as the shell (/bin/sh) would. Only handles
* quotes; if a string contains file globs, arithmetic operators,
* variables, backticks, redirections, or other special-to-the-shell
* features, the result will be different from the result a real shell
* would produce (the variables, backticks, etc. will be passed
* through literally instead of being expanded). This function is
* guaranteed to succeed if applied to the result of
* g_shell_quote(). If it fails, it returns %NULL and sets the
* error. The @quoted_string need not actually contain quoted or
* escaped text; g_shell_unquote() simply goes through the string and
* unquotes/unescapes anything that the shell would. Both single and
* double quotes are handled, as are escapes including escaped
* newlines. The return value must be freed with g_free(). Possible
* errors are in the #G_SHELL_ERROR domain.
*
* Shell quoting rules are a bit strange. Single quotes preserve the
* literal string exactly. escape sequences are not allowed; not even
* \' - if you want a ' in the quoted text, you have to do something
* like 'foo'\''bar'. Double quotes allow $, `, ", \, and newline to
* be escaped with backslash. Otherwise double quotes preserve things
* literally.
*
* Return value: an unquoted string
**/
gchar*
g_shell_unquote (const gchar *quoted_string,
GError **error)
{
gchar *unquoted;
gchar *end;
gchar *start;
GString *retval;
g_return_val_if_fail (quoted_string != NULL, NULL);
unquoted = g_strdup (quoted_string);
start = unquoted;
end = unquoted;
retval = g_string_new (NULL);
/* The loop allows cases such as
* "foo"blah blah'bar'woo foo"baz"la la la\'\''foo'
*/
while (*start)
{
/* Append all non-quoted chars, honoring backslash escape
*/
while (*start && !(*start == '"' || *start == '\''))
{
if (*start == '\\')
{
/* all characters can get escaped by backslash,
* except newline, which is removed if it follows
* a backslash outside of quotes
*/
++start;
if (*start)
{
if (*start != '\n')
g_string_append_c (retval, *start);
++start;
}
}
else
{
g_string_append_c (retval, *start);
++start;
}
}
if (*start)
{
if (!unquote_string_inplace (start, &end, error))
{
goto error;
}
else
{
g_string_append (retval, start);
start = end;
}
}
}
g_free (unquoted);
return g_string_free (retval, FALSE);
error:
g_assert (error == NULL || *error != NULL);
g_free (unquoted);
g_string_free (retval, TRUE);
return NULL;
}
/* g_parse_argv() does a semi-arbitrary weird subset of the way
* the shell parses a command line. We don't do variable expansion,
* don't understand that operators are tokens, don't do tilde expansion,
* don't do command substitution, no arithmetic expansion, IFS gets ignored,
* don't do filename globs, don't remove redirection stuff, etc.
*
* READ THE UNIX98 SPEC on "Shell Command Language" before changing
* the behavior of this code.
*
* Steps to parsing the argv string:
*
* - tokenize the string (but since we ignore operators,
* our tokenization may diverge from what the shell would do)
* note that tokenization ignores the internals of a quoted
* word and it always splits on spaces, not on IFS even
* if we used IFS. We also ignore "end of input indicator"
* (I guess this is control-D?)
*
* Tokenization steps, from UNIX98 with operator stuff removed,
* are:
*
* 1) "If the current character is backslash, single-quote or
* double-quote (\, ' or ") and it is not quoted, it will affect
* quoting for subsequent characters up to the end of the quoted
* text. The rules for quoting are as described in Quoting
* . During token recognition no substitutions will be actually
* performed, and the result token will contain exactly the
* characters that appear in the input (except for newline
* character joining), unmodified, including any embedded or
* enclosing quotes or substitution operators, between the quote
* mark and the end of the quoted text. The token will not be
* delimited by the end of the quoted field."
*
* 2) "If the current character is an unquoted newline character,
* the current token will be delimited."
*
* 3) "If the current character is an unquoted blank character, any
* token containing the previous character is delimited and the
* current character will be discarded."
*
* 4) "If the previous character was part of a word, the current
* character will be appended to that word."
*
* 5) "If the current character is a "#", it and all subsequent
* characters up to, but excluding, the next newline character
* will be discarded as a comment. The newline character that
* ends the line is not considered part of the comment. The
* "#" starts a comment only when it is at the beginning of a
* token. Since the search for the end-of-comment does not
* consider an escaped newline character specially, a comment
* cannot be continued to the next line."
*
* 6) "The current character will be used as the start of a new word."
*
*
* - for each token (word), perform portions of word expansion, namely
* field splitting (using default whitespace IFS) and quote
* removal. Field splitting may increase the number of words.
* Quote removal does not increase the number of words.
*
* "If the complete expansion appropriate for a word results in an
* empty field, that empty field will be deleted from the list of
* fields that form the completely expanded command, unless the
* original word contained single-quote or double-quote characters."
* - UNIX98 spec
*
*
*/
static inline void
ensure_token (GString **token)
{
if (*token == NULL)
*token = g_string_new (NULL);
}
static void
delimit_token (GString **token,
GSList **retval)
{
if (*token == NULL)
return;
*retval = g_slist_prepend (*retval, g_string_free (*token, FALSE));
*token = NULL;
}
static GSList*
tokenize_command_line (const gchar *command_line,
GError **error)
{
gchar current_quote;
const gchar *p;
GString *current_token = NULL;
GSList *retval = NULL;
gboolean quoted;
current_quote = '\0';
quoted = FALSE;
p = command_line;
while (*p)
{
if (current_quote == '\\')
{
if (*p == '\n')
{
/* we append nothing; backslash-newline become nothing */
}
else
{
/* we append the backslash and the current char,
* to be interpreted later after tokenization
*/
ensure_token (¤t_token);
g_string_append_c (current_token, '\\');
g_string_append_c (current_token, *p);
}
current_quote = '\0';
}
else if (current_quote == '#')
{
/* Discard up to and including next newline */
while (*p && *p != '\n')
++p;
current_quote = '\0';
if (*p == '\0')
break;
}
else if (current_quote)
{
if (*p == current_quote &&
/* check that it isn't an escaped double quote */
!(current_quote == '"' && quoted))
{
/* close the quote */
current_quote = '\0';
}
/* Everything inside quotes, and the close quote,
* gets appended literally.
*/
ensure_token (¤t_token);
g_string_append_c (current_token, *p);
}
else
{
switch (*p)
{
case '\n':
delimit_token (¤t_token, &retval);
break;
case ' ':
case '\t':
/* If the current token contains the previous char, delimit
* the current token. A nonzero length
* token should always contain the previous char.
*/
if (current_token &&
current_token->len > 0)
{
delimit_token (¤t_token, &retval);
}
/* discard all unquoted blanks (don't add them to a token) */
break;
/* single/double quotes are appended to the token,
* escapes are maybe appended next time through the loop,
* comment chars are never appended.
*/
case '\'':
case '"':
ensure_token (¤t_token);
g_string_append_c (current_token, *p);
/* FALL THRU */
case '\\':
current_quote = *p;
break;
case '#':
if (p == command_line)
{ /* '#' was the first char */
current_quote = *p;
break;
}
switch(*(p-1))
{
case ' ':
case '\n':
case '\0':
current_quote = *p;
break;
default:
ensure_token (¤t_token);
g_string_append_c (current_token, *p);
break;
}
break;
default:
/* Combines rules 4) and 6) - if we have a token, append to it,
* otherwise create a new token.
*/
ensure_token (¤t_token);
g_string_append_c (current_token, *p);
break;
}
}
/* We need to count consecutive backslashes mod 2,
* to detect escaped doublequotes.
*/
if (*p != '\\')
quoted = FALSE;
else
quoted = !quoted;
++p;
}
delimit_token (¤t_token, &retval);
if (current_quote)
{
if (current_quote == '\\')
g_set_error (error,
G_SHELL_ERROR,
G_SHELL_ERROR_BAD_QUOTING,
_("Text ended just after a '\\' character."
" (The text was '%s')"),
command_line);
else
g_set_error (error,
G_SHELL_ERROR,
G_SHELL_ERROR_BAD_QUOTING,
_("Text ended before matching quote was found for %c."
" (The text was '%s')"),
current_quote, command_line);
goto error;
}
if (retval == NULL)
{
g_set_error_literal (error,
G_SHELL_ERROR,
G_SHELL_ERROR_EMPTY_STRING,
_("Text was empty (or contained only whitespace)"));
goto error;
}
/* we appended backward */
retval = g_slist_reverse (retval);
return retval;
error:
g_assert (error == NULL || *error != NULL);
g_slist_free_full (retval, g_free);
return NULL;
}
/**
* g_shell_parse_argv:
* @command_line: command line to parse
* @argcp: (out): return location for number of args
* @argvp: (out) (array length=argcp zero-terminated=1): return location for array of args
* @error: return location for error
*
* Parses a command line into an argument vector, in much the same way
* the shell would, but without many of the expansions the shell would
* perform (variable expansion, globs, operators, filename expansion,
* etc. are not supported). The results are defined to be the same as
* those you would get from a UNIX98 /bin/sh, as long as the input
* contains none of the unsupported shell expansions. If the input
* does contain such expansions, they are passed through
* literally. Possible errors are those from the #G_SHELL_ERROR
* domain. Free the returned vector with g_strfreev().
*
* Return value: %TRUE on success, %FALSE if error set
**/
gboolean
g_shell_parse_argv (const gchar *command_line,
gint *argcp,
gchar ***argvp,
GError **error)
{
/* Code based on poptParseArgvString() from libpopt */
gint argc = 0;
gchar **argv = NULL;
GSList *tokens = NULL;
gint i;
GSList *tmp_list;
g_return_val_if_fail (command_line != NULL, FALSE);
tokens = tokenize_command_line (command_line, error);
if (tokens == NULL)
return FALSE;
/* Because we can't have introduced any new blank space into the
* tokens (we didn't do any new expansions), we don't need to
* perform field splitting. If we were going to honor IFS or do any
* expansions, we would have to do field splitting on each word
* here. Also, if we were going to do any expansion we would need to
* remove any zero-length words that didn't contain quotes
* originally; but since there's no expansion we know all words have
* nonzero length, unless they contain quotes.
*
* So, we simply remove quotes, and don't do any field splitting or
* empty word removal, since we know there was no way to introduce
* such things.
*/
argc = g_slist_length (tokens);
argv = g_new0 (gchar*, argc + 1);
i = 0;
tmp_list = tokens;
while (tmp_list)
{
argv[i] = g_shell_unquote (tmp_list->data, error);
/* Since we already checked that quotes matched up in the
* tokenizer, this shouldn't be possible to reach I guess.
*/
if (argv[i] == NULL)
goto failed;
tmp_list = g_slist_next (tmp_list);
++i;
}
g_slist_free_full (tokens, g_free);
if (argcp)
*argcp = argc;
if (argvp)
*argvp = argv;
else
g_strfreev (argv);
return TRUE;
failed:
g_assert (error == NULL || *error != NULL);
g_strfreev (argv);
g_slist_free_full (tokens, g_free);
return FALSE;
}
pkg-config-0.29.1/glib/glib/gdatetime.h 0000664 0001750 0001750 00000027531 12651243552 014535 0000000 0000000 /*
* Copyright (C) 2009-2010 Christian Hergert
* Copyright © 2010 Codethink Limited
*
* This 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
* licence, or (at your option) any later version.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
* USA.
*
* Authors: Christian Hergert
* Thiago Santos
* Emmanuele Bassi
* Ryan Lortie
*/
#ifndef __G_DATE_TIME_H__
#define __G_DATE_TIME_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
G_BEGIN_DECLS
/**
* G_TIME_SPAN_DAY:
*
* Evaluates to a time span of one day.
*
* Since: 2.26
*/
#define G_TIME_SPAN_DAY (G_GINT64_CONSTANT (86400000000))
/**
* G_TIME_SPAN_HOUR:
*
* Evaluates to a time span of one hour.
*
* Since: 2.26
*/
#define G_TIME_SPAN_HOUR (G_GINT64_CONSTANT (3600000000))
/**
* G_TIME_SPAN_MINUTE:
*
* Evaluates to a time span of one minute.
*
* Since: 2.26
*/
#define G_TIME_SPAN_MINUTE (G_GINT64_CONSTANT (60000000))
/**
* G_TIME_SPAN_SECOND:
*
* Evaluates to a time span of one second.
*
* Since: 2.26
*/
#define G_TIME_SPAN_SECOND (G_GINT64_CONSTANT (1000000))
/**
* G_TIME_SPAN_MILLISECOND:
*
* Evaluates to a time span of one millisecond.
*
* Since: 2.26
*/
#define G_TIME_SPAN_MILLISECOND (G_GINT64_CONSTANT (1000))
/**
* GTimeSpan:
*
* A value representing an interval of time, in microseconds.
*
* Since: 2.26
*/
typedef gint64 GTimeSpan;
/**
* GDateTime:
*
* GDateTime is an opaque structure whose members
* cannot be accessed directly.
*
* Since: 2.26
*/
typedef struct _GDateTime GDateTime;
GLIB_AVAILABLE_IN_ALL
void g_date_time_unref (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_ref (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_new_now (GTimeZone *tz);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_new_now_local (void);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_new_now_utc (void);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_new_from_unix_local (gint64 t);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_new_from_unix_utc (gint64 t);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_new_from_timeval_local (const GTimeVal *tv);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_new_from_timeval_utc (const GTimeVal *tv);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_new (GTimeZone *tz,
gint year,
gint month,
gint day,
gint hour,
gint minute,
gdouble seconds);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_new_local (gint year,
gint month,
gint day,
gint hour,
gint minute,
gdouble seconds);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_new_utc (gint year,
gint month,
gint day,
gint hour,
gint minute,
gdouble seconds);
GLIB_AVAILABLE_IN_ALL
G_GNUC_WARN_UNUSED_RESULT
GDateTime * g_date_time_add (GDateTime *datetime,
GTimeSpan timespan);
GLIB_AVAILABLE_IN_ALL
G_GNUC_WARN_UNUSED_RESULT
GDateTime * g_date_time_add_years (GDateTime *datetime,
gint years);
GLIB_AVAILABLE_IN_ALL
G_GNUC_WARN_UNUSED_RESULT
GDateTime * g_date_time_add_months (GDateTime *datetime,
gint months);
GLIB_AVAILABLE_IN_ALL
G_GNUC_WARN_UNUSED_RESULT
GDateTime * g_date_time_add_weeks (GDateTime *datetime,
gint weeks);
GLIB_AVAILABLE_IN_ALL
G_GNUC_WARN_UNUSED_RESULT
GDateTime * g_date_time_add_days (GDateTime *datetime,
gint days);
GLIB_AVAILABLE_IN_ALL
G_GNUC_WARN_UNUSED_RESULT
GDateTime * g_date_time_add_hours (GDateTime *datetime,
gint hours);
GLIB_AVAILABLE_IN_ALL
G_GNUC_WARN_UNUSED_RESULT
GDateTime * g_date_time_add_minutes (GDateTime *datetime,
gint minutes);
GLIB_AVAILABLE_IN_ALL
G_GNUC_WARN_UNUSED_RESULT
GDateTime * g_date_time_add_seconds (GDateTime *datetime,
gdouble seconds);
GLIB_AVAILABLE_IN_ALL
G_GNUC_WARN_UNUSED_RESULT
GDateTime * g_date_time_add_full (GDateTime *datetime,
gint years,
gint months,
gint days,
gint hours,
gint minutes,
gdouble seconds);
GLIB_AVAILABLE_IN_ALL
gint g_date_time_compare (gconstpointer dt1,
gconstpointer dt2);
GLIB_AVAILABLE_IN_ALL
GTimeSpan g_date_time_difference (GDateTime *end,
GDateTime *begin);
GLIB_AVAILABLE_IN_ALL
guint g_date_time_hash (gconstpointer datetime);
GLIB_AVAILABLE_IN_ALL
gboolean g_date_time_equal (gconstpointer dt1,
gconstpointer dt2);
GLIB_AVAILABLE_IN_ALL
void g_date_time_get_ymd (GDateTime *datetime,
gint *year,
gint *month,
gint *day);
GLIB_AVAILABLE_IN_ALL
gint g_date_time_get_year (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gint g_date_time_get_month (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gint g_date_time_get_day_of_month (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gint g_date_time_get_week_numbering_year (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gint g_date_time_get_week_of_year (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gint g_date_time_get_day_of_week (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gint g_date_time_get_day_of_year (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gint g_date_time_get_hour (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gint g_date_time_get_minute (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gint g_date_time_get_second (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gint g_date_time_get_microsecond (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gdouble g_date_time_get_seconds (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gint64 g_date_time_to_unix (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gboolean g_date_time_to_timeval (GDateTime *datetime,
GTimeVal *tv);
GLIB_AVAILABLE_IN_ALL
GTimeSpan g_date_time_get_utc_offset (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
const gchar * g_date_time_get_timezone_abbreviation (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gboolean g_date_time_is_daylight_savings (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_to_timezone (GDateTime *datetime,
GTimeZone *tz);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_to_local (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
GDateTime * g_date_time_to_utc (GDateTime *datetime);
GLIB_AVAILABLE_IN_ALL
gchar * g_date_time_format (GDateTime *datetime,
const gchar *format) G_GNUC_MALLOC;
G_END_DECLS
#endif /* __G_DATE_TIME_H__ */
pkg-config-0.29.1/glib/glib/gthread-win32.c 0000664 0001750 0001750 00000062621 12651243552 015142 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* gthread.c: solaris thread system implementation
* Copyright 1998-2001 Sebastian Wilhelmi; University of Karlsruhe
* Copyright 2001 Hans Breuer
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
/* The GMutex and GCond implementations in this file are some of the
* lowest-level code in GLib. All other parts of GLib (messages,
* memory, slices, etc) assume that they can freely use these facilities
* without risking recursion.
*
* As such, these functions are NOT permitted to call any other part of
* GLib.
*
* The thread manipulation functions (create, exit, join, etc.) have
* more freedom -- they can do as they please.
*/
#include "config.h"
#include "glib.h"
#include "glib-init.h"
#include "gthread.h"
#include "gthreadprivate.h"
#include "gslice.h"
#include
#include
#include
#include
static void
g_thread_abort (gint status,
const gchar *function)
{
fprintf (stderr, "GLib (gthread-win32.c): Unexpected error from C library during '%s': %s. Aborting.\n",
strerror (status), function);
abort ();
}
/* Starting with Vista and Windows 2008, we have access to the
* CONDITION_VARIABLE and SRWLock primatives on Windows, which are
* pretty reasonable approximations of the primatives specified in
* POSIX 2001 (pthread_cond_t and pthread_mutex_t respectively).
*
* Both of these types are structs containing a single pointer. That
* pointer is used as an atomic bitfield to support user-space mutexes
* that only get the kernel involved in cases of contention (similar
* to how futex()-based mutexes work on Linux). The biggest advantage
* of these new types is that they can be statically initialised to
* zero. That means that they are completely ABI compatible with our
* GMutex and GCond APIs.
*
* Unfortunately, Windows XP lacks these facilities and GLib still
* needs to support Windows XP. Our approach here is as follows:
*
* - avoid depending on structure declarations at compile-time by
* declaring our own GMutex and GCond strutures to be
* ABI-compatible with SRWLock and CONDITION_VARIABLE and using
* those instead
*
* - avoid a hard dependency on the symbols used to manipulate these
* structures by doing a dynamic lookup of those symbols at
* runtime
*
* - if the symbols are not available, emulate them using other
* primatives
*
* Using this approach also allows us to easily build a GLib that lacks
* support for Windows XP or to remove this code entirely when XP is no
* longer supported (end of line is currently April 8, 2014).
*/
typedef struct
{
void (__stdcall * CallThisOnThreadExit) (void); /* fake */
void (__stdcall * InitializeSRWLock) (gpointer lock);
void (__stdcall * DeleteSRWLock) (gpointer lock); /* fake */
void (__stdcall * AcquireSRWLockExclusive) (gpointer lock);
BOOLEAN (__stdcall * TryAcquireSRWLockExclusive) (gpointer lock);
void (__stdcall * ReleaseSRWLockExclusive) (gpointer lock);
void (__stdcall * AcquireSRWLockShared) (gpointer lock);
BOOLEAN (__stdcall * TryAcquireSRWLockShared) (gpointer lock);
void (__stdcall * ReleaseSRWLockShared) (gpointer lock);
void (__stdcall * InitializeConditionVariable) (gpointer cond);
void (__stdcall * DeleteConditionVariable) (gpointer cond); /* fake */
BOOL (__stdcall * SleepConditionVariableSRW) (gpointer cond,
gpointer lock,
DWORD timeout,
ULONG flags);
void (__stdcall * WakeAllConditionVariable) (gpointer cond);
void (__stdcall * WakeConditionVariable) (gpointer cond);
} GThreadImplVtable;
static GThreadImplVtable g_thread_impl_vtable;
/* {{{1 GMutex */
void
g_mutex_init (GMutex *mutex)
{
g_thread_impl_vtable.InitializeSRWLock (mutex);
}
void
g_mutex_clear (GMutex *mutex)
{
if (g_thread_impl_vtable.DeleteSRWLock != NULL)
g_thread_impl_vtable.DeleteSRWLock (mutex);
}
void
g_mutex_lock (GMutex *mutex)
{
g_thread_impl_vtable.AcquireSRWLockExclusive (mutex);
}
gboolean
g_mutex_trylock (GMutex *mutex)
{
return g_thread_impl_vtable.TryAcquireSRWLockExclusive (mutex);
}
void
g_mutex_unlock (GMutex *mutex)
{
g_thread_impl_vtable.ReleaseSRWLockExclusive (mutex);
}
/* {{{1 GRecMutex */
static CRITICAL_SECTION *
g_rec_mutex_impl_new (void)
{
CRITICAL_SECTION *cs;
cs = g_slice_new (CRITICAL_SECTION);
InitializeCriticalSection (cs);
return cs;
}
static void
g_rec_mutex_impl_free (CRITICAL_SECTION *cs)
{
DeleteCriticalSection (cs);
g_slice_free (CRITICAL_SECTION, cs);
}
static CRITICAL_SECTION *
g_rec_mutex_get_impl (GRecMutex *mutex)
{
CRITICAL_SECTION *impl = mutex->p;
if G_UNLIKELY (mutex->p == NULL)
{
impl = g_rec_mutex_impl_new ();
if (InterlockedCompareExchangePointer (&mutex->p, impl, NULL) != NULL)
g_rec_mutex_impl_free (impl);
impl = mutex->p;
}
return impl;
}
void
g_rec_mutex_init (GRecMutex *mutex)
{
mutex->p = g_rec_mutex_impl_new ();
}
void
g_rec_mutex_clear (GRecMutex *mutex)
{
g_rec_mutex_impl_free (mutex->p);
}
void
g_rec_mutex_lock (GRecMutex *mutex)
{
EnterCriticalSection (g_rec_mutex_get_impl (mutex));
}
void
g_rec_mutex_unlock (GRecMutex *mutex)
{
LeaveCriticalSection (mutex->p);
}
gboolean
g_rec_mutex_trylock (GRecMutex *mutex)
{
return TryEnterCriticalSection (g_rec_mutex_get_impl (mutex));
}
/* {{{1 GRWLock */
void
g_rw_lock_init (GRWLock *lock)
{
g_thread_impl_vtable.InitializeSRWLock (lock);
}
void
g_rw_lock_clear (GRWLock *lock)
{
if (g_thread_impl_vtable.DeleteSRWLock != NULL)
g_thread_impl_vtable.DeleteSRWLock (lock);
}
void
g_rw_lock_writer_lock (GRWLock *lock)
{
g_thread_impl_vtable.AcquireSRWLockExclusive (lock);
}
gboolean
g_rw_lock_writer_trylock (GRWLock *lock)
{
return g_thread_impl_vtable.TryAcquireSRWLockExclusive (lock);
}
void
g_rw_lock_writer_unlock (GRWLock *lock)
{
g_thread_impl_vtable.ReleaseSRWLockExclusive (lock);
}
void
g_rw_lock_reader_lock (GRWLock *lock)
{
g_thread_impl_vtable.AcquireSRWLockShared (lock);
}
gboolean
g_rw_lock_reader_trylock (GRWLock *lock)
{
return g_thread_impl_vtable.TryAcquireSRWLockShared (lock);
}
void
g_rw_lock_reader_unlock (GRWLock *lock)
{
g_thread_impl_vtable.ReleaseSRWLockShared (lock);
}
/* {{{1 GCond */
void
g_cond_init (GCond *cond)
{
g_thread_impl_vtable.InitializeConditionVariable (cond);
}
void
g_cond_clear (GCond *cond)
{
if (g_thread_impl_vtable.DeleteConditionVariable)
g_thread_impl_vtable.DeleteConditionVariable (cond);
}
void
g_cond_signal (GCond *cond)
{
g_thread_impl_vtable.WakeConditionVariable (cond);
}
void
g_cond_broadcast (GCond *cond)
{
g_thread_impl_vtable.WakeAllConditionVariable (cond);
}
void
g_cond_wait (GCond *cond,
GMutex *entered_mutex)
{
g_thread_impl_vtable.SleepConditionVariableSRW (cond, entered_mutex, INFINITE, 0);
}
gboolean
g_cond_wait_until (GCond *cond,
GMutex *entered_mutex,
gint64 end_time)
{
gint64 span;
span = end_time - g_get_monotonic_time ();
if G_UNLIKELY (span < 0)
span = 0;
if G_UNLIKELY (span > G_GINT64_CONSTANT (1000) * G_MAXINT32)
span = INFINITE;
return g_thread_impl_vtable.SleepConditionVariableSRW (cond, entered_mutex, span / 1000, 0);
}
/* {{{1 GPrivate */
typedef struct _GPrivateDestructor GPrivateDestructor;
struct _GPrivateDestructor
{
DWORD index;
GDestroyNotify notify;
GPrivateDestructor *next;
};
static GPrivateDestructor * volatile g_private_destructors;
static CRITICAL_SECTION g_private_lock;
static DWORD
g_private_get_impl (GPrivate *key)
{
DWORD impl = (DWORD) key->p;
if G_UNLIKELY (impl == 0)
{
EnterCriticalSection (&g_private_lock);
impl = (DWORD) key->p;
if (impl == 0)
{
GPrivateDestructor *destructor;
impl = TlsAlloc ();
if (impl == TLS_OUT_OF_INDEXES)
g_thread_abort (0, "TlsAlloc");
if (key->notify != NULL)
{
destructor = malloc (sizeof (GPrivateDestructor));
if G_UNLIKELY (destructor == NULL)
g_thread_abort (errno, "malloc");
destructor->index = impl;
destructor->notify = key->notify;
destructor->next = g_private_destructors;
/* We need to do an atomic store due to the unlocked
* access to the destructor list from the thread exit
* function.
*
* It can double as a sanity check...
*/
if (InterlockedCompareExchangePointer (&g_private_destructors, destructor,
destructor->next) != destructor->next)
g_thread_abort (0, "g_private_get_impl(1)");
}
/* Ditto, due to the unlocked access on the fast path */
if (InterlockedCompareExchangePointer (&key->p, impl, NULL) != NULL)
g_thread_abort (0, "g_private_get_impl(2)");
}
LeaveCriticalSection (&g_private_lock);
}
return impl;
}
gpointer
g_private_get (GPrivate *key)
{
return TlsGetValue (g_private_get_impl (key));
}
void
g_private_set (GPrivate *key,
gpointer value)
{
TlsSetValue (g_private_get_impl (key), value);
}
void
g_private_replace (GPrivate *key,
gpointer value)
{
DWORD impl = g_private_get_impl (key);
gpointer old;
old = TlsGetValue (impl);
if (old && key->notify)
key->notify (old);
TlsSetValue (impl, value);
}
/* {{{1 GThread */
#define win32_check_for_error(what) G_STMT_START{ \
if (!(what)) \
g_error ("file %s: line %d (%s): error %s during %s", \
__FILE__, __LINE__, G_STRFUNC, \
g_win32_error_message (GetLastError ()), #what); \
}G_STMT_END
#define G_MUTEX_SIZE (sizeof (gpointer))
typedef BOOL (__stdcall *GTryEnterCriticalSectionFunc) (CRITICAL_SECTION *);
typedef struct
{
GRealThread thread;
GThreadFunc proxy;
HANDLE handle;
} GThreadWin32;
void
g_system_thread_free (GRealThread *thread)
{
GThreadWin32 *wt = (GThreadWin32 *) thread;
win32_check_for_error (CloseHandle (wt->handle));
g_slice_free (GThreadWin32, wt);
}
void
g_system_thread_exit (void)
{
_endthreadex (0);
}
static guint __stdcall
g_thread_win32_proxy (gpointer data)
{
GThreadWin32 *self = data;
self->proxy (self);
g_system_thread_exit ();
g_assert_not_reached ();
return 0;
}
GRealThread *
g_system_thread_new (GThreadFunc func,
gulong stack_size,
GError **error)
{
GThreadWin32 *thread;
guint ignore;
thread = g_slice_new0 (GThreadWin32);
thread->proxy = func;
thread->handle = (HANDLE) _beginthreadex (NULL, stack_size, g_thread_win32_proxy, thread, 0, &ignore);
if (thread->handle == NULL)
{
gchar *win_error = g_win32_error_message (GetLastError ());
g_set_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN,
"Error creating thread: %s", win_error);
g_free (win_error);
g_slice_free (GThreadWin32, thread);
return NULL;
}
return (GRealThread *) thread;
}
void
g_thread_yield (void)
{
Sleep(0);
}
void
g_system_thread_wait (GRealThread *thread)
{
GThreadWin32 *wt = (GThreadWin32 *) thread;
win32_check_for_error (WAIT_FAILED != WaitForSingleObject (wt->handle, INFINITE));
}
void
g_system_thread_set_name (const gchar *name)
{
/* FIXME: implement */
}
/* {{{1 SRWLock and CONDITION_VARIABLE emulation (for Windows XP) */
static CRITICAL_SECTION g_thread_xp_lock;
static DWORD g_thread_xp_waiter_tls;
/* {{{2 GThreadWaiter utility class for CONDITION_VARIABLE emulation */
typedef struct _GThreadXpWaiter GThreadXpWaiter;
struct _GThreadXpWaiter
{
HANDLE event;
volatile GThreadXpWaiter *next;
volatile GThreadXpWaiter **my_owner;
};
static GThreadXpWaiter *
g_thread_xp_waiter_get (void)
{
GThreadXpWaiter *waiter;
waiter = TlsGetValue (g_thread_xp_waiter_tls);
if G_UNLIKELY (waiter == NULL)
{
waiter = malloc (sizeof (GThreadXpWaiter));
if (waiter == NULL)
g_thread_abort (GetLastError (), "malloc");
waiter->event = CreateEvent (0, FALSE, FALSE, NULL);
if (waiter->event == NULL)
g_thread_abort (GetLastError (), "CreateEvent");
waiter->my_owner = NULL;
TlsSetValue (g_thread_xp_waiter_tls, waiter);
}
return waiter;
}
static void __stdcall
g_thread_xp_CallThisOnThreadExit (void)
{
GThreadXpWaiter *waiter;
waiter = TlsGetValue (g_thread_xp_waiter_tls);
if (waiter != NULL)
{
TlsSetValue (g_thread_xp_waiter_tls, NULL);
CloseHandle (waiter->event);
free (waiter);
}
}
/* {{{2 SRWLock emulation */
typedef struct
{
CRITICAL_SECTION writer_lock;
gboolean ever_shared; /* protected by writer_lock */
gboolean writer_locked; /* protected by writer_lock */
/* below is only ever touched if ever_shared becomes true */
CRITICAL_SECTION atomicity;
GThreadXpWaiter *queued_writer; /* protected by atomicity lock */
gint num_readers; /* protected by atomicity lock */
} GThreadSRWLock;
static void __stdcall
g_thread_xp_InitializeSRWLock (gpointer mutex)
{
*(GThreadSRWLock * volatile *) mutex = NULL;
}
static void __stdcall
g_thread_xp_DeleteSRWLock (gpointer mutex)
{
GThreadSRWLock *lock = *(GThreadSRWLock * volatile *) mutex;
if (lock)
{
if (lock->ever_shared)
DeleteCriticalSection (&lock->atomicity);
DeleteCriticalSection (&lock->writer_lock);
free (lock);
}
}
static GThreadSRWLock * __stdcall
g_thread_xp_get_srwlock (GThreadSRWLock * volatile *lock)
{
GThreadSRWLock *result;
/* It looks like we're missing some barriers here, but this code only
* ever runs on Windows XP, which in turn only ever runs on hardware
* with a relatively rigid memory model. The 'volatile' will take
* care of the compiler.
*/
result = *lock;
if G_UNLIKELY (result == NULL)
{
EnterCriticalSection (&g_thread_xp_lock);
/* Check again */
result = *lock;
if (result == NULL)
{
result = malloc (sizeof (GThreadSRWLock));
if (result == NULL)
g_thread_abort (errno, "malloc");
InitializeCriticalSection (&result->writer_lock);
result->writer_locked = FALSE;
result->ever_shared = FALSE;
*lock = result;
}
LeaveCriticalSection (&g_thread_xp_lock);
}
return result;
}
static void __stdcall
g_thread_xp_AcquireSRWLockExclusive (gpointer mutex)
{
GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
EnterCriticalSection (&lock->writer_lock);
/* CRITICAL_SECTION is reentrant, but SRWLock is not.
* Detect the deadlock that would occur on later Windows version.
*/
g_assert (!lock->writer_locked);
lock->writer_locked = TRUE;
if (lock->ever_shared)
{
GThreadXpWaiter *waiter = NULL;
EnterCriticalSection (&lock->atomicity);
if (lock->num_readers > 0)
lock->queued_writer = waiter = g_thread_xp_waiter_get ();
LeaveCriticalSection (&lock->atomicity);
if (waiter != NULL)
WaitForSingleObject (waiter->event, INFINITE);
lock->queued_writer = NULL;
}
}
static BOOLEAN __stdcall
g_thread_xp_TryAcquireSRWLockExclusive (gpointer mutex)
{
GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
if (!TryEnterCriticalSection (&lock->writer_lock))
return FALSE;
/* CRITICAL_SECTION is reentrant, but SRWLock is not.
* Ensure that this properly returns FALSE (as SRWLock would).
*/
if G_UNLIKELY (lock->writer_locked)
{
LeaveCriticalSection (&lock->writer_lock);
return FALSE;
}
lock->writer_locked = TRUE;
if (lock->ever_shared)
{
gboolean available;
EnterCriticalSection (&lock->atomicity);
available = lock->num_readers == 0;
LeaveCriticalSection (&lock->atomicity);
if (!available)
{
LeaveCriticalSection (&lock->writer_lock);
return FALSE;
}
}
return TRUE;
}
static void __stdcall
g_thread_xp_ReleaseSRWLockExclusive (gpointer mutex)
{
GThreadSRWLock *lock = *(GThreadSRWLock * volatile *) mutex;
lock->writer_locked = FALSE;
/* We need this until we fix some weird parts of GLib that try to
* unlock freshly-allocated mutexes.
*/
if (lock != NULL)
LeaveCriticalSection (&lock->writer_lock);
}
static void
g_thread_xp_srwlock_become_reader (GThreadSRWLock *lock)
{
if G_UNLIKELY (!lock->ever_shared)
{
InitializeCriticalSection (&lock->atomicity);
lock->queued_writer = NULL;
lock->num_readers = 0;
lock->ever_shared = TRUE;
}
EnterCriticalSection (&lock->atomicity);
lock->num_readers++;
LeaveCriticalSection (&lock->atomicity);
}
static void __stdcall
g_thread_xp_AcquireSRWLockShared (gpointer mutex)
{
GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
EnterCriticalSection (&lock->writer_lock);
/* See g_thread_xp_AcquireSRWLockExclusive */
g_assert (!lock->writer_locked);
g_thread_xp_srwlock_become_reader (lock);
LeaveCriticalSection (&lock->writer_lock);
}
static BOOLEAN __stdcall
g_thread_xp_TryAcquireSRWLockShared (gpointer mutex)
{
GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
if (!TryEnterCriticalSection (&lock->writer_lock))
return FALSE;
/* See g_thread_xp_AcquireSRWLockExclusive */
if G_UNLIKELY (lock->writer_locked)
{
LeaveCriticalSection (&lock->writer_lock);
return FALSE;
}
g_thread_xp_srwlock_become_reader (lock);
LeaveCriticalSection (&lock->writer_lock);
return TRUE;
}
static void __stdcall
g_thread_xp_ReleaseSRWLockShared (gpointer mutex)
{
GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
EnterCriticalSection (&lock->atomicity);
lock->num_readers--;
if (lock->num_readers == 0 && lock->queued_writer)
SetEvent (lock->queued_writer->event);
LeaveCriticalSection (&lock->atomicity);
}
/* {{{2 CONDITION_VARIABLE emulation */
typedef struct
{
volatile GThreadXpWaiter *first;
volatile GThreadXpWaiter **last_ptr;
} GThreadXpCONDITION_VARIABLE;
static void __stdcall
g_thread_xp_InitializeConditionVariable (gpointer cond)
{
*(GThreadXpCONDITION_VARIABLE * volatile *) cond = NULL;
}
static void __stdcall
g_thread_xp_DeleteConditionVariable (gpointer cond)
{
GThreadXpCONDITION_VARIABLE *cv = *(GThreadXpCONDITION_VARIABLE * volatile *) cond;
if (cv)
free (cv);
}
static GThreadXpCONDITION_VARIABLE * __stdcall
g_thread_xp_get_condition_variable (GThreadXpCONDITION_VARIABLE * volatile *cond)
{
GThreadXpCONDITION_VARIABLE *result;
/* It looks like we're missing some barriers here, but this code only
* ever runs on Windows XP, which in turn only ever runs on hardware
* with a relatively rigid memory model. The 'volatile' will take
* care of the compiler.
*/
result = *cond;
if G_UNLIKELY (result == NULL)
{
result = malloc (sizeof (GThreadXpCONDITION_VARIABLE));
if (result == NULL)
g_thread_abort (errno, "malloc");
result->first = NULL;
result->last_ptr = &result->first;
if (InterlockedCompareExchangePointer (cond, result, NULL) != NULL)
{
free (result);
result = *cond;
}
}
return result;
}
static BOOL __stdcall
g_thread_xp_SleepConditionVariableSRW (gpointer cond,
gpointer mutex,
DWORD timeout,
ULONG flags)
{
GThreadXpCONDITION_VARIABLE *cv = g_thread_xp_get_condition_variable (cond);
GThreadXpWaiter *waiter = g_thread_xp_waiter_get ();
DWORD status;
waiter->next = NULL;
EnterCriticalSection (&g_thread_xp_lock);
waiter->my_owner = cv->last_ptr;
*cv->last_ptr = waiter;
cv->last_ptr = &waiter->next;
LeaveCriticalSection (&g_thread_xp_lock);
g_mutex_unlock (mutex);
status = WaitForSingleObject (waiter->event, timeout);
if (status != WAIT_TIMEOUT && status != WAIT_OBJECT_0)
g_thread_abort (GetLastError (), "WaitForSingleObject");
g_mutex_lock (mutex);
if (status == WAIT_TIMEOUT)
{
EnterCriticalSection (&g_thread_xp_lock);
if (waiter->my_owner)
{
if (waiter->next)
waiter->next->my_owner = waiter->my_owner;
else
cv->last_ptr = waiter->my_owner;
*waiter->my_owner = waiter->next;
waiter->my_owner = NULL;
}
LeaveCriticalSection (&g_thread_xp_lock);
}
return status == WAIT_OBJECT_0;
}
static void __stdcall
g_thread_xp_WakeConditionVariable (gpointer cond)
{
GThreadXpCONDITION_VARIABLE *cv = g_thread_xp_get_condition_variable (cond);
volatile GThreadXpWaiter *waiter;
EnterCriticalSection (&g_thread_xp_lock);
waiter = cv->first;
if (waiter != NULL)
{
waiter->my_owner = NULL;
cv->first = waiter->next;
if (cv->first != NULL)
cv->first->my_owner = &cv->first;
else
cv->last_ptr = &cv->first;
}
if (waiter != NULL)
SetEvent (waiter->event);
LeaveCriticalSection (&g_thread_xp_lock);
}
static void __stdcall
g_thread_xp_WakeAllConditionVariable (gpointer cond)
{
GThreadXpCONDITION_VARIABLE *cv = g_thread_xp_get_condition_variable (cond);
volatile GThreadXpWaiter *waiter;
EnterCriticalSection (&g_thread_xp_lock);
waiter = cv->first;
cv->first = NULL;
cv->last_ptr = &cv->first;
while (waiter != NULL)
{
volatile GThreadXpWaiter *next;
next = waiter->next;
SetEvent (waiter->event);
waiter->my_owner = NULL;
waiter = next;
}
LeaveCriticalSection (&g_thread_xp_lock);
}
/* {{{2 XP Setup */
static void
g_thread_xp_init (void)
{
static const GThreadImplVtable g_thread_xp_impl_vtable = {
g_thread_xp_CallThisOnThreadExit,
g_thread_xp_InitializeSRWLock,
g_thread_xp_DeleteSRWLock,
g_thread_xp_AcquireSRWLockExclusive,
g_thread_xp_TryAcquireSRWLockExclusive,
g_thread_xp_ReleaseSRWLockExclusive,
g_thread_xp_AcquireSRWLockShared,
g_thread_xp_TryAcquireSRWLockShared,
g_thread_xp_ReleaseSRWLockShared,
g_thread_xp_InitializeConditionVariable,
g_thread_xp_DeleteConditionVariable,
g_thread_xp_SleepConditionVariableSRW,
g_thread_xp_WakeAllConditionVariable,
g_thread_xp_WakeConditionVariable
};
InitializeCriticalSection (&g_thread_xp_lock);
g_thread_xp_waiter_tls = TlsAlloc ();
g_thread_impl_vtable = g_thread_xp_impl_vtable;
}
/* {{{1 Epilogue */
static gboolean
g_thread_lookup_native_funcs (void)
{
GThreadImplVtable native_vtable = { 0, };
HMODULE kernel32;
kernel32 = GetModuleHandle ("KERNEL32.DLL");
if (kernel32 == NULL)
return FALSE;
#define GET_FUNC(name) if ((native_vtable.name = (void *) GetProcAddress (kernel32, #name)) == NULL) return FALSE
GET_FUNC(InitializeSRWLock);
GET_FUNC(AcquireSRWLockExclusive);
GET_FUNC(TryAcquireSRWLockExclusive);
GET_FUNC(ReleaseSRWLockExclusive);
GET_FUNC(AcquireSRWLockShared);
GET_FUNC(TryAcquireSRWLockShared);
GET_FUNC(ReleaseSRWLockShared);
GET_FUNC(InitializeConditionVariable);
GET_FUNC(SleepConditionVariableSRW);
GET_FUNC(WakeAllConditionVariable);
GET_FUNC(WakeConditionVariable);
#undef GET_FUNC
g_thread_impl_vtable = native_vtable;
return TRUE;
}
void
g_thread_win32_init (void)
{
if (!g_thread_lookup_native_funcs ())
g_thread_xp_init ();
InitializeCriticalSection (&g_private_lock);
}
void
g_thread_win32_thread_detach (void)
{
gboolean dtors_called;
do
{
GPrivateDestructor *dtor;
/* We go by the POSIX book on this one.
*
* If we call a destructor then there is a chance that some new
* TLS variables got set by code called in that destructor.
*
* Loop until nothing is left.
*/
dtors_called = FALSE;
for (dtor = g_private_destructors; dtor; dtor = dtor->next)
{
gpointer value;
value = TlsGetValue (dtor->index);
if (value != NULL && dtor->notify != NULL)
{
/* POSIX says to clear this before the call */
TlsSetValue (dtor->index, NULL);
dtor->notify (value);
dtors_called = TRUE;
}
}
}
while (dtors_called);
if (g_thread_impl_vtable.CallThisOnThreadExit)
g_thread_impl_vtable.CallThisOnThreadExit ();
}
/* vim:set foldmethod=marker: */
pkg-config-0.29.1/glib/glib/gsequence.c 0000664 0001750 0001750 00000141724 12651243552 014545 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
* Soeren Sandmann (sandmann@daimi.au.dk)
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gsequence.h"
#include "gmem.h"
#include "gtestutils.h"
#include "gslice.h"
/**
* SECTION:sequence
* @title: Sequences
* @short_description: scalable lists
*
* The #GSequence data structure has the API of a list, but is
* implemented internally with a balanced binary tree. This means that
* it is possible to maintain a sorted list of n elements in time O(n
* log n). The data contained in each element can be either integer
* values, by using of the Type Conversion Macros,
* or simply pointers to any type of data.
*
* A #GSequence is accessed through iterators,
* represented by a #GSequenceIter. An iterator represents a position
* between two elements of the sequence. For example, the
* begin iterator represents the gap immediately
* before the first element of the sequence, and the
* end iterator represents the gap immediately
* after the last element. In an empty sequence, the begin and end
* iterators are the same.
*
* Some methods on #GSequence operate on ranges of items. For example
* g_sequence_foreach_range() will call a user-specified function on
* each element with the given range. The range is delimited by the
* gaps represented by the passed-in iterators, so if you pass in the
* begin and end iterators, the range in question is the entire
* sequence.
*
* The function g_sequence_get() is used with an iterator to access the
* element immediately following the gap that the iterator represents.
* The iterator is said to point to that element.
*
* Iterators are stable across most operations on a #GSequence. For
* example an iterator pointing to some element of a sequence will
* continue to point to that element even after the sequence is sorted.
* Even moving an element to another sequence using for example
* g_sequence_move_range() will not invalidate the iterators pointing
* to it. The only operation that will invalidate an iterator is when
* the element it points to is removed from any sequence.
**/
/**
* GSequenceIter:
*
* The #GSequenceIter struct is an opaque data type representing an
* iterator pointing into a #GSequence.
**/
/**
* GSequenceIterCompareFunc:
* @a: a #GSequenceIter
* @b: a #GSequenceIter
* @data: user data
*
* A #GSequenceIterCompareFunc is a function used to compare iterators.
* It must return zero if the iterators compare equal, a negative value
* if @a comes before @b, and a positive value if @b comes before @a.
*
* Returns: zero if the iterators are equal, a negative value if @a
* comes before @b, and a positive value if @b comes before
* @a.
**/
typedef struct _GSequenceNode GSequenceNode;
/**
* GSequence:
*
* The #GSequence struct is an opaque data type representing a
* Sequence data type.
**/
struct _GSequence
{
GSequenceNode * end_node;
GDestroyNotify data_destroy_notify;
gboolean access_prohibited;
/* The 'real_sequence' is used when temporary sequences are created
* to hold nodes that are being rearranged. The 'real_sequence' of such
* a temporary sequence points to the sequence that is actually being
* manipulated. The only reason we need this is so that when the
* sort/sort_changed/search_iter() functions call out to the application
* g_sequence_iter_get_sequence() will return the correct sequence.
*/
GSequence * real_sequence;
};
struct _GSequenceNode
{
gint n_nodes;
GSequenceNode * parent;
GSequenceNode * left;
GSequenceNode * right;
gpointer data; /* For the end node, this field points
* to the sequence
*/
};
/*
* Declaration of GSequenceNode methods
*/
static GSequenceNode *node_new (gpointer data);
static GSequenceNode *node_get_first (GSequenceNode *node);
static GSequenceNode *node_get_last (GSequenceNode *node);
static GSequenceNode *node_get_prev (GSequenceNode *node);
static GSequenceNode *node_get_next (GSequenceNode *node);
static gint node_get_pos (GSequenceNode *node);
static GSequenceNode *node_get_by_pos (GSequenceNode *node,
gint pos);
static GSequenceNode *node_find (GSequenceNode *haystack,
GSequenceNode *needle,
GSequenceNode *end,
GSequenceIterCompareFunc cmp,
gpointer user_data);
static GSequenceNode *node_find_closest (GSequenceNode *haystack,
GSequenceNode *needle,
GSequenceNode *end,
GSequenceIterCompareFunc cmp,
gpointer user_data);
static gint node_get_length (GSequenceNode *node);
static void node_free (GSequenceNode *node,
GSequence *seq);
static void node_cut (GSequenceNode *split);
static void node_insert_before (GSequenceNode *node,
GSequenceNode *new);
static void node_unlink (GSequenceNode *node);
static void node_join (GSequenceNode *left,
GSequenceNode *right);
static void node_insert_sorted (GSequenceNode *node,
GSequenceNode *new,
GSequenceNode *end,
GSequenceIterCompareFunc cmp_func,
gpointer cmp_data);
/*
* Various helper functions
*/
static void
check_seq_access (GSequence *seq)
{
if (G_UNLIKELY (seq->access_prohibited))
{
g_warning ("Accessing a sequence while it is "
"being sorted or searched is not allowed");
}
}
static GSequence *
get_sequence (GSequenceNode *node)
{
return (GSequence *)node_get_last (node)->data;
}
static void
check_iter_access (GSequenceIter *iter)
{
check_seq_access (get_sequence (iter));
}
static gboolean
is_end (GSequenceIter *iter)
{
GSequence *seq;
if (iter->right)
return FALSE;
if (!iter->parent)
return TRUE;
if (iter->parent->right != iter)
return FALSE;
seq = get_sequence (iter);
return seq->end_node == iter;
}
typedef struct
{
GCompareDataFunc cmp_func;
gpointer cmp_data;
GSequenceNode *end_node;
} SortInfo;
/* This function compares two iters using a normal compare
* function and user_data passed in in a SortInfo struct
*/
static gint
iter_compare (GSequenceIter *node1,
GSequenceIter *node2,
gpointer data)
{
const SortInfo *info = data;
gint retval;
if (node1 == info->end_node)
return 1;
if (node2 == info->end_node)
return -1;
retval = info->cmp_func (node1->data, node2->data, info->cmp_data);
return retval;
}
/*
* Public API
*/
/**
* g_sequence_new:
* @data_destroy: (allow-none): a #GDestroyNotify function, or %NULL
*
* Creates a new GSequence. The @data_destroy function, if non-%NULL will
* be called on all items when the sequence is destroyed and on items that
* are removed from the sequence.
*
* Return value: a new #GSequence
*
* Since: 2.14
**/
GSequence *
g_sequence_new (GDestroyNotify data_destroy)
{
GSequence *seq = g_new (GSequence, 1);
seq->data_destroy_notify = data_destroy;
seq->end_node = node_new (seq);
seq->access_prohibited = FALSE;
seq->real_sequence = seq;
return seq;
}
/**
* g_sequence_free:
* @seq: a #GSequence
*
* Frees the memory allocated for @seq. If @seq has a data destroy
* function associated with it, that function is called on all items in
* @seq.
*
* Since: 2.14
**/
void
g_sequence_free (GSequence *seq)
{
g_return_if_fail (seq != NULL);
check_seq_access (seq);
node_free (seq->end_node, seq);
g_free (seq);
}
/**
* g_sequence_foreach_range:
* @begin: a #GSequenceIter
* @end: a #GSequenceIter
* @func: a #GFunc
* @user_data: user data passed to @func
*
* Calls @func for each item in the range (@begin, @end) passing
* @user_data to the function.
*
* Since: 2.14
**/
void
g_sequence_foreach_range (GSequenceIter *begin,
GSequenceIter *end,
GFunc func,
gpointer user_data)
{
GSequence *seq;
GSequenceIter *iter;
g_return_if_fail (func != NULL);
g_return_if_fail (begin != NULL);
g_return_if_fail (end != NULL);
seq = get_sequence (begin);
seq->access_prohibited = TRUE;
iter = begin;
while (iter != end)
{
GSequenceIter *next = node_get_next (iter);
func (iter->data, user_data);
iter = next;
}
seq->access_prohibited = FALSE;
}
/**
* g_sequence_foreach:
* @seq: a #GSequence
* @func: the function to call for each item in @seq
* @user_data: user data passed to @func
*
* Calls @func for each item in the sequence passing @user_data
* to the function.
*
* Since: 2.14
**/
void
g_sequence_foreach (GSequence *seq,
GFunc func,
gpointer user_data)
{
GSequenceIter *begin, *end;
check_seq_access (seq);
begin = g_sequence_get_begin_iter (seq);
end = g_sequence_get_end_iter (seq);
g_sequence_foreach_range (begin, end, func, user_data);
}
/**
* g_sequence_range_get_midpoint:
* @begin: a #GSequenceIter
* @end: a #GSequenceIter
*
* Finds an iterator somewhere in the range (@begin, @end). This
* iterator will be close to the middle of the range, but is not
* guaranteed to be exactly in the middle.
*
* The @begin and @end iterators must both point to the same sequence and
* @begin must come before or be equal to @end in the sequence.
*
* Return value: A #GSequenceIter pointing somewhere in the
* (@begin, @end) range.
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_range_get_midpoint (GSequenceIter *begin,
GSequenceIter *end)
{
int begin_pos, end_pos, mid_pos;
g_return_val_if_fail (begin != NULL, NULL);
g_return_val_if_fail (end != NULL, NULL);
g_return_val_if_fail (get_sequence (begin) == get_sequence (end), NULL);
begin_pos = node_get_pos (begin);
end_pos = node_get_pos (end);
g_return_val_if_fail (end_pos >= begin_pos, NULL);
mid_pos = begin_pos + (end_pos - begin_pos) / 2;
return node_get_by_pos (begin, mid_pos);
}
/**
* g_sequence_iter_compare:
* @a: a #GSequenceIter
* @b: a #GSequenceIter
*
* Returns a negative number if @a comes before @b, 0 if they are equal,
* and a positive number if @a comes after @b.
*
* The @a and @b iterators must point into the same sequence.
*
* Return value: A negative number if @a comes before @b, 0 if they are
* equal, and a positive number if @a comes after @b.
*
* Since: 2.14
**/
gint
g_sequence_iter_compare (GSequenceIter *a,
GSequenceIter *b)
{
gint a_pos, b_pos;
g_return_val_if_fail (a != NULL, 0);
g_return_val_if_fail (b != NULL, 0);
g_return_val_if_fail (get_sequence (a) == get_sequence (b), 0);
check_iter_access (a);
check_iter_access (b);
a_pos = node_get_pos (a);
b_pos = node_get_pos (b);
if (a_pos == b_pos)
return 0;
else if (a_pos > b_pos)
return 1;
else
return -1;
}
/**
* g_sequence_append:
* @seq: a #GSequence
* @data: the data for the new item
*
* Adds a new item to the end of @seq.
*
* Return value: an iterator pointing to the new item
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_append (GSequence *seq,
gpointer data)
{
GSequenceNode *node;
g_return_val_if_fail (seq != NULL, NULL);
check_seq_access (seq);
node = node_new (data);
node_insert_before (seq->end_node, node);
return node;
}
/**
* g_sequence_prepend:
* @seq: a #GSequence
* @data: the data for the new item
*
* Adds a new item to the front of @seq
*
* Return value: an iterator pointing to the new item
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_prepend (GSequence *seq,
gpointer data)
{
GSequenceNode *node, *first;
g_return_val_if_fail (seq != NULL, NULL);
check_seq_access (seq);
node = node_new (data);
first = node_get_first (seq->end_node);
node_insert_before (first, node);
return node;
}
/**
* g_sequence_insert_before:
* @iter: a #GSequenceIter
* @data: the data for the new item
*
* Inserts a new item just before the item pointed to by @iter.
*
* Return value: an iterator pointing to the new item
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_insert_before (GSequenceIter *iter,
gpointer data)
{
GSequenceNode *node;
g_return_val_if_fail (iter != NULL, NULL);
check_iter_access (iter);
node = node_new (data);
node_insert_before (iter, node);
return node;
}
/**
* g_sequence_remove:
* @iter: a #GSequenceIter
*
* Removes the item pointed to by @iter. It is an error to pass the
* end iterator to this function.
*
* If the sequence has a data destroy function associated with it, this
* function is called on the data for the removed item.
*
* Since: 2.14
**/
void
g_sequence_remove (GSequenceIter *iter)
{
GSequence *seq;
g_return_if_fail (iter != NULL);
g_return_if_fail (!is_end (iter));
check_iter_access (iter);
seq = get_sequence (iter);
node_unlink (iter);
node_free (iter, seq);
}
/**
* g_sequence_remove_range:
* @begin: a #GSequenceIter
* @end: a #GSequenceIter
*
* Removes all items in the (@begin, @end) range.
*
* If the sequence has a data destroy function associated with it, this
* function is called on the data for the removed items.
*
* Since: 2.14
**/
void
g_sequence_remove_range (GSequenceIter *begin,
GSequenceIter *end)
{
g_return_if_fail (get_sequence (begin) == get_sequence (end));
check_iter_access (begin);
check_iter_access (end);
g_sequence_move_range (NULL, begin, end);
}
/**
* g_sequence_move_range:
* @dest: a #GSequenceIter
* @begin: a #GSequenceIter
* @end: a #GSequenceIter
*
* Inserts the (@begin, @end) range at the destination pointed to by ptr.
* The @begin and @end iters must point into the same sequence. It is
* allowed for @dest to point to a different sequence than the one pointed
* into by @begin and @end.
*
* If @dest is NULL, the range indicated by @begin and @end is
* removed from the sequence. If @dest iter points to a place within
* the (@begin, @end) range, the range does not move.
*
* Since: 2.14
**/
void
g_sequence_move_range (GSequenceIter *dest,
GSequenceIter *begin,
GSequenceIter *end)
{
GSequence *src_seq;
GSequenceNode *first;
g_return_if_fail (begin != NULL);
g_return_if_fail (end != NULL);
check_iter_access (begin);
check_iter_access (end);
if (dest)
check_iter_access (dest);
src_seq = get_sequence (begin);
g_return_if_fail (src_seq == get_sequence (end));
/* Dest points to begin or end? */
if (dest == begin || dest == end)
return;
/* begin comes after end? */
if (g_sequence_iter_compare (begin, end) >= 0)
return;
/* dest points somewhere in the (begin, end) range? */
if (dest && get_sequence (dest) == src_seq &&
g_sequence_iter_compare (dest, begin) > 0 &&
g_sequence_iter_compare (dest, end) < 0)
{
return;
}
src_seq = get_sequence (begin);
first = node_get_first (begin);
node_cut (begin);
node_cut (end);
if (first != begin)
node_join (first, end);
if (dest)
{
first = node_get_first (dest);
node_cut (dest);
node_join (begin, dest);
if (dest != first)
node_join (first, begin);
}
else
{
node_free (begin, src_seq);
}
}
/**
* g_sequence_sort:
* @seq: a #GSequence
* @cmp_func: the function used to sort the sequence
* @cmp_data: user data passed to @cmp_func
*
* Sorts @seq using @cmp_func.
*
* @cmp_func is passed two items of @seq and should
* return 0 if they are equal, a negative value if the
* first comes before the second, and a positive value
* if the second comes before the first.
*
* Since: 2.14
**/
void
g_sequence_sort (GSequence *seq,
GCompareDataFunc cmp_func,
gpointer cmp_data)
{
SortInfo info;
info.cmp_func = cmp_func;
info.cmp_data = cmp_data;
info.end_node = seq->end_node;
check_seq_access (seq);
g_sequence_sort_iter (seq, iter_compare, &info);
}
/**
* g_sequence_insert_sorted:
* @seq: a #GSequence
* @data: the data to insert
* @cmp_func: the function used to compare items in the sequence
* @cmp_data: user data passed to @cmp_func.
*
* Inserts @data into @sequence using @func to determine the new
* position. The sequence must already be sorted according to @cmp_func;
* otherwise the new position of @data is undefined.
*
* @cmp_func is called with two items of the @seq and @user_data.
* It should return 0 if the items are equal, a negative value
* if the first item comes before the second, and a positive value
* if the second item comes before the first.
*
* Return value: a #GSequenceIter pointing to the new item.
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_insert_sorted (GSequence *seq,
gpointer data,
GCompareDataFunc cmp_func,
gpointer cmp_data)
{
SortInfo info;
g_return_val_if_fail (seq != NULL, NULL);
g_return_val_if_fail (cmp_func != NULL, NULL);
info.cmp_func = cmp_func;
info.cmp_data = cmp_data;
info.end_node = seq->end_node;
check_seq_access (seq);
return g_sequence_insert_sorted_iter (seq, data, iter_compare, &info);
}
/**
* g_sequence_sort_changed:
* @iter: A #GSequenceIter
* @cmp_func: the function used to compare items in the sequence
* @cmp_data: user data passed to @cmp_func.
*
* Moves the data pointed to a new position as indicated by @cmp_func. This
* function should be called for items in a sequence already sorted according
* to @cmp_func whenever some aspect of an item changes so that @cmp_func
* may return different values for that item.
*
* @cmp_func is called with two items of the @seq and @user_data.
* It should return 0 if the items are equal, a negative value if
* the first item comes before the second, and a positive value if
* the second item comes before the first.
*
* Since: 2.14
**/
void
g_sequence_sort_changed (GSequenceIter *iter,
GCompareDataFunc cmp_func,
gpointer cmp_data)
{
SortInfo info;
g_return_if_fail (!is_end (iter));
info.cmp_func = cmp_func;
info.cmp_data = cmp_data;
info.end_node = get_sequence (iter)->end_node;
check_iter_access (iter);
g_sequence_sort_changed_iter (iter, iter_compare, &info);
}
/**
* g_sequence_search:
* @seq: a #GSequence
* @data: data for the new item
* @cmp_func: the function used to compare items in the sequence
* @cmp_data: user data passed to @cmp_func.
*
* Returns an iterator pointing to the position where @data would
* be inserted according to @cmp_func and @cmp_data.
*
* @cmp_func is called with two items of the @seq and @user_data.
* It should return 0 if the items are equal, a negative value if
* the first item comes before the second, and a positive value if
* the second item comes before the first.
*
* If you are simply searching for an existing element of the sequence,
* consider using g_sequence_lookup().
*
*
* This function will fail if the data contained in the sequence is
* unsorted. Use g_sequence_insert_sorted() or
* g_sequence_insert_sorted_iter() to add data to your sequence or, if
* you want to add a large amount of data, call g_sequence_sort() after
* doing unsorted insertions.
*
*
* Return value: an #GSequenceIter pointing to the position where @data
* would have been inserted according to @cmp_func and @cmp_data.
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_search (GSequence *seq,
gpointer data,
GCompareDataFunc cmp_func,
gpointer cmp_data)
{
SortInfo info;
g_return_val_if_fail (seq != NULL, NULL);
info.cmp_func = cmp_func;
info.cmp_data = cmp_data;
info.end_node = seq->end_node;
check_seq_access (seq);
return g_sequence_search_iter (seq, data, iter_compare, &info);
}
/**
* g_sequence_lookup:
* @seq: a #GSequence
* @data: data to lookup
* @cmp_func: the function used to compare items in the sequence
* @cmp_data: user data passed to @cmp_func.
*
* Returns an iterator pointing to the position of the first item found
* equal to @data according to @cmp_func and @cmp_data. If more than one
* item is equal, it is not guaranteed that it is the first which is
* returned. In that case, you can use g_sequence_iter_next() and
* g_sequence_iter_prev() to get others.
*
* @cmp_func is called with two items of the @seq and @user_data.
* It should return 0 if the items are equal, a negative value if
* the first item comes before the second, and a positive value if
* the second item comes before the first.
*
*
* This function will fail if the data contained in the sequence is
* unsorted. Use g_sequence_insert_sorted() or
* g_sequence_insert_sorted_iter() to add data to your sequence or, if
* you want to add a large amount of data, call g_sequence_sort() after
* doing unsorted insertions.
*
*
* Return value: an #GSequenceIter pointing to the position of the
* first item found equal to @data according to @cmp_func and
* @cmp_data, or %NULL if no such item exists.
*
* Since: 2.28
**/
GSequenceIter *
g_sequence_lookup (GSequence *seq,
gpointer data,
GCompareDataFunc cmp_func,
gpointer cmp_data)
{
SortInfo info;
g_return_val_if_fail (seq != NULL, NULL);
info.cmp_func = cmp_func;
info.cmp_data = cmp_data;
info.end_node = seq->end_node;
check_seq_access (seq);
return g_sequence_lookup_iter (seq, data, iter_compare, &info);
}
/**
* g_sequence_sort_iter:
* @seq: a #GSequence
* @cmp_func: the function used to compare iterators in the sequence
* @cmp_data: user data passed to @cmp_func
*
* Like g_sequence_sort(), but uses a #GSequenceIterCompareFunc instead
* of a GCompareDataFunc as the compare function
*
* @cmp_func is called with two iterators pointing into @seq. It should
* return 0 if the iterators are equal, a negative value if the first
* iterator comes before the second, and a positive value if the second
* iterator comes before the first.
*
* Since: 2.14
**/
void
g_sequence_sort_iter (GSequence *seq,
GSequenceIterCompareFunc cmp_func,
gpointer cmp_data)
{
GSequence *tmp;
GSequenceNode *begin, *end;
g_return_if_fail (seq != NULL);
g_return_if_fail (cmp_func != NULL);
check_seq_access (seq);
begin = g_sequence_get_begin_iter (seq);
end = g_sequence_get_end_iter (seq);
tmp = g_sequence_new (NULL);
tmp->real_sequence = seq;
g_sequence_move_range (g_sequence_get_begin_iter (tmp), begin, end);
seq->access_prohibited = TRUE;
tmp->access_prohibited = TRUE;
while (g_sequence_get_length (tmp) > 0)
{
GSequenceNode *node = g_sequence_get_begin_iter (tmp);
node_insert_sorted (seq->end_node, node, seq->end_node,
cmp_func, cmp_data);
}
tmp->access_prohibited = FALSE;
seq->access_prohibited = FALSE;
g_sequence_free (tmp);
}
/**
* g_sequence_sort_changed_iter:
* @iter: a #GSequenceIter
* @iter_cmp: the function used to compare iterators in the sequence
* @cmp_data: user data passed to @cmp_func
*
* Like g_sequence_sort_changed(), but uses
* a #GSequenceIterCompareFunc instead of a #GCompareDataFunc as
* the compare function.
*
* @iter_cmp is called with two iterators pointing into @seq. It should
* return 0 if the iterators are equal, a negative value if the first
* iterator comes before the second, and a positive value if the second
* iterator comes before the first.
*
* Since: 2.14
**/
void
g_sequence_sort_changed_iter (GSequenceIter *iter,
GSequenceIterCompareFunc iter_cmp,
gpointer cmp_data)
{
GSequence *seq, *tmp_seq;
GSequenceIter *next, *prev;
g_return_if_fail (iter != NULL);
g_return_if_fail (!is_end (iter));
g_return_if_fail (iter_cmp != NULL);
check_iter_access (iter);
/* If one of the neighbours is equal to iter, then
* don't move it. This ensures that sort_changed() is
* a stable operation.
*/
next = node_get_next (iter);
prev = node_get_prev (iter);
if (prev != iter && iter_cmp (prev, iter, cmp_data) == 0)
return;
if (!is_end (next) && iter_cmp (next, iter, cmp_data) == 0)
return;
seq = get_sequence (iter);
seq->access_prohibited = TRUE;
tmp_seq = g_sequence_new (NULL);
tmp_seq->real_sequence = seq;
node_unlink (iter);
node_insert_before (tmp_seq->end_node, iter);
node_insert_sorted (seq->end_node, iter, seq->end_node,
iter_cmp, cmp_data);
g_sequence_free (tmp_seq);
seq->access_prohibited = FALSE;
}
/**
* g_sequence_insert_sorted_iter:
* @seq: a #GSequence
* @data: data for the new item
* @iter_cmp: the function used to compare iterators in the sequence
* @cmp_data: user data passed to @cmp_func
*
* Like g_sequence_insert_sorted(), but uses
* a #GSequenceIterCompareFunc instead of a #GCompareDataFunc as
* the compare function.
*
* @iter_cmp is called with two iterators pointing into @seq.
* It should return 0 if the iterators are equal, a negative
* value if the first iterator comes before the second, and a
* positive value if the second iterator comes before the first.
*
* It is called with two iterators pointing into @seq. It should
* return 0 if the iterators are equal, a negative value if the
* first iterator comes before the second, and a positive value
* if the second iterator comes before the first.
*
* Return value: a #GSequenceIter pointing to the new item
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_insert_sorted_iter (GSequence *seq,
gpointer data,
GSequenceIterCompareFunc iter_cmp,
gpointer cmp_data)
{
GSequenceNode *new_node;
GSequence *tmp_seq;
g_return_val_if_fail (seq != NULL, NULL);
g_return_val_if_fail (iter_cmp != NULL, NULL);
check_seq_access (seq);
seq->access_prohibited = TRUE;
/* Create a new temporary sequence and put the new node into
* that. The reason for this is that the user compare function
* will be called with the new node, and if it dereferences,
* "is_end" will be called on it. But that will crash if the
* node is not actually in a sequence.
*
* node_insert_sorted() makes sure the node is unlinked before
* it is inserted.
*
* The reason we need the "iter" versions at all is that that
* is the only kind of compare functions GtkTreeView can use.
*/
tmp_seq = g_sequence_new (NULL);
tmp_seq->real_sequence = seq;
new_node = g_sequence_append (tmp_seq, data);
node_insert_sorted (seq->end_node, new_node,
seq->end_node, iter_cmp, cmp_data);
g_sequence_free (tmp_seq);
seq->access_prohibited = FALSE;
return new_node;
}
/**
* g_sequence_search_iter:
* @seq: a #GSequence
* @data: data for the new item
* @iter_cmp: the function used to compare iterators in the sequence
* @cmp_data: user data passed to @iter_cmp
*
* Like g_sequence_search(), but uses a #GSequenceIterCompareFunc
* instead of a #GCompareDataFunc as the compare function.
*
* @iter_cmp is called with two iterators pointing into @seq.
* It should return 0 if the iterators are equal, a negative value
* if the first iterator comes before the second, and a positive
* value if the second iterator comes before the first.
*
* If you are simply searching for an existing element of the sequence,
* consider using g_sequence_lookup_iter().
*
*
* This function will fail if the data contained in the sequence is
* unsorted. Use g_sequence_insert_sorted() or
* g_sequence_insert_sorted_iter() to add data to your sequence or, if
* you want to add a large amount of data, call g_sequence_sort() after
* doing unsorted insertions.
*
*
* Return value: a #GSequenceIter pointing to the position in @seq
* where @data would have been inserted according to @iter_cmp
* and @cmp_data.
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_search_iter (GSequence *seq,
gpointer data,
GSequenceIterCompareFunc iter_cmp,
gpointer cmp_data)
{
GSequenceNode *node;
GSequenceNode *dummy;
GSequence *tmp_seq;
g_return_val_if_fail (seq != NULL, NULL);
check_seq_access (seq);
seq->access_prohibited = TRUE;
tmp_seq = g_sequence_new (NULL);
tmp_seq->real_sequence = seq;
dummy = g_sequence_append (tmp_seq, data);
node = node_find_closest (seq->end_node, dummy,
seq->end_node, iter_cmp, cmp_data);
g_sequence_free (tmp_seq);
seq->access_prohibited = FALSE;
return node;
}
/**
* g_sequence_lookup_iter:
* @seq: a #GSequence
* @data: data to lookup
* @iter_cmp: the function used to compare iterators in the sequence
* @cmp_data: user data passed to @iter_cmp
*
* Like g_sequence_lookup(), but uses a #GSequenceIterCompareFunc
* instead of a #GCompareDataFunc as the compare function.
*
* @iter_cmp is called with two iterators pointing into @seq.
* It should return 0 if the iterators are equal, a negative value
* if the first iterator comes before the second, and a positive
* value if the second iterator comes before the first.
*
*
* This function will fail if the data contained in the sequence is
* unsorted. Use g_sequence_insert_sorted() or
* g_sequence_insert_sorted_iter() to add data to your sequence or, if
* you want to add a large amount of data, call g_sequence_sort() after
* doing unsorted insertions.
*
*
* Return value: an #GSequenceIter pointing to the position of
* the first item found equal to @data according to @cmp_func
* and @cmp_data, or %NULL if no such item exists.
*
* Since: 2.28
**/
GSequenceIter *
g_sequence_lookup_iter (GSequence *seq,
gpointer data,
GSequenceIterCompareFunc iter_cmp,
gpointer cmp_data)
{
GSequenceNode *node;
GSequenceNode *dummy;
GSequence *tmp_seq;
g_return_val_if_fail (seq != NULL, NULL);
check_seq_access (seq);
seq->access_prohibited = TRUE;
tmp_seq = g_sequence_new (NULL);
tmp_seq->real_sequence = seq;
dummy = g_sequence_append (tmp_seq, data);
node = node_find (seq->end_node, dummy,
seq->end_node, iter_cmp, cmp_data);
g_sequence_free (tmp_seq);
seq->access_prohibited = FALSE;
return node;
}
/**
* g_sequence_iter_get_sequence:
* @iter: a #GSequenceIter
*
* Returns the #GSequence that @iter points into.
*
* Return value: the #GSequence that @iter points into.
*
* Since: 2.14
**/
GSequence *
g_sequence_iter_get_sequence (GSequenceIter *iter)
{
GSequence *seq;
g_return_val_if_fail (iter != NULL, NULL);
seq = get_sequence (iter);
/* For temporary sequences, this points to the sequence that
* is actually being manipulated
*/
return seq->real_sequence;
}
/**
* g_sequence_get:
* @iter: a #GSequenceIter
*
* Returns the data that @iter points to.
*
* Return value: the data that @iter points to
*
* Since: 2.14
**/
gpointer
g_sequence_get (GSequenceIter *iter)
{
g_return_val_if_fail (iter != NULL, NULL);
g_return_val_if_fail (!is_end (iter), NULL);
return iter->data;
}
/**
* g_sequence_set:
* @iter: a #GSequenceIter
* @data: new data for the item
*
* Changes the data for the item pointed to by @iter to be @data. If
* the sequence has a data destroy function associated with it, that
* function is called on the existing data that @iter pointed to.
*
* Since: 2.14
**/
void
g_sequence_set (GSequenceIter *iter,
gpointer data)
{
GSequence *seq;
g_return_if_fail (iter != NULL);
g_return_if_fail (!is_end (iter));
seq = get_sequence (iter);
/* If @data is identical to iter->data, it is destroyed
* here. This will work right in case of ref-counted objects. Also
* it is similar to what ghashtables do.
*
* For non-refcounted data it's a little less convenient, but
* code relying on self-setting not destroying would be
* pretty dubious anyway ...
*/
if (seq->data_destroy_notify)
seq->data_destroy_notify (iter->data);
iter->data = data;
}
/**
* g_sequence_get_length:
* @seq: a #GSequence
*
* Returns the length of @seq
*
* Return value: the length of @seq
*
* Since: 2.14
**/
gint
g_sequence_get_length (GSequence *seq)
{
return node_get_length (seq->end_node) - 1;
}
/**
* g_sequence_get_end_iter:
* @seq: a #GSequence
*
* Returns the end iterator for @seg
*
* Return value: the end iterator for @seq
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_get_end_iter (GSequence *seq)
{
g_return_val_if_fail (seq != NULL, NULL);
return seq->end_node;
}
/**
* g_sequence_get_begin_iter:
* @seq: a #GSequence
*
* Returns the begin iterator for @seq.
*
* Return value: the begin iterator for @seq.
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_get_begin_iter (GSequence *seq)
{
g_return_val_if_fail (seq != NULL, NULL);
return node_get_first (seq->end_node);
}
static int
clamp_position (GSequence *seq,
int pos)
{
gint len = g_sequence_get_length (seq);
if (pos > len || pos < 0)
pos = len;
return pos;
}
/*
* if pos > number of items or -1, will return end pointer
*/
/**
* g_sequence_get_iter_at_pos:
* @seq: a #GSequence
* @pos: a position in @seq, or -1 for the end.
*
* Returns the iterator at position @pos. If @pos is negative or larger
* than the number of items in @seq, the end iterator is returned.
*
* Return value: The #GSequenceIter at position @pos
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_get_iter_at_pos (GSequence *seq,
gint pos)
{
g_return_val_if_fail (seq != NULL, NULL);
pos = clamp_position (seq, pos);
return node_get_by_pos (seq->end_node, pos);
}
/**
* g_sequence_move:
* @src: a #GSequenceIter pointing to the item to move
* @dest: a #GSequenceIter pointing to the position to which
* the item is moved.
*
* Moves the item pointed to by @src to the position indicated by @dest.
* After calling this function @dest will point to the position immediately
* after @src. It is allowed for @src and @dest to point into different
* sequences.
*
* Since: 2.14
**/
void
g_sequence_move (GSequenceIter *src,
GSequenceIter *dest)
{
g_return_if_fail (src != NULL);
g_return_if_fail (dest != NULL);
g_return_if_fail (!is_end (src));
if (src == dest)
return;
node_unlink (src);
node_insert_before (dest, src);
}
/* GSequenceIter */
/**
* g_sequence_iter_is_end:
* @iter: a #GSequenceIter
*
* Returns whether @iter is the end iterator
*
* Return value: Whether @iter is the end iterator.
*
* Since: 2.14
**/
gboolean
g_sequence_iter_is_end (GSequenceIter *iter)
{
g_return_val_if_fail (iter != NULL, FALSE);
return is_end (iter);
}
/**
* g_sequence_iter_is_begin:
* @iter: a #GSequenceIter
*
* Returns whether @iter is the begin iterator
*
* Return value: whether @iter is the begin iterator
*
* Since: 2.14
**/
gboolean
g_sequence_iter_is_begin (GSequenceIter *iter)
{
g_return_val_if_fail (iter != NULL, FALSE);
return (node_get_prev (iter) == iter);
}
/**
* g_sequence_iter_get_position:
* @iter: a #GSequenceIter
*
* Returns the position of @iter
*
* Return value: the position of @iter
*
* Since: 2.14
**/
gint
g_sequence_iter_get_position (GSequenceIter *iter)
{
g_return_val_if_fail (iter != NULL, -1);
return node_get_pos (iter);
}
/**
* g_sequence_iter_next:
* @iter: a #GSequenceIter
*
* Returns an iterator pointing to the next position after @iter. If
* @iter is the end iterator, the end iterator is returned.
*
* Return value: a #GSequenceIter pointing to the next position after @iter.
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_iter_next (GSequenceIter *iter)
{
g_return_val_if_fail (iter != NULL, NULL);
return node_get_next (iter);
}
/**
* g_sequence_iter_prev:
* @iter: a #GSequenceIter
*
* Returns an iterator pointing to the previous position before @iter. If
* @iter is the begin iterator, the begin iterator is returned.
*
* Return value: a #GSequenceIter pointing to the previous position before
* @iter.
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_iter_prev (GSequenceIter *iter)
{
g_return_val_if_fail (iter != NULL, NULL);
return node_get_prev (iter);
}
/**
* g_sequence_iter_move:
* @iter: a #GSequenceIter
* @delta: A positive or negative number indicating how many positions away
* from @iter the returned #GSequenceIter will be.
*
* Returns the #GSequenceIter which is @delta positions away from @iter.
* If @iter is closer than -@delta positions to the beginning of the sequence,
* the begin iterator is returned. If @iter is closer than @delta positions
* to the end of the sequence, the end iterator is returned.
*
* Return value: a #GSequenceIter which is @delta positions away from @iter.
*
* Since: 2.14
**/
GSequenceIter *
g_sequence_iter_move (GSequenceIter *iter,
gint delta)
{
gint new_pos;
gint len;
g_return_val_if_fail (iter != NULL, NULL);
len = g_sequence_get_length (get_sequence (iter));
new_pos = node_get_pos (iter) + delta;
if (new_pos < 0)
new_pos = 0;
else if (new_pos > len)
new_pos = len;
return node_get_by_pos (iter, new_pos);
}
/**
* g_sequence_swap:
* @a: a #GSequenceIter
* @b: a #GSequenceIter
*
* Swaps the items pointed to by @a and @b. It is allowed for @a and @b
* to point into difference sequences.
*
* Since: 2.14
**/
void
g_sequence_swap (GSequenceIter *a,
GSequenceIter *b)
{
GSequenceNode *leftmost, *rightmost, *rightmost_next;
int a_pos, b_pos;
g_return_if_fail (!g_sequence_iter_is_end (a));
g_return_if_fail (!g_sequence_iter_is_end (b));
if (a == b)
return;
a_pos = g_sequence_iter_get_position (a);
b_pos = g_sequence_iter_get_position (b);
if (a_pos > b_pos)
{
leftmost = b;
rightmost = a;
}
else
{
leftmost = a;
rightmost = b;
}
rightmost_next = node_get_next (rightmost);
/* The situation is now like this:
*
* ..., leftmost, ......., rightmost, rightmost_next, ...
*
*/
g_sequence_move (rightmost, leftmost);
g_sequence_move (leftmost, rightmost_next);
}
/*
* Implementation of a treap
*
*
*/
static guint
get_priority (GSequenceNode *node)
{
guint key = GPOINTER_TO_UINT (node);
/* This hash function is based on one found on Thomas Wang's
* web page at
*
* http://www.concentric.net/~Ttwang/tech/inthash.htm
*
*/
key = (key << 15) - key - 1;
key = key ^ (key >> 12);
key = key + (key << 2);
key = key ^ (key >> 4);
key = key + (key << 3) + (key << 11);
key = key ^ (key >> 16);
/* We rely on 0 being less than all other priorities */
return key? key : 1;
}
static GSequenceNode *
find_root (GSequenceNode *node)
{
while (node->parent)
node = node->parent;
return node;
}
static GSequenceNode *
node_new (gpointer data)
{
GSequenceNode *node = g_slice_new0 (GSequenceNode);
node->n_nodes = 1;
node->data = data;
node->left = NULL;
node->right = NULL;
node->parent = NULL;
return node;
}
static GSequenceNode *
node_get_first (GSequenceNode *node)
{
node = find_root (node);
while (node->left)
node = node->left;
return node;
}
static GSequenceNode *
node_get_last (GSequenceNode *node)
{
node = find_root (node);
while (node->right)
node = node->right;
return node;
}
#define NODE_LEFT_CHILD(n) (((n)->parent) && ((n)->parent->left) == (n))
#define NODE_RIGHT_CHILD(n) (((n)->parent) && ((n)->parent->right) == (n))
static GSequenceNode *
node_get_next (GSequenceNode *node)
{
GSequenceNode *n = node;
if (n->right)
{
n = n->right;
while (n->left)
n = n->left;
}
else
{
while (NODE_RIGHT_CHILD (n))
n = n->parent;
if (n->parent)
n = n->parent;
else
n = node;
}
return n;
}
static GSequenceNode *
node_get_prev (GSequenceNode *node)
{
GSequenceNode *n = node;
if (n->left)
{
n = n->left;
while (n->right)
n = n->right;
}
else
{
while (NODE_LEFT_CHILD (n))
n = n->parent;
if (n->parent)
n = n->parent;
else
n = node;
}
return n;
}
#define N_NODES(n) ((n)? (n)->n_nodes : 0)
static gint
node_get_pos (GSequenceNode *node)
{
int n_smaller = 0;
if (node->left)
n_smaller = node->left->n_nodes;
while (node)
{
if (NODE_RIGHT_CHILD (node))
n_smaller += N_NODES (node->parent->left) + 1;
node = node->parent;
}
return n_smaller;
}
static GSequenceNode *
node_get_by_pos (GSequenceNode *node,
gint pos)
{
int i;
node = find_root (node);
while ((i = N_NODES (node->left)) != pos)
{
if (i < pos)
{
node = node->right;
pos -= (i + 1);
}
else
{
node = node->left;
}
}
return node;
}
static GSequenceNode *
node_find (GSequenceNode *haystack,
GSequenceNode *needle,
GSequenceNode *end,
GSequenceIterCompareFunc iter_cmp,
gpointer cmp_data)
{
gint c;
haystack = find_root (haystack);
do
{
/* iter_cmp can't be passed the end node, since the function may
* be user-supplied
*/
if (haystack == end)
c = 1;
else
c = iter_cmp (haystack, needle, cmp_data);
if (c == 0)
break;
if (c > 0)
haystack = haystack->left;
else
haystack = haystack->right;
}
while (haystack != NULL);
return haystack;
}
static GSequenceNode *
node_find_closest (GSequenceNode *haystack,
GSequenceNode *needle,
GSequenceNode *end,
GSequenceIterCompareFunc iter_cmp,
gpointer cmp_data)
{
GSequenceNode *best;
gint c;
haystack = find_root (haystack);
do
{
best = haystack;
/* iter_cmp can't be passed the end node, since the function may
* be user-supplied
*/
if (haystack == end)
c = 1;
else
c = iter_cmp (haystack, needle, cmp_data);
/* In the following we don't break even if c == 0. Instead we go on
* searching along the 'bigger' nodes, so that we find the last one
* that is equal to the needle.
*/
if (c > 0)
haystack = haystack->left;
else
haystack = haystack->right;
}
while (haystack != NULL);
/* If the best node is smaller or equal to the data, then move one step
* to the right to make sure the best one is strictly bigger than the data
*/
if (best != end && c <= 0)
best = node_get_next (best);
return best;
}
static gint
node_get_length (GSequenceNode *node)
{
node = find_root (node);
return node->n_nodes;
}
static void
real_node_free (GSequenceNode *node,
GSequence *seq)
{
if (node)
{
real_node_free (node->left, seq);
real_node_free (node->right, seq);
if (seq && seq->data_destroy_notify && node != seq->end_node)
seq->data_destroy_notify (node->data);
g_slice_free (GSequenceNode, node);
}
}
static void
node_free (GSequenceNode *node,
GSequence *seq)
{
node = find_root (node);
real_node_free (node, seq);
}
static void
node_update_fields (GSequenceNode *node)
{
int n_nodes = 1;
n_nodes += N_NODES (node->left);
n_nodes += N_NODES (node->right);
node->n_nodes = n_nodes;
}
static void
node_rotate (GSequenceNode *node)
{
GSequenceNode *tmp, *old;
g_assert (node->parent);
g_assert (node->parent != node);
if (NODE_LEFT_CHILD (node))
{
/* rotate right */
tmp = node->right;
node->right = node->parent;
node->parent = node->parent->parent;
if (node->parent)
{
if (node->parent->left == node->right)
node->parent->left = node;
else
node->parent->right = node;
}
g_assert (node->right);
node->right->parent = node;
node->right->left = tmp;
if (node->right->left)
node->right->left->parent = node->right;
old = node->right;
}
else
{
/* rotate left */
tmp = node->left;
node->left = node->parent;
node->parent = node->parent->parent;
if (node->parent)
{
if (node->parent->right == node->left)
node->parent->right = node;
else
node->parent->left = node;
}
g_assert (node->left);
node->left->parent = node;
node->left->right = tmp;
if (node->left->right)
node->left->right->parent = node->left;
old = node->left;
}
node_update_fields (old);
node_update_fields (node);
}
static void
node_update_fields_deep (GSequenceNode *node)
{
if (node)
{
node_update_fields (node);
node_update_fields_deep (node->parent);
}
}
static void
rotate_down (GSequenceNode *node,
guint priority)
{
guint left, right;
left = node->left ? get_priority (node->left) : 0;
right = node->right ? get_priority (node->right) : 0;
while (priority < left || priority < right)
{
if (left > right)
node_rotate (node->left);
else
node_rotate (node->right);
left = node->left ? get_priority (node->left) : 0;
right = node->right ? get_priority (node->right) : 0;
}
}
static void
node_cut (GSequenceNode *node)
{
while (node->parent)
node_rotate (node);
if (node->left)
node->left->parent = NULL;
node->left = NULL;
node_update_fields (node);
rotate_down (node, get_priority (node));
}
static void
node_join (GSequenceNode *left,
GSequenceNode *right)
{
GSequenceNode *fake = node_new (NULL);
fake->left = find_root (left);
fake->right = find_root (right);
fake->left->parent = fake;
fake->right->parent = fake;
node_update_fields (fake);
node_unlink (fake);
node_free (fake, NULL);
}
static void
node_insert_before (GSequenceNode *node,
GSequenceNode *new)
{
new->left = node->left;
if (new->left)
new->left->parent = new;
new->parent = node;
node->left = new;
node_update_fields_deep (new);
while (new->parent && get_priority (new) > get_priority (new->parent))
node_rotate (new);
rotate_down (new, get_priority (new));
}
static void
node_unlink (GSequenceNode *node)
{
rotate_down (node, 0);
if (NODE_RIGHT_CHILD (node))
node->parent->right = NULL;
else if (NODE_LEFT_CHILD (node))
node->parent->left = NULL;
if (node->parent)
node_update_fields_deep (node->parent);
node->parent = NULL;
}
static void
node_insert_sorted (GSequenceNode *node,
GSequenceNode *new,
GSequenceNode *end,
GSequenceIterCompareFunc iter_cmp,
gpointer cmp_data)
{
GSequenceNode *closest;
closest = node_find_closest (node, new, end, iter_cmp, cmp_data);
node_unlink (new);
node_insert_before (closest, new);
}
pkg-config-0.29.1/glib/glib/gmacros.h 0000664 0001750 0001750 00000030450 12651243552 014217 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
/* This file must not include any other glib header file and must thus
* not refer to variables from glibconfig.h
*/
#ifndef __G_MACROS_H__
#define __G_MACROS_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
/* We include stddef.h to get the system's definition of NULL
*/
#include
/* Here we provide G_GNUC_EXTENSION as an alias for __extension__,
* where this is valid. This allows for warningless compilation of
* "long long" types even in the presence of '-ansi -pedantic'.
*/
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
# define G_GNUC_EXTENSION __extension__
#else
# define G_GNUC_EXTENSION
#endif
/* Provide macros to feature the GCC function attribute.
*/
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
#define G_GNUC_PURE \
__attribute__((__pure__))
#define G_GNUC_MALLOC \
__attribute__((__malloc__))
#else
#define G_GNUC_PURE
#define G_GNUC_MALLOC
#endif
#if __GNUC__ >= 4
#define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__))
#else
#define G_GNUC_NULL_TERMINATED
#endif
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
#define G_GNUC_ALLOC_SIZE(x) __attribute__((__alloc_size__(x)))
#define G_GNUC_ALLOC_SIZE2(x,y) __attribute__((__alloc_size__(x,y)))
#else
#define G_GNUC_ALLOC_SIZE(x)
#define G_GNUC_ALLOC_SIZE2(x,y)
#endif
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
#define G_GNUC_PRINTF( format_idx, arg_idx ) \
__attribute__((__format__ (__printf__, format_idx, arg_idx)))
#define G_GNUC_SCANF( format_idx, arg_idx ) \
__attribute__((__format__ (__scanf__, format_idx, arg_idx)))
#define G_GNUC_FORMAT( arg_idx ) \
__attribute__((__format_arg__ (arg_idx)))
#define G_GNUC_NORETURN \
__attribute__((__noreturn__))
#define G_GNUC_CONST \
__attribute__((__const__))
#define G_GNUC_UNUSED \
__attribute__((__unused__))
#define G_GNUC_NO_INSTRUMENT \
__attribute__((__no_instrument_function__))
#else /* !__GNUC__ */
#define G_GNUC_PRINTF( format_idx, arg_idx )
#define G_GNUC_SCANF( format_idx, arg_idx )
#define G_GNUC_FORMAT( arg_idx )
#define G_GNUC_NORETURN
#define G_GNUC_CONST
#define G_GNUC_UNUSED
#define G_GNUC_NO_INSTRUMENT
#endif /* !__GNUC__ */
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
#define G_GNUC_DEPRECATED \
__attribute__((__deprecated__))
#else
#define G_GNUC_DEPRECATED
#endif /* __GNUC__ */
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
#define G_GNUC_DEPRECATED_FOR(f) \
__attribute__((deprecated("Use " #f " instead")))
#else
#define G_GNUC_DEPRECATED_FOR(f) G_GNUC_DEPRECATED
#endif /* __GNUC__ */
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#define G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
#define G_GNUC_END_IGNORE_DEPRECATIONS \
_Pragma ("GCC diagnostic pop")
#elif defined (_MSC_VER) && (_MSC_VER >= 1500)
#define G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
__pragma (warning (push)) \
__pragma (warning (disable : 4996))
#define G_GNUC_END_IGNORE_DEPRECATIONS \
__pragma (warning (pop))
#else
#define G_GNUC_BEGIN_IGNORE_DEPRECATIONS
#define G_GNUC_END_IGNORE_DEPRECATIONS
#endif
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
# define G_GNUC_MAY_ALIAS __attribute__((may_alias))
#else
# define G_GNUC_MAY_ALIAS
#endif
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#define G_GNUC_WARN_UNUSED_RESULT \
__attribute__((warn_unused_result))
#else
#define G_GNUC_WARN_UNUSED_RESULT
#endif /* __GNUC__ */
#ifndef G_DISABLE_DEPRECATED
/* Wrap the gcc __PRETTY_FUNCTION__ and __FUNCTION__ variables with
* macros, so we can refer to them as strings unconditionally.
* usage not-recommended since gcc-3.0
*/
#if defined (__GNUC__) && (__GNUC__ < 3)
#define G_GNUC_FUNCTION __FUNCTION__
#define G_GNUC_PRETTY_FUNCTION __PRETTY_FUNCTION__
#else /* !__GNUC__ */
#define G_GNUC_FUNCTION ""
#define G_GNUC_PRETTY_FUNCTION ""
#endif /* !__GNUC__ */
#endif /* !G_DISABLE_DEPRECATED */
/* Clang feature detection: http://clang.llvm.org/docs/LanguageExtensions.html */
#ifndef __has_feature
#define __has_feature(x) 0
#endif
#if __has_feature(attribute_analyzer_noreturn)
#define G_ANALYZER_ANALYZING 1
#define G_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
#else
#define G_ANALYZER_ANALYZING 0
#define G_ANALYZER_NORETURN
#endif
#define G_STRINGIFY(macro_or_string) G_STRINGIFY_ARG (macro_or_string)
#define G_STRINGIFY_ARG(contents) #contents
#ifndef __GI_SCANNER__ /* The static assert macro really confuses the introspection parser */
#define G_PASTE_ARGS(identifier1,identifier2) identifier1 ## identifier2
#define G_PASTE(identifier1,identifier2) G_PASTE_ARGS (identifier1, identifier2)
#ifdef __COUNTER__
#define G_STATIC_ASSERT(expr) typedef char G_PASTE (_GStaticAssertCompileTimeAssertion_, __COUNTER__)[(expr) ? 1 : -1] G_GNUC_UNUSED
#else
#define G_STATIC_ASSERT(expr) typedef char G_PASTE (_GStaticAssertCompileTimeAssertion_, __LINE__)[(expr) ? 1 : -1] G_GNUC_UNUSED
#endif
#define G_STATIC_ASSERT_EXPR(expr) ((void) sizeof (char[(expr) ? 1 : -1]))
#endif
/* Provide a string identifying the current code position */
#if defined(__GNUC__) && (__GNUC__ < 3) && !defined(__cplusplus)
# define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__) ":" __PRETTY_FUNCTION__ "()"
#else
# define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__)
#endif
/* Provide a string identifying the current function, non-concatenatable */
#if defined (__GNUC__) && defined (__cplusplus)
# define G_STRFUNC ((const char*) (__PRETTY_FUNCTION__))
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 19901L
# define G_STRFUNC ((const char*) (__func__))
#elif defined (__GNUC__) || (defined(_MSC_VER) && (_MSC_VER > 1300))
# define G_STRFUNC ((const char*) (__FUNCTION__))
#else
# define G_STRFUNC ((const char*) ("???"))
#endif
/* Guard C code in headers, while including them from C++ */
#ifdef __cplusplus
# define G_BEGIN_DECLS extern "C" {
# define G_END_DECLS }
#else
# define G_BEGIN_DECLS
# define G_END_DECLS
#endif
/* Provide definitions for some commonly used macros.
* Some of them are only provided if they haven't already
* been defined. It is assumed that if they are already
* defined then the current definition is correct.
*/
#ifndef NULL
# ifdef __cplusplus
# define NULL (0L)
# else /* !__cplusplus */
# define NULL ((void*) 0)
# endif /* !__cplusplus */
#endif
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
#undef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#undef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#undef ABS
#define ABS(a) (((a) < 0) ? -(a) : (a))
#undef CLAMP
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
/* Count the number of elements in an array. The array must be defined
* as such; using this with a dynamically allocated array will give
* incorrect results.
*/
#define G_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
/* Macros by analogy to GINT_TO_POINTER, GPOINTER_TO_INT
*/
#define GPOINTER_TO_SIZE(p) ((gsize) (p))
#define GSIZE_TO_POINTER(s) ((gpointer) (gsize) (s))
/* Provide convenience macros for handling structure
* fields through their offsets.
*/
#if defined(__GNUC__) && __GNUC__ >= 4
# define G_STRUCT_OFFSET(struct_type, member) \
((glong) offsetof (struct_type, member))
#else
# define G_STRUCT_OFFSET(struct_type, member) \
((glong) ((guint8*) &((struct_type*) 0)->member))
#endif
#define G_STRUCT_MEMBER_P(struct_p, struct_offset) \
((gpointer) ((guint8*) (struct_p) + (glong) (struct_offset)))
#define G_STRUCT_MEMBER(member_type, struct_p, struct_offset) \
(*(member_type*) G_STRUCT_MEMBER_P ((struct_p), (struct_offset)))
/* Provide simple macro statement wrappers:
* G_STMT_START { statements; } G_STMT_END;
* This can be used as a single statement, like:
* if (x) G_STMT_START { ... } G_STMT_END; else ...
* This intentionally does not use compiler extensions like GCC's '({...})' to
* avoid portability issue or side effects when compiled with different compilers.
*/
#if !(defined (G_STMT_START) && defined (G_STMT_END))
# define G_STMT_START do
# define G_STMT_END while (0)
#endif
/* Deprecated -- do not use. */
#ifndef G_DISABLE_DEPRECATED
#ifdef G_DISABLE_CONST_RETURNS
#define G_CONST_RETURN
#else
#define G_CONST_RETURN const
#endif
#endif
/*
* The G_LIKELY and G_UNLIKELY macros let the programmer give hints to
* the compiler about the expected result of an expression. Some compilers
* can use this information for optimizations.
*
* The _G_BOOLEAN_EXPR macro is intended to trigger a gcc warning when
* putting assignments in g_return_if_fail ().
*/
#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
#define _G_BOOLEAN_EXPR(expr) \
G_GNUC_EXTENSION ({ \
int _g_boolean_var_; \
if (expr) \
_g_boolean_var_ = 1; \
else \
_g_boolean_var_ = 0; \
_g_boolean_var_; \
})
#define G_LIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR(expr), 1))
#define G_UNLIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR(expr), 0))
#else
#define G_LIKELY(expr) (expr)
#define G_UNLIKELY(expr) (expr)
#endif
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
#define G_DEPRECATED __attribute__((__deprecated__))
#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
#define G_DEPRECATED __declspec(deprecated)
#else
#define G_DEPRECATED
#endif
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
#define G_DEPRECATED_FOR(f) __attribute__((__deprecated__("Use '" #f "' instead")))
#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320)
#define G_DEPRECATED_FOR(f) __declspec(deprecated("is deprecated. Use '" #f "' instead"))
#else
#define G_DEPRECATED_FOR(f) G_DEPRECATED
#endif
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
#define G_UNAVAILABLE(maj,min) __attribute__((deprecated("Not available before " #maj "." #min)))
#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320)
#define G_UNAVAILABLE(maj,min) __declspec(deprecated("is not available before " #maj "." #min))
#else
#define G_UNAVAILABLE(maj,min) G_DEPRECATED
#endif
#ifndef _GLIB_EXTERN
#define _GLIB_EXTERN extern
#endif
/* These macros are used to mark deprecated functions in GLib headers,
* and thus have to be exposed in installed headers. But please
* do *not* use them in other projects. Instead, use G_DEPRECATED
* or define your own wrappers around it.
*/
#ifdef GLIB_DISABLE_DEPRECATION_WARNINGS
#define GLIB_DEPRECATED _GLIB_EXTERN
#define GLIB_DEPRECATED_FOR(f) _GLIB_EXTERN
#define GLIB_UNAVAILABLE(maj,min) _GLIB_EXTERN
#else
#define GLIB_DEPRECATED G_DEPRECATED _GLIB_EXTERN
#define GLIB_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) _GLIB_EXTERN
#define GLIB_UNAVAILABLE(maj,min) G_UNAVAILABLE(maj,min) _GLIB_EXTERN
#endif
#endif /* __G_MACROS_H__ */
pkg-config-0.29.1/glib/glib/gbookmarkfile.c 0000664 0001750 0001750 00000301745 12651243552 015403 0000000 0000000 /* gbookmarkfile.c: parsing and building desktop bookmarks
*
* Copyright (C) 2005-2006 Emmanuele Bassi
*
* 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., 59 Temple Place - Suite 330,
*/
#include "config.h"
#include "gbookmarkfile.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef HAVE_UNISTD_H
#include
#endif
#include "gconvert.h"
#include "gdataset.h"
#include "gerror.h"
#include "gfileutils.h"
#include "ghash.h"
#include "glibintl.h"
#include "glist.h"
#include "gslist.h"
#include "gmain.h"
#include "gmarkup.h"
#include "gmem.h"
#include "gmessages.h"
#include "gshell.h"
#include "gslice.h"
#include "gstdio.h"
#include "gstring.h"
#include "gstrfuncs.h"
#include "gtimer.h"
#include "gutils.h"
/**
* SECTION:bookmarkfile
* @title: Bookmark file parser
* @short_description: parses files containing bookmarks
*
* GBookmarkFile lets you parse, edit or create files containing bookmarks
* to URI, along with some meta-data about the resource pointed by the URI
* like its MIME type, the application that is registering the bookmark and
* the icon that should be used to represent the bookmark. The data is stored
* using the
* Desktop Bookmark
* Specification.
*
* The syntax of the bookmark files is described in detail inside the Desktop
* Bookmark Specification, here is a quick summary: bookmark files use a
* sub-class of the XML Bookmark Exchange Language
* specification, consisting of valid UTF-8 encoded XML, under the
* xbel root element; each bookmark is stored inside a
* bookmark element, using its URI: no relative paths can
* be used inside a bookmark file. The bookmark may have a user defined title
* and description, to be used instead of the URI. Under the
* metadata element, with its owner
* attribute set to http://freedesktop.org, is stored the
* meta-data about a resource pointed by its URI. The meta-data consists of
* the resource's MIME type; the applications that have registered a bookmark;
* the groups to which a bookmark belongs to; a visibility flag, used to set
* the bookmark as "private" to the applications and groups that has it
* registered; the URI and MIME type of an icon, to be used when displaying
* the bookmark inside a GUI.
* |[FIXME: MISSING XINCLUDE CONTENT]|
*
* A bookmark file might contain more than one bookmark; each bookmark
* is accessed through its URI.
*
* The important caveat of bookmark files is that when you add a new
* bookmark you must also add the application that is registering it, using
* g_bookmark_file_add_application() or g_bookmark_file_set_app_info().
* If a bookmark has no applications then it won't be dumped when creating
* the on disk representation, using g_bookmark_file_to_data() or
* g_bookmark_file_to_file().
*
* The #GBookmarkFile parser was added in GLib 2.12.
*/
/* XBEL 1.0 standard entities */
#define XBEL_VERSION "1.0"
#define XBEL_DTD_NICK "xbel"
#define XBEL_DTD_SYSTEM "+//IDN python.org//DTD XML Bookmark " \
"Exchange Language 1.0//EN//XML"
#define XBEL_DTD_URI "http://www.python.org/topics/xml/dtds/xbel-1.0.dtd"
#define XBEL_ROOT_ELEMENT "xbel"
#define XBEL_FOLDER_ELEMENT "folder" /* unused */
#define XBEL_BOOKMARK_ELEMENT "bookmark"
#define XBEL_ALIAS_ELEMENT "alias" /* unused */
#define XBEL_SEPARATOR_ELEMENT "separator" /* unused */
#define XBEL_TITLE_ELEMENT "title"
#define XBEL_DESC_ELEMENT "desc"
#define XBEL_INFO_ELEMENT "info"
#define XBEL_METADATA_ELEMENT "metadata"
#define XBEL_VERSION_ATTRIBUTE "version"
#define XBEL_FOLDED_ATTRIBUTE "folded" /* unused */
#define XBEL_OWNER_ATTRIBUTE "owner"
#define XBEL_ADDED_ATTRIBUTE "added"
#define XBEL_VISITED_ATTRIBUTE "visited"
#define XBEL_MODIFIED_ATTRIBUTE "modified"
#define XBEL_ID_ATTRIBUTE "id"
#define XBEL_HREF_ATTRIBUTE "href"
#define XBEL_REF_ATTRIBUTE "ref" /* unused */
#define XBEL_YES_VALUE "yes"
#define XBEL_NO_VALUE "no"
/* Desktop bookmark spec entities */
#define BOOKMARK_METADATA_OWNER "http://freedesktop.org"
#define BOOKMARK_NAMESPACE_NAME "bookmark"
#define BOOKMARK_NAMESPACE_URI "http://www.freedesktop.org/standards/desktop-bookmarks"
#define BOOKMARK_GROUPS_ELEMENT "groups"
#define BOOKMARK_GROUP_ELEMENT "group"
#define BOOKMARK_APPLICATIONS_ELEMENT "applications"
#define BOOKMARK_APPLICATION_ELEMENT "application"
#define BOOKMARK_ICON_ELEMENT "icon"
#define BOOKMARK_PRIVATE_ELEMENT "private"
#define BOOKMARK_NAME_ATTRIBUTE "name"
#define BOOKMARK_EXEC_ATTRIBUTE "exec"
#define BOOKMARK_COUNT_ATTRIBUTE "count"
#define BOOKMARK_TIMESTAMP_ATTRIBUTE "timestamp" /* deprecated by "modified" */
#define BOOKMARK_MODIFIED_ATTRIBUTE "modified"
#define BOOKMARK_HREF_ATTRIBUTE "href"
#define BOOKMARK_TYPE_ATTRIBUTE "type"
/* Shared MIME Info entities */
#define MIME_NAMESPACE_NAME "mime"
#define MIME_NAMESPACE_URI "http://www.freedesktop.org/standards/shared-mime-info"
#define MIME_TYPE_ELEMENT "mime-type"
#define MIME_TYPE_ATTRIBUTE "type"
typedef struct _BookmarkAppInfo BookmarkAppInfo;
typedef struct _BookmarkMetadata BookmarkMetadata;
typedef struct _BookmarkItem BookmarkItem;
typedef struct _ParseData ParseData;
struct _BookmarkAppInfo
{
gchar *name;
gchar *exec;
guint count;
time_t stamp;
};
struct _BookmarkMetadata
{
gchar *mime_type;
GList *groups;
GList *applications;
GHashTable *apps_by_name;
gchar *icon_href;
gchar *icon_mime;
guint is_private : 1;
};
struct _BookmarkItem
{
gchar *uri;
gchar *title;
gchar *description;
time_t added;
time_t modified;
time_t visited;
BookmarkMetadata *metadata;
};
struct _GBookmarkFile
{
gchar *title;
gchar *description;
/* we store our items in a list and keep a copy inside
* an hash table for faster lookup performances
*/
GList *items;
GHashTable *items_by_uri;
};
/* parser state machine */
enum
{
STATE_STARTED = 0,
STATE_ROOT,
STATE_BOOKMARK,
STATE_TITLE,
STATE_DESC,
STATE_INFO,
STATE_METADATA,
STATE_APPLICATIONS,
STATE_APPLICATION,
STATE_GROUPS,
STATE_GROUP,
STATE_MIME,
STATE_ICON,
STATE_FINISHED
};
static void g_bookmark_file_init (GBookmarkFile *bookmark);
static void g_bookmark_file_clear (GBookmarkFile *bookmark);
static gboolean g_bookmark_file_parse (GBookmarkFile *bookmark,
const gchar *buffer,
gsize length,
GError **error);
static gchar * g_bookmark_file_dump (GBookmarkFile *bookmark,
gsize *length,
GError **error);
static BookmarkItem *g_bookmark_file_lookup_item (GBookmarkFile *bookmark,
const gchar *uri);
static void g_bookmark_file_add_item (GBookmarkFile *bookmark,
BookmarkItem *item,
GError **error);
static time_t timestamp_from_iso8601 (const gchar *iso_date);
static gchar * timestamp_to_iso8601 (time_t timestamp);
/********************************
* BookmarkAppInfo *
* *
* Application metadata storage *
********************************/
static BookmarkAppInfo *
bookmark_app_info_new (const gchar *name)
{
BookmarkAppInfo *retval;
g_warn_if_fail (name != NULL);
retval = g_slice_new (BookmarkAppInfo);
retval->name = g_strdup (name);
retval->exec = NULL;
retval->count = 0;
retval->stamp = 0;
return retval;
}
static void
bookmark_app_info_free (BookmarkAppInfo *app_info)
{
if (!app_info)
return;
g_free (app_info->name);
g_free (app_info->exec);
g_slice_free (BookmarkAppInfo, app_info);
}
static gchar *
bookmark_app_info_dump (BookmarkAppInfo *app_info)
{
gchar *retval;
gchar *name, *exec, *modified, *count;
g_warn_if_fail (app_info != NULL);
if (app_info->count == 0)
return NULL;
name = g_markup_escape_text (app_info->name, -1);
exec = g_markup_escape_text (app_info->exec, -1);
modified = timestamp_to_iso8601 (app_info->stamp);
count = g_strdup_printf ("%u", app_info->count);
retval = g_strconcat (" "
"<" BOOKMARK_NAMESPACE_NAME ":" BOOKMARK_APPLICATION_ELEMENT
" " BOOKMARK_NAME_ATTRIBUTE "=\"", name, "\""
" " BOOKMARK_EXEC_ATTRIBUTE "=\"", exec, "\""
" " BOOKMARK_MODIFIED_ATTRIBUTE "=\"", modified, "\""
" " BOOKMARK_COUNT_ATTRIBUTE "=\"", count, "\"/>\n",
NULL);
g_free (name);
g_free (exec);
g_free (modified);
g_free (count);
return retval;
}
/***********************
* BookmarkMetadata *
* *
* Metadata storage *
***********************/
static BookmarkMetadata *
bookmark_metadata_new (void)
{
BookmarkMetadata *retval;
retval = g_slice_new (BookmarkMetadata);
retval->mime_type = NULL;
retval->groups = NULL;
retval->applications = NULL;
retval->apps_by_name = g_hash_table_new_full (g_str_hash,
g_str_equal,
NULL,
NULL);
retval->is_private = FALSE;
retval->icon_href = NULL;
retval->icon_mime = NULL;
return retval;
}
static void
bookmark_metadata_free (BookmarkMetadata *metadata)
{
if (!metadata)
return;
g_free (metadata->mime_type);
g_list_free_full (metadata->groups, g_free);
g_list_free_full (metadata->applications, (GDestroyNotify) bookmark_app_info_free);
g_hash_table_destroy (metadata->apps_by_name);
g_free (metadata->icon_href);
g_free (metadata->icon_mime);
g_slice_free (BookmarkMetadata, metadata);
}
static gchar *
bookmark_metadata_dump (BookmarkMetadata *metadata)
{
GString *retval;
gchar *buffer;
if (!metadata->applications)
return NULL;
retval = g_string_sized_new (1024);
/* metadata container */
g_string_append (retval,
" "
"<" XBEL_METADATA_ELEMENT
" " XBEL_OWNER_ATTRIBUTE "=\"" BOOKMARK_METADATA_OWNER
"\">\n");
/* mime type */
if (metadata->mime_type) {
buffer = g_strconcat (" "
"<" MIME_NAMESPACE_NAME ":" MIME_TYPE_ELEMENT " "
MIME_TYPE_ATTRIBUTE "=\"", metadata->mime_type, "\"/>\n",
NULL);
g_string_append (retval, buffer);
g_free (buffer);
}
if (metadata->groups)
{
GList *l;
/* open groups container */
g_string_append (retval,
" "
"<" BOOKMARK_NAMESPACE_NAME
":" BOOKMARK_GROUPS_ELEMENT ">\n");
for (l = g_list_last (metadata->groups); l != NULL; l = l->prev)
{
gchar *group_name;
group_name = g_markup_escape_text ((gchar *) l->data, -1);
buffer = g_strconcat (" "
"<" BOOKMARK_NAMESPACE_NAME
":" BOOKMARK_GROUP_ELEMENT ">",
group_name,
"" BOOKMARK_NAMESPACE_NAME
":" BOOKMARK_GROUP_ELEMENT ">\n", NULL);
g_string_append (retval, buffer);
g_free (buffer);
g_free (group_name);
}
/* close groups container */
g_string_append (retval,
" "
"" BOOKMARK_NAMESPACE_NAME
":" BOOKMARK_GROUPS_ELEMENT ">\n");
}
if (metadata->applications)
{
GList *l;
/* open applications container */
g_string_append (retval,
" "
"<" BOOKMARK_NAMESPACE_NAME
":" BOOKMARK_APPLICATIONS_ELEMENT ">\n");
for (l = g_list_last (metadata->applications); l != NULL; l = l->prev)
{
BookmarkAppInfo *app_info = (BookmarkAppInfo *) l->data;
gchar *app_data;
g_warn_if_fail (app_info != NULL);
app_data = bookmark_app_info_dump (app_info);
if (app_data)
{
retval = g_string_append (retval, app_data);
g_free (app_data);
}
}
/* close applications container */
g_string_append (retval,
" "
"" BOOKMARK_NAMESPACE_NAME
":" BOOKMARK_APPLICATIONS_ELEMENT ">\n");
}
/* icon */
if (metadata->icon_href)
{
if (!metadata->icon_mime)
metadata->icon_mime = g_strdup ("application/octet-stream");
buffer = g_strconcat (" "
"<" BOOKMARK_NAMESPACE_NAME
":" BOOKMARK_ICON_ELEMENT
" " BOOKMARK_HREF_ATTRIBUTE "=\"", metadata->icon_href,
"\" " BOOKMARK_TYPE_ATTRIBUTE "=\"", metadata->icon_mime, "\"/>\n", NULL);
g_string_append (retval, buffer);
g_free (buffer);
}
/* private hint */
if (metadata->is_private)
g_string_append (retval,
" "
"<" BOOKMARK_NAMESPACE_NAME
":" BOOKMARK_PRIVATE_ELEMENT "/>\n");
/* close metadata container */
g_string_append (retval,
" "
"" XBEL_METADATA_ELEMENT ">\n");
return g_string_free (retval, FALSE);
}
/******************************************************
* BookmarkItem *
* *
* Storage for a single bookmark item inside the list *
******************************************************/
static BookmarkItem *
bookmark_item_new (const gchar *uri)
{
BookmarkItem *item;
g_warn_if_fail (uri != NULL);
item = g_slice_new (BookmarkItem);
item->uri = g_strdup (uri);
item->title = NULL;
item->description = NULL;
item->added = (time_t) -1;
item->modified = (time_t) -1;
item->visited = (time_t) -1;
item->metadata = NULL;
return item;
}
static void
bookmark_item_free (BookmarkItem *item)
{
if (!item)
return;
g_free (item->uri);
g_free (item->title);
g_free (item->description);
if (item->metadata)
bookmark_metadata_free (item->metadata);
g_slice_free (BookmarkItem, item);
}
static gchar *
bookmark_item_dump (BookmarkItem *item)
{
GString *retval;
gchar *added, *visited, *modified;
gchar *escaped_uri;
gchar *buffer;
/* at this point, we must have at least a registered application; if we don't
* we don't screw up the bookmark file, and just skip this item
*/
if (!item->metadata || !item->metadata->applications)
{
g_warning ("Item for URI '%s' has no registered applications: skipping.\n", item->uri);
return NULL;
}
retval = g_string_sized_new (4096);
added = timestamp_to_iso8601 (item->added);
modified = timestamp_to_iso8601 (item->modified);
visited = timestamp_to_iso8601 (item->visited);
escaped_uri = g_markup_escape_text (item->uri, -1);
buffer = g_strconcat (" <"
XBEL_BOOKMARK_ELEMENT
" "
XBEL_HREF_ATTRIBUTE "=\"", escaped_uri, "\" "
XBEL_ADDED_ATTRIBUTE "=\"", added, "\" "
XBEL_MODIFIED_ATTRIBUTE "=\"", modified, "\" "
XBEL_VISITED_ATTRIBUTE "=\"", visited, "\">\n",
NULL);
g_string_append (retval, buffer);
g_free (escaped_uri);
g_free (visited);
g_free (modified);
g_free (added);
g_free (buffer);
if (item->title)
{
gchar *escaped_title;
escaped_title = g_markup_escape_text (item->title, -1);
buffer = g_strconcat (" "
"<" XBEL_TITLE_ELEMENT ">",
escaped_title,
"" XBEL_TITLE_ELEMENT ">\n",
NULL);
g_string_append (retval, buffer);
g_free (escaped_title);
g_free (buffer);
}
if (item->description)
{
gchar *escaped_desc;
escaped_desc = g_markup_escape_text (item->description, -1);
buffer = g_strconcat (" "
"<" XBEL_DESC_ELEMENT ">",
escaped_desc,
"" XBEL_DESC_ELEMENT ">\n",
NULL);
g_string_append (retval, buffer);
g_free (escaped_desc);
g_free (buffer);
}
if (item->metadata)
{
gchar *metadata;
metadata = bookmark_metadata_dump (item->metadata);
if (metadata)
{
buffer = g_strconcat (" "
"<" XBEL_INFO_ELEMENT ">\n",
metadata,
" "
"" XBEL_INFO_ELEMENT ">\n",
NULL);
retval = g_string_append (retval, buffer);
g_free (buffer);
g_free (metadata);
}
}
g_string_append (retval, " " XBEL_BOOKMARK_ELEMENT ">\n");
return g_string_free (retval, FALSE);
}
static BookmarkAppInfo *
bookmark_item_lookup_app_info (BookmarkItem *item,
const gchar *app_name)
{
g_warn_if_fail (item != NULL && app_name != NULL);
if (!item->metadata)
return NULL;
return g_hash_table_lookup (item->metadata->apps_by_name, app_name);
}
/*************************
* GBookmarkFile *
*************************/
static void
g_bookmark_file_init (GBookmarkFile *bookmark)
{
bookmark->title = NULL;
bookmark->description = NULL;
bookmark->items = NULL;
bookmark->items_by_uri = g_hash_table_new_full (g_str_hash,
g_str_equal,
NULL,
NULL);
}
static void
g_bookmark_file_clear (GBookmarkFile *bookmark)
{
g_free (bookmark->title);
g_free (bookmark->description);
g_list_free_full (bookmark->items, (GDestroyNotify) bookmark_item_free);
bookmark->items = NULL;
if (bookmark->items_by_uri)
{
g_hash_table_destroy (bookmark->items_by_uri);
bookmark->items_by_uri = NULL;
}
}
struct _ParseData
{
gint state;
GHashTable *namespaces;
GBookmarkFile *bookmark_file;
BookmarkItem *current_item;
};
static ParseData *
parse_data_new (void)
{
ParseData *retval;
retval = g_new (ParseData, 1);
retval->state = STATE_STARTED;
retval->namespaces = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) g_free);
retval->bookmark_file = NULL;
retval->current_item = NULL;
return retval;
}
static void
parse_data_free (ParseData *parse_data)
{
g_hash_table_destroy (parse_data->namespaces);
g_free (parse_data);
}
#define IS_ATTRIBUTE(s,a) ((0 == strcmp ((s), (a))))
static void
parse_bookmark_element (GMarkupParseContext *context,
ParseData *parse_data,
const gchar **attribute_names,
const gchar **attribute_values,
GError **error)
{
const gchar *uri, *added, *modified, *visited;
const gchar *attr;
gint i;
BookmarkItem *item;
GError *add_error;
g_warn_if_fail ((parse_data != NULL) && (parse_data->state == STATE_BOOKMARK));
i = 0;
uri = added = modified = visited = NULL;
for (attr = attribute_names[i]; attr != NULL; attr = attribute_names[++i])
{
if (IS_ATTRIBUTE (attr, XBEL_HREF_ATTRIBUTE))
uri = attribute_values[i];
else if (IS_ATTRIBUTE (attr, XBEL_ADDED_ATTRIBUTE))
added = attribute_values[i];
else if (IS_ATTRIBUTE (attr, XBEL_MODIFIED_ATTRIBUTE))
modified = attribute_values[i];
else if (IS_ATTRIBUTE (attr, XBEL_VISITED_ATTRIBUTE))
visited = attribute_values[i];
else
{
/* bookmark is defined by the XBEL spec, so we need
* to error out if the element has different or
* missing attributes
*/
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
_("Unexpected attribute '%s' for element '%s'"),
attr,
XBEL_BOOKMARK_ELEMENT);
return;
}
}
if (!uri)
{
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
_("Attribute '%s' of element '%s' not found"),
XBEL_HREF_ATTRIBUTE,
XBEL_BOOKMARK_ELEMENT);
return;
}
g_warn_if_fail (parse_data->current_item == NULL);
item = bookmark_item_new (uri);
if (added)
item->added = timestamp_from_iso8601 (added);
if (modified)
item->modified = timestamp_from_iso8601 (modified);
if (visited)
item->visited = timestamp_from_iso8601 (visited);
add_error = NULL;
g_bookmark_file_add_item (parse_data->bookmark_file,
item,
&add_error);
if (add_error)
{
bookmark_item_free (item);
g_propagate_error (error, add_error);
return;
}
parse_data->current_item = item;
}
static void
parse_application_element (GMarkupParseContext *context,
ParseData *parse_data,
const gchar **attribute_names,
const gchar **attribute_values,
GError **error)
{
const gchar *name, *exec, *count, *stamp, *modified;
const gchar *attr;
gint i;
BookmarkItem *item;
BookmarkAppInfo *ai;
g_warn_if_fail ((parse_data != NULL) && (parse_data->state == STATE_APPLICATION));
i = 0;
name = exec = count = stamp = modified = NULL;
for (attr = attribute_names[i]; attr != NULL; attr = attribute_names[++i])
{
if (IS_ATTRIBUTE (attr, BOOKMARK_NAME_ATTRIBUTE))
name = attribute_values[i];
else if (IS_ATTRIBUTE (attr, BOOKMARK_EXEC_ATTRIBUTE))
exec = attribute_values[i];
else if (IS_ATTRIBUTE (attr, BOOKMARK_COUNT_ATTRIBUTE))
count = attribute_values[i];
else if (IS_ATTRIBUTE (attr, BOOKMARK_TIMESTAMP_ATTRIBUTE))
stamp = attribute_values[i];
else if (IS_ATTRIBUTE (attr, BOOKMARK_MODIFIED_ATTRIBUTE))
modified = attribute_values[i];
}
/* the "name" and "exec" attributes are mandatory */
if (!name)
{
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
_("Attribute '%s' of element '%s' not found"),
BOOKMARK_NAME_ATTRIBUTE,
BOOKMARK_APPLICATION_ELEMENT);
return;
}
if (!exec)
{
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
_("Attribute '%s' of element '%s' not found"),
BOOKMARK_EXEC_ATTRIBUTE,
BOOKMARK_APPLICATION_ELEMENT);
return;
}
g_warn_if_fail (parse_data->current_item != NULL);
item = parse_data->current_item;
ai = bookmark_item_lookup_app_info (item, name);
if (!ai)
{
ai = bookmark_app_info_new (name);
if (!item->metadata)
item->metadata = bookmark_metadata_new ();
item->metadata->applications = g_list_prepend (item->metadata->applications, ai);
g_hash_table_replace (item->metadata->apps_by_name, ai->name, ai);
}
ai->exec = g_strdup (exec);
if (count)
ai->count = atoi (count);
else
ai->count = 1;
if (modified)
ai->stamp = timestamp_from_iso8601 (modified);
else
{
/* the timestamp attribute has been deprecated but we still parse
* it for backward compatibility
*/
if (stamp)
ai->stamp = (time_t) atol (stamp);
else
ai->stamp = time (NULL);
}
}
static void
parse_mime_type_element (GMarkupParseContext *context,
ParseData *parse_data,
const gchar **attribute_names,
const gchar **attribute_values,
GError **error)
{
const gchar *type;
const gchar *attr;
gint i;
BookmarkItem *item;
g_warn_if_fail ((parse_data != NULL) && (parse_data->state == STATE_MIME));
i = 0;
type = NULL;
for (attr = attribute_names[i]; attr != NULL; attr = attribute_names[++i])
{
if (IS_ATTRIBUTE (attr, MIME_TYPE_ATTRIBUTE))
type = attribute_values[i];
}
if (!type)
type = "application/octet-stream";
g_warn_if_fail (parse_data->current_item != NULL);
item = parse_data->current_item;
if (!item->metadata)
item->metadata = bookmark_metadata_new ();
item->metadata->mime_type = g_strdup (type);
}
static void
parse_icon_element (GMarkupParseContext *context,
ParseData *parse_data,
const gchar **attribute_names,
const gchar **attribute_values,
GError **error)
{
const gchar *href;
const gchar *type;
const gchar *attr;
gint i;
BookmarkItem *item;
g_warn_if_fail ((parse_data != NULL) && (parse_data->state == STATE_ICON));
i = 0;
href = NULL;
type = NULL;
for (attr = attribute_names[i]; attr != NULL; attr = attribute_names[++i])
{
if (IS_ATTRIBUTE (attr, BOOKMARK_HREF_ATTRIBUTE))
href = attribute_values[i];
else if (IS_ATTRIBUTE (attr, BOOKMARK_TYPE_ATTRIBUTE))
type = attribute_values[i];
}
/* the "href" attribute is mandatory */
if (!href)
{
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
_("Attribute '%s' of element '%s' not found"),
BOOKMARK_HREF_ATTRIBUTE,
BOOKMARK_ICON_ELEMENT);
return;
}
if (!type)
type = "application/octet-stream";
g_warn_if_fail (parse_data->current_item != NULL);
item = parse_data->current_item;
if (!item->metadata)
item->metadata = bookmark_metadata_new ();
item->metadata->icon_href = g_strdup (href);
item->metadata->icon_mime = g_strdup (type);
}
/* scans through the attributes of an element for the "xmlns" pragma, and
* adds any resulting namespace declaration to a per-parser hashtable, using
* the namespace name as a key for the namespace URI; if no key was found,
* the namespace is considered as default, and stored under the "default" key.
*
* FIXME: this works on the assumption that the generator of the XBEL file
* is either this code or is smart enough to place the namespace declarations
* inside the main root node or inside the metadata node and does not redefine
* a namespace inside an inner node; this does *not* conform to the
* XML-NS standard, although is a close approximation. In order to make this
* conformant to the XML-NS specification we should use a per-element
* namespace table inside GMarkup and ask it to resolve the namespaces for us.
*/
static void
map_namespace_to_name (ParseData *parse_data,
const gchar **attribute_names,
const gchar **attribute_values)
{
const gchar *attr;
gint i;
g_warn_if_fail (parse_data != NULL);
if (!attribute_names || !attribute_names[0])
return;
i = 0;
for (attr = attribute_names[i]; attr; attr = attribute_names[++i])
{
if (g_str_has_prefix (attr, "xmlns"))
{
gchar *namespace_name, *namespace_uri;
gchar *p;
p = g_utf8_strchr (attr, -1, ':');
if (p)
p = g_utf8_next_char (p);
else
p = "default";
namespace_name = g_strdup (p);
namespace_uri = g_strdup (attribute_values[i]);
g_hash_table_replace (parse_data->namespaces,
namespace_name,
namespace_uri);
}
}
}
/* checks whether @element_full is equal to @element.
*
* if @namespace is set, it tries to resolve the namespace to a known URI,
* and if found is prepended to the element name, from which is separated
* using the character specified in the @sep parameter.
*/
static gboolean
is_element_full (ParseData *parse_data,
const gchar *element_full,
const gchar *namespace,
const gchar *element,
const gchar sep)
{
gchar *ns_uri, *ns_name;
const gchar *p, *element_name;
gboolean retval;
g_warn_if_fail (parse_data != NULL);
g_warn_if_fail (element_full != NULL);
if (!element)
return FALSE;
/* no namespace requested: dumb element compare */
if (!namespace)
return (0 == strcmp (element_full, element));
/* search for namespace separator; if none found, assume we are under the
* default namespace, and set ns_name to our "default" marker; if no default
* namespace has been set, just do a plain comparison between @full_element
* and @element.
*/
p = g_utf8_strchr (element_full, -1, ':');
if (p)
{
ns_name = g_strndup (element_full, p - element_full);
element_name = g_utf8_next_char (p);
}
else
{
ns_name = g_strdup ("default");
element_name = element_full;
}
ns_uri = g_hash_table_lookup (parse_data->namespaces, ns_name);
if (!ns_uri)
{
/* no default namespace found */
g_free (ns_name);
return (0 == strcmp (element_full, element));
}
retval = (0 == strcmp (ns_uri, namespace) &&
0 == strcmp (element_name, element));
g_free (ns_name);
return retval;
}
#define IS_ELEMENT(p,s,e) (is_element_full ((p), (s), NULL, (e), '\0'))
#define IS_ELEMENT_NS(p,s,n,e) (is_element_full ((p), (s), (n), (e), '|'))
static void
start_element_raw_cb (GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
const gchar **attribute_values,
gpointer user_data,
GError **error)
{
ParseData *parse_data = (ParseData *) user_data;
/* we must check for namespace declarations first
*
* XXX - we could speed up things by checking for namespace declarations
* only on the root node, where they usually are; this would probably break
* on streams not produced by us or by "smart" generators
*/
map_namespace_to_name (parse_data, attribute_names, attribute_values);
switch (parse_data->state)
{
case STATE_STARTED:
if (IS_ELEMENT (parse_data, element_name, XBEL_ROOT_ELEMENT))
{
const gchar *attr;
gint i;
i = 0;
for (attr = attribute_names[i]; attr; attr = attribute_names[++i])
{
if ((IS_ATTRIBUTE (attr, XBEL_VERSION_ATTRIBUTE)) &&
(0 == strcmp (attribute_values[i], XBEL_VERSION)))
parse_data->state = STATE_ROOT;
}
}
else
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
_("Unexpected tag '%s', tag '%s' expected"),
element_name, XBEL_ROOT_ELEMENT);
break;
case STATE_ROOT:
if (IS_ELEMENT (parse_data, element_name, XBEL_TITLE_ELEMENT))
parse_data->state = STATE_TITLE;
else if (IS_ELEMENT (parse_data, element_name, XBEL_DESC_ELEMENT))
parse_data->state = STATE_DESC;
else if (IS_ELEMENT (parse_data, element_name, XBEL_BOOKMARK_ELEMENT))
{
GError *inner_error = NULL;
parse_data->state = STATE_BOOKMARK;
parse_bookmark_element (context,
parse_data,
attribute_names,
attribute_values,
&inner_error);
if (inner_error)
g_propagate_error (error, inner_error);
}
else
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
_("Unexpected tag '%s' inside '%s'"),
element_name,
XBEL_ROOT_ELEMENT);
break;
case STATE_BOOKMARK:
if (IS_ELEMENT (parse_data, element_name, XBEL_TITLE_ELEMENT))
parse_data->state = STATE_TITLE;
else if (IS_ELEMENT (parse_data, element_name, XBEL_DESC_ELEMENT))
parse_data->state = STATE_DESC;
else if (IS_ELEMENT (parse_data, element_name, XBEL_INFO_ELEMENT))
parse_data->state = STATE_INFO;
else
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
_("Unexpected tag '%s' inside '%s'"),
element_name,
XBEL_BOOKMARK_ELEMENT);
break;
case STATE_INFO:
if (IS_ELEMENT (parse_data, element_name, XBEL_METADATA_ELEMENT))
{
const gchar *attr;
gint i;
i = 0;
for (attr = attribute_names[i]; attr; attr = attribute_names[++i])
{
if ((IS_ATTRIBUTE (attr, XBEL_OWNER_ATTRIBUTE)) &&
(0 == strcmp (attribute_values[i], BOOKMARK_METADATA_OWNER)))
{
parse_data->state = STATE_METADATA;
if (!parse_data->current_item->metadata)
parse_data->current_item->metadata = bookmark_metadata_new ();
}
}
}
else
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
_("Unexpected tag '%s', tag '%s' expected"),
element_name,
XBEL_METADATA_ELEMENT);
break;
case STATE_METADATA:
if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_APPLICATIONS_ELEMENT))
parse_data->state = STATE_APPLICATIONS;
else if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_GROUPS_ELEMENT))
parse_data->state = STATE_GROUPS;
else if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_PRIVATE_ELEMENT))
parse_data->current_item->metadata->is_private = TRUE;
else if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_ICON_ELEMENT))
{
GError *inner_error = NULL;
parse_data->state = STATE_ICON;
parse_icon_element (context,
parse_data,
attribute_names,
attribute_values,
&inner_error);
if (inner_error)
g_propagate_error (error, inner_error);
}
else if (IS_ELEMENT_NS (parse_data, element_name, MIME_NAMESPACE_URI, MIME_TYPE_ELEMENT))
{
GError *inner_error = NULL;
parse_data->state = STATE_MIME;
parse_mime_type_element (context,
parse_data,
attribute_names,
attribute_values,
&inner_error);
if (inner_error)
g_propagate_error (error, inner_error);
}
else
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ELEMENT,
_("Unexpected tag '%s' inside '%s'"),
element_name,
XBEL_METADATA_ELEMENT);
break;
case STATE_APPLICATIONS:
if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_APPLICATION_ELEMENT))
{
GError *inner_error = NULL;
parse_data->state = STATE_APPLICATION;
parse_application_element (context,
parse_data,
attribute_names,
attribute_values,
&inner_error);
if (inner_error)
g_propagate_error (error, inner_error);
}
else
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
_("Unexpected tag '%s', tag '%s' expected"),
element_name,
BOOKMARK_APPLICATION_ELEMENT);
break;
case STATE_GROUPS:
if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_GROUP_ELEMENT))
parse_data->state = STATE_GROUP;
else
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
_("Unexpected tag '%s', tag '%s' expected"),
element_name,
BOOKMARK_GROUP_ELEMENT);
break;
case STATE_ICON:
if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_ICON_ELEMENT))
{
GError *inner_error = NULL;
parse_icon_element (context,
parse_data,
attribute_names,
attribute_values,
&inner_error);
if (inner_error)
g_propagate_error (error, inner_error);
}
else
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ELEMENT,
_("Unexpected tag '%s' inside '%s'"),
element_name,
XBEL_METADATA_ELEMENT);
break;
default:
g_warn_if_reached ();
break;
}
}
static void
end_element_raw_cb (GMarkupParseContext *context,
const gchar *element_name,
gpointer user_data,
GError **error)
{
ParseData *parse_data = (ParseData *) user_data;
if (IS_ELEMENT (parse_data, element_name, XBEL_ROOT_ELEMENT))
parse_data->state = STATE_FINISHED;
else if (IS_ELEMENT (parse_data, element_name, XBEL_BOOKMARK_ELEMENT))
{
parse_data->current_item = NULL;
parse_data->state = STATE_ROOT;
}
else if ((IS_ELEMENT (parse_data, element_name, XBEL_INFO_ELEMENT)) ||
(IS_ELEMENT (parse_data, element_name, XBEL_TITLE_ELEMENT)) ||
(IS_ELEMENT (parse_data, element_name, XBEL_DESC_ELEMENT)))
{
if (parse_data->current_item)
parse_data->state = STATE_BOOKMARK;
else
parse_data->state = STATE_ROOT;
}
else if (IS_ELEMENT (parse_data, element_name, XBEL_METADATA_ELEMENT))
parse_data->state = STATE_INFO;
else if (IS_ELEMENT_NS (parse_data, element_name,
BOOKMARK_NAMESPACE_URI,
BOOKMARK_APPLICATION_ELEMENT))
parse_data->state = STATE_APPLICATIONS;
else if (IS_ELEMENT_NS (parse_data, element_name,
BOOKMARK_NAMESPACE_URI,
BOOKMARK_GROUP_ELEMENT))
parse_data->state = STATE_GROUPS;
else if ((IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_APPLICATIONS_ELEMENT)) ||
(IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_GROUPS_ELEMENT)) ||
(IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_PRIVATE_ELEMENT)) ||
(IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_ICON_ELEMENT)) ||
(IS_ELEMENT_NS (parse_data, element_name, MIME_NAMESPACE_URI, MIME_TYPE_ELEMENT)))
parse_data->state = STATE_METADATA;
}
static void
text_raw_cb (GMarkupParseContext *context,
const gchar *text,
gsize length,
gpointer user_data,
GError **error)
{
ParseData *parse_data = (ParseData *) user_data;
gchar *payload;
payload = g_strndup (text, length);
switch (parse_data->state)
{
case STATE_TITLE:
if (parse_data->current_item)
{
g_free (parse_data->current_item->title);
parse_data->current_item->title = g_strdup (payload);
}
else
{
g_free (parse_data->bookmark_file->title);
parse_data->bookmark_file->title = g_strdup (payload);
}
break;
case STATE_DESC:
if (parse_data->current_item)
{
g_free (parse_data->current_item->description);
parse_data->current_item->description = g_strdup (payload);
}
else
{
g_free (parse_data->bookmark_file->description);
parse_data->bookmark_file->description = g_strdup (payload);
}
break;
case STATE_GROUP:
{
GList *groups;
g_warn_if_fail (parse_data->current_item != NULL);
if (!parse_data->current_item->metadata)
parse_data->current_item->metadata = bookmark_metadata_new ();
groups = parse_data->current_item->metadata->groups;
parse_data->current_item->metadata->groups = g_list_prepend (groups, g_strdup (payload));
}
break;
case STATE_ROOT:
case STATE_BOOKMARK:
case STATE_INFO:
case STATE_METADATA:
case STATE_APPLICATIONS:
case STATE_APPLICATION:
case STATE_GROUPS:
case STATE_MIME:
case STATE_ICON:
break;
default:
g_warn_if_reached ();
break;
}
g_free (payload);
}
static const GMarkupParser markup_parser =
{
start_element_raw_cb, /* start_element */
end_element_raw_cb, /* end_element */
text_raw_cb, /* text */
NULL, /* passthrough */
NULL
};
static gboolean
g_bookmark_file_parse (GBookmarkFile *bookmark,
const gchar *buffer,
gsize length,
GError **error)
{
GMarkupParseContext *context;
ParseData *parse_data;
GError *parse_error, *end_error;
gboolean retval;
g_warn_if_fail (bookmark != NULL);
if (!buffer)
return FALSE;
parse_error = NULL;
end_error = NULL;
if (length == (gsize) -1)
length = strlen (buffer);
parse_data = parse_data_new ();
parse_data->bookmark_file = bookmark;
context = g_markup_parse_context_new (&markup_parser,
0,
parse_data,
(GDestroyNotify) parse_data_free);
retval = g_markup_parse_context_parse (context,
buffer,
length,
&parse_error);
if (!retval)
g_propagate_error (error, parse_error);
else
{
retval = g_markup_parse_context_end_parse (context, &end_error);
if (!retval)
g_propagate_error (error, end_error);
}
g_markup_parse_context_free (context);
return retval;
}
static gchar *
g_bookmark_file_dump (GBookmarkFile *bookmark,
gsize *length,
GError **error)
{
GString *retval;
gchar *buffer;
GList *l;
retval = g_string_sized_new (4096);
g_string_append (retval,
"\n"
#if 0
/* XXX - do we really need the doctype? */
"\n"
#endif
"<" XBEL_ROOT_ELEMENT " " XBEL_VERSION_ATTRIBUTE "=\"" XBEL_VERSION "\"\n"
" xmlns:" BOOKMARK_NAMESPACE_NAME "=\"" BOOKMARK_NAMESPACE_URI "\"\n"
" xmlns:" MIME_NAMESPACE_NAME "=\"" MIME_NAMESPACE_URI "\"\n>");
if (bookmark->title)
{
gchar *escaped_title;
escaped_title = g_markup_escape_text (bookmark->title, -1);
buffer = g_strconcat (" "
"<" XBEL_TITLE_ELEMENT ">",
escaped_title,
"" XBEL_TITLE_ELEMENT ">\n", NULL);
g_string_append (retval, buffer);
g_free (buffer);
g_free (escaped_title);
}
if (bookmark->description)
{
gchar *escaped_desc;
escaped_desc = g_markup_escape_text (bookmark->description, -1);
buffer = g_strconcat (" "
"<" XBEL_DESC_ELEMENT ">",
escaped_desc,
"" XBEL_DESC_ELEMENT ">\n", NULL);
g_string_append (retval, buffer);
g_free (buffer);
g_free (escaped_desc);
}
if (!bookmark->items)
goto out;
else
retval = g_string_append (retval, "\n");
/* the items are stored in reverse order */
for (l = g_list_last (bookmark->items);
l != NULL;
l = l->prev)
{
BookmarkItem *item = (BookmarkItem *) l->data;
gchar *item_dump;
item_dump = bookmark_item_dump (item);
if (!item_dump)
continue;
retval = g_string_append (retval, item_dump);
g_free (item_dump);
}
out:
g_string_append (retval, "" XBEL_ROOT_ELEMENT ">");
if (length)
*length = retval->len;
return g_string_free (retval, FALSE);
}
/**************
* Misc *
**************/
/* converts a Unix timestamp in a ISO 8601 compliant string; you
* should free the returned string.
*/
static gchar *
timestamp_to_iso8601 (time_t timestamp)
{
GTimeVal stamp;
if (timestamp == (time_t) -1)
g_get_current_time (&stamp);
else
{
stamp.tv_sec = timestamp;
stamp.tv_usec = 0;
}
return g_time_val_to_iso8601 (&stamp);
}
static time_t
timestamp_from_iso8601 (const gchar *iso_date)
{
GTimeVal stamp;
if (!g_time_val_from_iso8601 (iso_date, &stamp))
return (time_t) -1;
return (time_t) stamp.tv_sec;
}
G_DEFINE_QUARK (g-bookmark-file-error-quark, g_bookmark_file_error)
/********************
* Public API *
********************/
/**
* g_bookmark_file_new:
*
* Creates a new empty #GBookmarkFile object.
*
* Use g_bookmark_file_load_from_file(), g_bookmark_file_load_from_data()
* or g_bookmark_file_load_from_data_dirs() to read an existing bookmark
* file.
*
* Return value: an empty #GBookmarkFile
*
* Since: 2.12
*/
GBookmarkFile *
g_bookmark_file_new (void)
{
GBookmarkFile *bookmark;
bookmark = g_new (GBookmarkFile, 1);
g_bookmark_file_init (bookmark);
return bookmark;
}
/**
* g_bookmark_file_free:
* @bookmark: a #GBookmarkFile
*
* Frees a #GBookmarkFile.
*
* Since: 2.12
*/
void
g_bookmark_file_free (GBookmarkFile *bookmark)
{
if (!bookmark)
return;
g_bookmark_file_clear (bookmark);
g_free (bookmark);
}
/**
* g_bookmark_file_load_from_data:
* @bookmark: an empty #GBookmarkFile struct
* @data: desktop bookmarks loaded in memory
* @length: the length of @data in bytes
* @error: return location for a #GError, or %NULL
*
* Loads a bookmark file from memory into an empty #GBookmarkFile
* structure. If the object cannot be created then @error is set to a
* #GBookmarkFileError.
*
* Return value: %TRUE if a desktop bookmark could be loaded.
*
* Since: 2.12
*/
gboolean
g_bookmark_file_load_from_data (GBookmarkFile *bookmark,
const gchar *data,
gsize length,
GError **error)
{
GError *parse_error;
gboolean retval;
g_return_val_if_fail (bookmark != NULL, FALSE);
if (length == (gsize) -1)
length = strlen (data);
if (bookmark->items)
{
g_bookmark_file_clear (bookmark);
g_bookmark_file_init (bookmark);
}
parse_error = NULL;
retval = g_bookmark_file_parse (bookmark, data, length, &parse_error);
if (!retval)
g_propagate_error (error, parse_error);
return retval;
}
/**
* g_bookmark_file_load_from_file:
* @bookmark: an empty #GBookmarkFile struct
* @filename: the path of a filename to load, in the GLib file name encoding
* @error: return location for a #GError, or %NULL
*
* Loads a desktop bookmark file into an empty #GBookmarkFile structure.
* If the file could not be loaded then @error is set to either a #GFileError
* or #GBookmarkFileError.
*
* Return value: %TRUE if a desktop bookmark file could be loaded
*
* Since: 2.12
*/
gboolean
g_bookmark_file_load_from_file (GBookmarkFile *bookmark,
const gchar *filename,
GError **error)
{
gchar *buffer;
gsize len;
GError *read_error;
gboolean retval;
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
read_error = NULL;
g_file_get_contents (filename, &buffer, &len, &read_error);
if (read_error)
{
g_propagate_error (error, read_error);
return FALSE;
}
read_error = NULL;
retval = g_bookmark_file_load_from_data (bookmark,
buffer,
len,
&read_error);
if (read_error)
{
g_propagate_error (error, read_error);
g_free (buffer);
return FALSE;
}
g_free (buffer);
return retval;
}
/* Iterates through all the directories in *dirs trying to
* find file. When it successfully locates file, returns a
* string its absolute path. It also leaves the unchecked
* directories in *dirs. You should free the returned string
*
* Adapted from gkeyfile.c
*/
static gchar *
find_file_in_data_dirs (const gchar *file,
gchar ***dirs,
GError **error)
{
gchar **data_dirs, *data_dir, *path;
path = NULL;
if (dirs == NULL)
return NULL;
data_dirs = *dirs;
path = NULL;
while (data_dirs && (data_dir = *data_dirs) && !path)
{
gchar *candidate_file, *sub_dir;
candidate_file = (gchar *) file;
sub_dir = g_strdup ("");
while (candidate_file != NULL && !path)
{
gchar *p;
path = g_build_filename (data_dir, sub_dir,
candidate_file, NULL);
candidate_file = strchr (candidate_file, '-');
if (candidate_file == NULL)
break;
candidate_file++;
g_free (sub_dir);
sub_dir = g_strndup (file, candidate_file - file - 1);
for (p = sub_dir; *p != '\0'; p++)
{
if (*p == '-')
*p = G_DIR_SEPARATOR;
}
}
g_free (sub_dir);
data_dirs++;
}
*dirs = data_dirs;
if (!path)
{
g_set_error_literal (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_FILE_NOT_FOUND,
_("No valid bookmark file found in data dirs"));
return NULL;
}
return path;
}
/**
* g_bookmark_file_load_from_data_dirs:
* @bookmark: a #GBookmarkFile
* @file: a relative path to a filename to open and parse
* @full_path: (allow-none): return location for a string containing the full path
* of the file, or %NULL
* @error: return location for a #GError, or %NULL
*
* This function looks for a desktop bookmark file named @file in the
* paths returned from g_get_user_data_dir() and g_get_system_data_dirs(),
* loads the file into @bookmark and returns the file's full path in
* @full_path. If the file could not be loaded then an %error is
* set to either a #GFileError or #GBookmarkFileError.
*
* Return value: %TRUE if a key file could be loaded, %FALSE otherwise
*
* Since: 2.12
*/
gboolean
g_bookmark_file_load_from_data_dirs (GBookmarkFile *bookmark,
const gchar *file,
gchar **full_path,
GError **error)
{
GError *file_error = NULL;
gchar **all_data_dirs, **data_dirs;
const gchar *user_data_dir;
const gchar * const * system_data_dirs;
gsize i, j;
gchar *output_path;
gboolean found_file;
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (!g_path_is_absolute (file), FALSE);
user_data_dir = g_get_user_data_dir ();
system_data_dirs = g_get_system_data_dirs ();
all_data_dirs = g_new0 (gchar *, g_strv_length ((gchar **)system_data_dirs) + 2);
i = 0;
all_data_dirs[i++] = g_strdup (user_data_dir);
j = 0;
while (system_data_dirs[j] != NULL)
all_data_dirs[i++] = g_strdup (system_data_dirs[j++]);
found_file = FALSE;
data_dirs = all_data_dirs;
output_path = NULL;
while (*data_dirs != NULL && !found_file)
{
g_free (output_path);
output_path = find_file_in_data_dirs (file, &data_dirs, &file_error);
if (file_error)
{
g_propagate_error (error, file_error);
break;
}
found_file = g_bookmark_file_load_from_file (bookmark,
output_path,
&file_error);
if (file_error)
{
g_propagate_error (error, file_error);
break;
}
}
if (found_file && full_path)
*full_path = output_path;
else
g_free (output_path);
g_strfreev (all_data_dirs);
return found_file;
}
/**
* g_bookmark_file_to_data:
* @bookmark: a #GBookmarkFile
* @length: (allow-none) (out): return location for the length of the returned string, or %NULL
* @error: return location for a #GError, or %NULL
*
* This function outputs @bookmark as a string.
*
* Return value: a newly allocated string holding
* the contents of the #GBookmarkFile
*
* Since: 2.12
*/
gchar *
g_bookmark_file_to_data (GBookmarkFile *bookmark,
gsize *length,
GError **error)
{
GError *write_error = NULL;
gchar *retval;
g_return_val_if_fail (bookmark != NULL, NULL);
retval = g_bookmark_file_dump (bookmark, length, &write_error);
if (write_error)
{
g_propagate_error (error, write_error);
return NULL;
}
return retval;
}
/**
* g_bookmark_file_to_file:
* @bookmark: a #GBookmarkFile
* @filename: path of the output file
* @error: return location for a #GError, or %NULL
*
* This function outputs @bookmark into a file. The write process is
* guaranteed to be atomic by using g_file_set_contents() internally.
*
* Return value: %TRUE if the file was successfully written.
*
* Since: 2.12
*/
gboolean
g_bookmark_file_to_file (GBookmarkFile *bookmark,
const gchar *filename,
GError **error)
{
gchar *data;
GError *data_error, *write_error;
gsize len;
gboolean retval;
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
data_error = NULL;
data = g_bookmark_file_to_data (bookmark, &len, &data_error);
if (data_error)
{
g_propagate_error (error, data_error);
return FALSE;
}
write_error = NULL;
g_file_set_contents (filename, data, len, &write_error);
if (write_error)
{
g_propagate_error (error, write_error);
retval = FALSE;
}
else
retval = TRUE;
g_free (data);
return retval;
}
static BookmarkItem *
g_bookmark_file_lookup_item (GBookmarkFile *bookmark,
const gchar *uri)
{
g_warn_if_fail (bookmark != NULL && uri != NULL);
return g_hash_table_lookup (bookmark->items_by_uri, uri);
}
/* this function adds a new item to the list */
static void
g_bookmark_file_add_item (GBookmarkFile *bookmark,
BookmarkItem *item,
GError **error)
{
g_warn_if_fail (bookmark != NULL);
g_warn_if_fail (item != NULL);
/* this should never happen; and if it does, then we are
* screwing up something big time.
*/
if (G_UNLIKELY (g_bookmark_file_has_item (bookmark, item->uri)))
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_INVALID_URI,
_("A bookmark for URI '%s' already exists"),
item->uri);
return;
}
bookmark->items = g_list_prepend (bookmark->items, item);
g_hash_table_replace (bookmark->items_by_uri,
item->uri,
item);
if (item->added == (time_t) -1)
item->added = time (NULL);
if (item->modified == (time_t) -1)
item->modified = time (NULL);
}
/**
* g_bookmark_file_remove_item:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @error: return location for a #GError, or %NULL
*
* Removes the bookmark for @uri from the bookmark file @bookmark.
*
* Return value: %TRUE if the bookmark was removed successfully.
*
* Since: 2.12
*/
gboolean
g_bookmark_file_remove_item (GBookmarkFile *bookmark,
const gchar *uri,
GError **error)
{
BookmarkItem *item;
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return FALSE;
}
bookmark->items = g_list_remove (bookmark->items, item);
g_hash_table_remove (bookmark->items_by_uri, item->uri);
bookmark_item_free (item);
return TRUE;
}
/**
* g_bookmark_file_has_item:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
*
* Looks whether the desktop bookmark has an item with its URI set to @uri.
*
* Return value: %TRUE if @uri is inside @bookmark, %FALSE otherwise
*
* Since: 2.12
*/
gboolean
g_bookmark_file_has_item (GBookmarkFile *bookmark,
const gchar *uri)
{
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
return (NULL != g_hash_table_lookup (bookmark->items_by_uri, uri));
}
/**
* g_bookmark_file_get_uris:
* @bookmark: a #GBookmarkFile
* @length: (allow-none) (out): return location for the number of returned URIs, or %NULL
*
* Returns all URIs of the bookmarks in the bookmark file @bookmark.
* The array of returned URIs will be %NULL-terminated, so @length may
* optionally be %NULL.
*
* Return value: (array length=length) (transfer full): a newly allocated %NULL-terminated array of strings.
* Use g_strfreev() to free it.
*
* Since: 2.12
*/
gchar **
g_bookmark_file_get_uris (GBookmarkFile *bookmark,
gsize *length)
{
GList *l;
gchar **uris;
gsize i, n_items;
g_return_val_if_fail (bookmark != NULL, NULL);
n_items = g_list_length (bookmark->items);
uris = g_new0 (gchar *, n_items + 1);
/* the items are stored in reverse order, so we walk the list backward */
for (l = g_list_last (bookmark->items), i = 0; l != NULL; l = l->prev)
{
BookmarkItem *item = (BookmarkItem *) l->data;
g_warn_if_fail (item != NULL);
uris[i++] = g_strdup (item->uri);
}
uris[i] = NULL;
if (length)
*length = i;
return uris;
}
/**
* g_bookmark_file_set_title:
* @bookmark: a #GBookmarkFile
* @uri: (allow-none): a valid URI or %NULL
* @title: a UTF-8 encoded string
*
* Sets @title as the title of the bookmark for @uri inside the
* bookmark file @bookmark.
*
* If @uri is %NULL, the title of @bookmark is set.
*
* If a bookmark for @uri cannot be found then it is created.
*
* Since: 2.12
*/
void
g_bookmark_file_set_title (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *title)
{
g_return_if_fail (bookmark != NULL);
if (!uri)
{
g_free (bookmark->title);
bookmark->title = g_strdup (title);
}
else
{
BookmarkItem *item;
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
item = bookmark_item_new (uri);
g_bookmark_file_add_item (bookmark, item, NULL);
}
g_free (item->title);
item->title = g_strdup (title);
item->modified = time (NULL);
}
}
/**
* g_bookmark_file_get_title:
* @bookmark: a #GBookmarkFile
* @uri: (allow-none): a valid URI or %NULL
* @error: return location for a #GError, or %NULL
*
* Returns the title of the bookmark for @uri.
*
* If @uri is %NULL, the title of @bookmark is returned.
*
* In the event the URI cannot be found, %NULL is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
*
* Return value: a newly allocated string or %NULL if the specified
* URI cannot be found.
*
* Since: 2.12
*/
gchar *
g_bookmark_file_get_title (GBookmarkFile *bookmark,
const gchar *uri,
GError **error)
{
BookmarkItem *item;
g_return_val_if_fail (bookmark != NULL, NULL);
if (!uri)
return g_strdup (bookmark->title);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return NULL;
}
return g_strdup (item->title);
}
/**
* g_bookmark_file_set_description:
* @bookmark: a #GBookmarkFile
* @uri: (allow-none): a valid URI or %NULL
* @description: a string
*
* Sets @description as the description of the bookmark for @uri.
*
* If @uri is %NULL, the description of @bookmark is set.
*
* If a bookmark for @uri cannot be found then it is created.
*
* Since: 2.12
*/
void
g_bookmark_file_set_description (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *description)
{
g_return_if_fail (bookmark != NULL);
if (!uri)
{
g_free (bookmark->description);
bookmark->description = g_strdup (description);
}
else
{
BookmarkItem *item;
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
item = bookmark_item_new (uri);
g_bookmark_file_add_item (bookmark, item, NULL);
}
g_free (item->description);
item->description = g_strdup (description);
item->modified = time (NULL);
}
}
/**
* g_bookmark_file_get_description:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @error: return location for a #GError, or %NULL
*
* Retrieves the description of the bookmark for @uri.
*
* In the event the URI cannot be found, %NULL is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
*
* Return value: a newly allocated string or %NULL if the specified
* URI cannot be found.
*
* Since: 2.12
*/
gchar *
g_bookmark_file_get_description (GBookmarkFile *bookmark,
const gchar *uri,
GError **error)
{
BookmarkItem *item;
g_return_val_if_fail (bookmark != NULL, NULL);
if (!uri)
return g_strdup (bookmark->description);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return NULL;
}
return g_strdup (item->description);
}
/**
* g_bookmark_file_set_mime_type:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @mime_type: a MIME type
*
* Sets @mime_type as the MIME type of the bookmark for @uri.
*
* If a bookmark for @uri cannot be found then it is created.
*
* Since: 2.12
*/
void
g_bookmark_file_set_mime_type (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *mime_type)
{
BookmarkItem *item;
g_return_if_fail (bookmark != NULL);
g_return_if_fail (uri != NULL);
g_return_if_fail (mime_type != NULL);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
item = bookmark_item_new (uri);
g_bookmark_file_add_item (bookmark, item, NULL);
}
if (!item->metadata)
item->metadata = bookmark_metadata_new ();
g_free (item->metadata->mime_type);
item->metadata->mime_type = g_strdup (mime_type);
item->modified = time (NULL);
}
/**
* g_bookmark_file_get_mime_type:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @error: return location for a #GError, or %NULL
*
* Retrieves the MIME type of the resource pointed by @uri.
*
* In the event the URI cannot be found, %NULL is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND. In the
* event that the MIME type cannot be found, %NULL is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_INVALID_VALUE.
*
* Return value: a newly allocated string or %NULL if the specified
* URI cannot be found.
*
* Since: 2.12
*/
gchar *
g_bookmark_file_get_mime_type (GBookmarkFile *bookmark,
const gchar *uri,
GError **error)
{
BookmarkItem *item;
g_return_val_if_fail (bookmark != NULL, NULL);
g_return_val_if_fail (uri != NULL, NULL);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return NULL;
}
if (!item->metadata)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_INVALID_VALUE,
_("No MIME type defined in the bookmark for URI '%s'"),
uri);
return NULL;
}
return g_strdup (item->metadata->mime_type);
}
/**
* g_bookmark_file_set_is_private:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @is_private: %TRUE if the bookmark should be marked as private
*
* Sets the private flag of the bookmark for @uri.
*
* If a bookmark for @uri cannot be found then it is created.
*
* Since: 2.12
*/
void
g_bookmark_file_set_is_private (GBookmarkFile *bookmark,
const gchar *uri,
gboolean is_private)
{
BookmarkItem *item;
g_return_if_fail (bookmark != NULL);
g_return_if_fail (uri != NULL);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
item = bookmark_item_new (uri);
g_bookmark_file_add_item (bookmark, item, NULL);
}
if (!item->metadata)
item->metadata = bookmark_metadata_new ();
item->metadata->is_private = (is_private == TRUE);
item->modified = time (NULL);
}
/**
* g_bookmark_file_get_is_private:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @error: return location for a #GError, or %NULL
*
* Gets whether the private flag of the bookmark for @uri is set.
*
* In the event the URI cannot be found, %FALSE is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND. In the
* event that the private flag cannot be found, %FALSE is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_INVALID_VALUE.
*
* Return value: %TRUE if the private flag is set, %FALSE otherwise.
*
* Since: 2.12
*/
gboolean
g_bookmark_file_get_is_private (GBookmarkFile *bookmark,
const gchar *uri,
GError **error)
{
BookmarkItem *item;
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return FALSE;
}
if (!item->metadata)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_INVALID_VALUE,
_("No private flag has been defined in bookmark for URI '%s'"),
uri);
return FALSE;
}
return item->metadata->is_private;
}
/**
* g_bookmark_file_set_added:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @added: a timestamp or -1 to use the current time
*
* Sets the time the bookmark for @uri was added into @bookmark.
*
* If no bookmark for @uri is found then it is created.
*
* Since: 2.12
*/
void
g_bookmark_file_set_added (GBookmarkFile *bookmark,
const gchar *uri,
time_t added)
{
BookmarkItem *item;
g_return_if_fail (bookmark != NULL);
g_return_if_fail (uri != NULL);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
item = bookmark_item_new (uri);
g_bookmark_file_add_item (bookmark, item, NULL);
}
if (added == (time_t) -1)
time (&added);
item->added = added;
item->modified = added;
}
/**
* g_bookmark_file_get_added:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @error: return location for a #GError, or %NULL
*
* Gets the time the bookmark for @uri was added to @bookmark
*
* In the event the URI cannot be found, -1 is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
*
* Return value: a timestamp
*
* Since: 2.12
*/
time_t
g_bookmark_file_get_added (GBookmarkFile *bookmark,
const gchar *uri,
GError **error)
{
BookmarkItem *item;
g_return_val_if_fail (bookmark != NULL, (time_t) -1);
g_return_val_if_fail (uri != NULL, (time_t) -1);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return (time_t) -1;
}
return item->added;
}
/**
* g_bookmark_file_set_modified:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @modified: a timestamp or -1 to use the current time
*
* Sets the last time the bookmark for @uri was last modified.
*
* If no bookmark for @uri is found then it is created.
*
* The "modified" time should only be set when the bookmark's meta-data
* was actually changed. Every function of #GBookmarkFile that
* modifies a bookmark also changes the modification time, except for
* g_bookmark_file_set_visited().
*
* Since: 2.12
*/
void
g_bookmark_file_set_modified (GBookmarkFile *bookmark,
const gchar *uri,
time_t modified)
{
BookmarkItem *item;
g_return_if_fail (bookmark != NULL);
g_return_if_fail (uri != NULL);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
item = bookmark_item_new (uri);
g_bookmark_file_add_item (bookmark, item, NULL);
}
if (modified == (time_t) -1)
time (&modified);
item->modified = modified;
}
/**
* g_bookmark_file_get_modified:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @error: return location for a #GError, or %NULL
*
* Gets the time when the bookmark for @uri was last modified.
*
* In the event the URI cannot be found, -1 is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
*
* Return value: a timestamp
*
* Since: 2.12
*/
time_t
g_bookmark_file_get_modified (GBookmarkFile *bookmark,
const gchar *uri,
GError **error)
{
BookmarkItem *item;
g_return_val_if_fail (bookmark != NULL, (time_t) -1);
g_return_val_if_fail (uri != NULL, (time_t) -1);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return (time_t) -1;
}
return item->modified;
}
/**
* g_bookmark_file_set_visited:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @visited: a timestamp or -1 to use the current time
*
* Sets the time the bookmark for @uri was last visited.
*
* If no bookmark for @uri is found then it is created.
*
* The "visited" time should only be set if the bookmark was launched,
* either using the command line retrieved by g_bookmark_file_get_app_info()
* or by the default application for the bookmark's MIME type, retrieved
* using g_bookmark_file_get_mime_type(). Changing the "visited" time
* does not affect the "modified" time.
*
* Since: 2.12
*/
void
g_bookmark_file_set_visited (GBookmarkFile *bookmark,
const gchar *uri,
time_t visited)
{
BookmarkItem *item;
g_return_if_fail (bookmark != NULL);
g_return_if_fail (uri != NULL);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
item = bookmark_item_new (uri);
g_bookmark_file_add_item (bookmark, item, NULL);
}
if (visited == (time_t) -1)
time (&visited);
item->visited = visited;
}
/**
* g_bookmark_file_get_visited:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @error: return location for a #GError, or %NULL
*
* Gets the time the bookmark for @uri was last visited.
*
* In the event the URI cannot be found, -1 is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
*
* Return value: a timestamp.
*
* Since: 2.12
*/
time_t
g_bookmark_file_get_visited (GBookmarkFile *bookmark,
const gchar *uri,
GError **error)
{
BookmarkItem *item;
g_return_val_if_fail (bookmark != NULL, (time_t) -1);
g_return_val_if_fail (uri != NULL, (time_t) -1);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return (time_t) -1;
}
return item->visited;
}
/**
* g_bookmark_file_has_group:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @group: the group name to be searched
* @error: return location for a #GError, or %NULL
*
* Checks whether @group appears in the list of groups to which
* the bookmark for @uri belongs to.
*
* In the event the URI cannot be found, %FALSE is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
*
* Return value: %TRUE if @group was found.
*
* Since: 2.12
*/
gboolean
g_bookmark_file_has_group (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *group,
GError **error)
{
BookmarkItem *item;
GList *l;
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return FALSE;
}
if (!item->metadata)
return FALSE;
for (l = item->metadata->groups; l != NULL; l = l->next)
{
if (strcmp (l->data, group) == 0)
return TRUE;
}
return FALSE;
}
/**
* g_bookmark_file_add_group:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @group: the group name to be added
*
* Adds @group to the list of groups to which the bookmark for @uri
* belongs to.
*
* If no bookmark for @uri is found then it is created.
*
* Since: 2.12
*/
void
g_bookmark_file_add_group (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *group)
{
BookmarkItem *item;
g_return_if_fail (bookmark != NULL);
g_return_if_fail (uri != NULL);
g_return_if_fail (group != NULL && group[0] != '\0');
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
item = bookmark_item_new (uri);
g_bookmark_file_add_item (bookmark, item, NULL);
}
if (!item->metadata)
item->metadata = bookmark_metadata_new ();
if (!g_bookmark_file_has_group (bookmark, uri, group, NULL))
{
item->metadata->groups = g_list_prepend (item->metadata->groups,
g_strdup (group));
item->modified = time (NULL);
}
}
/**
* g_bookmark_file_remove_group:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @group: the group name to be removed
* @error: return location for a #GError, or %NULL
*
* Removes @group from the list of groups to which the bookmark
* for @uri belongs to.
*
* In the event the URI cannot be found, %FALSE is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
* In the event no group was defined, %FALSE is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_INVALID_VALUE.
*
* Return value: %TRUE if @group was successfully removed.
*
* Since: 2.12
*/
gboolean
g_bookmark_file_remove_group (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *group,
GError **error)
{
BookmarkItem *item;
GList *l;
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return FALSE;
}
if (!item->metadata)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_INVALID_VALUE,
_("No groups set in bookmark for URI '%s'"),
uri);
return FALSE;
}
for (l = item->metadata->groups; l != NULL; l = l->next)
{
if (strcmp (l->data, group) == 0)
{
item->metadata->groups = g_list_remove_link (item->metadata->groups, l);
g_free (l->data);
g_list_free_1 (l);
item->modified = time (NULL);
return TRUE;
}
}
return FALSE;
}
/**
* g_bookmark_file_set_groups:
* @bookmark: a #GBookmarkFile
* @uri: an item's URI
* @groups: (allow-none): an array of group names, or %NULL to remove all groups
* @length: number of group name values in @groups
*
* Sets a list of group names for the item with URI @uri. Each previously
* set group name list is removed.
*
* If @uri cannot be found then an item for it is created.
*
* Since: 2.12
*/
void
g_bookmark_file_set_groups (GBookmarkFile *bookmark,
const gchar *uri,
const gchar **groups,
gsize length)
{
BookmarkItem *item;
gsize i;
g_return_if_fail (bookmark != NULL);
g_return_if_fail (uri != NULL);
g_return_if_fail (groups != NULL);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
item = bookmark_item_new (uri);
g_bookmark_file_add_item (bookmark, item, NULL);
}
if (!item->metadata)
item->metadata = bookmark_metadata_new ();
g_list_free_full (item->metadata->groups, g_free);
item->metadata->groups = NULL;
if (groups)
{
for (i = 0; groups[i] != NULL && i < length; i++)
item->metadata->groups = g_list_append (item->metadata->groups,
g_strdup (groups[i]));
}
item->modified = time (NULL);
}
/**
* g_bookmark_file_get_groups:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @length: (allow-none) (out): return location for the length of the returned string, or %NULL
* @error: return location for a #GError, or %NULL
*
* Retrieves the list of group names of the bookmark for @uri.
*
* In the event the URI cannot be found, %NULL is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
*
* The returned array is %NULL terminated, so @length may optionally
* be %NULL.
*
* Return value: (array length=length) (transfer full): a newly allocated %NULL-terminated array of group names.
* Use g_strfreev() to free it.
*
* Since: 2.12
*/
gchar **
g_bookmark_file_get_groups (GBookmarkFile *bookmark,
const gchar *uri,
gsize *length,
GError **error)
{
BookmarkItem *item;
GList *l;
gsize len, i;
gchar **retval;
g_return_val_if_fail (bookmark != NULL, NULL);
g_return_val_if_fail (uri != NULL, NULL);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return NULL;
}
if (!item->metadata)
{
if (length)
*length = 0;
return NULL;
}
len = g_list_length (item->metadata->groups);
retval = g_new0 (gchar *, len + 1);
for (l = g_list_last (item->metadata->groups), i = 0;
l != NULL;
l = l->prev)
{
gchar *group_name = (gchar *) l->data;
g_warn_if_fail (group_name != NULL);
retval[i++] = g_strdup (group_name);
}
retval[i] = NULL;
if (length)
*length = len;
return retval;
}
/**
* g_bookmark_file_add_application:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @name: (allow-none): the name of the application registering the bookmark
* or %NULL
* @exec: (allow-none): command line to be used to launch the bookmark or %NULL
*
* Adds the application with @name and @exec to the list of
* applications that have registered a bookmark for @uri into
* @bookmark.
*
* Every bookmark inside a #GBookmarkFile must have at least an
* application registered. Each application must provide a name, a
* command line useful for launching the bookmark, the number of times
* the bookmark has been registered by the application and the last
* time the application registered this bookmark.
*
* If @name is %NULL, the name of the application will be the
* same returned by g_get_application_name(); if @exec is %NULL, the
* command line will be a composition of the program name as
* returned by g_get_prgname() and the "\%u" modifier, which will be
* expanded to the bookmark's URI.
*
* This function will automatically take care of updating the
* registrations count and timestamping in case an application
* with the same @name had already registered a bookmark for
* @uri inside @bookmark.
*
* If no bookmark for @uri is found, one is created.
*
* Since: 2.12
*/
void
g_bookmark_file_add_application (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *name,
const gchar *exec)
{
BookmarkItem *item;
gchar *app_name, *app_exec;
g_return_if_fail (bookmark != NULL);
g_return_if_fail (uri != NULL);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
item = bookmark_item_new (uri);
g_bookmark_file_add_item (bookmark, item, NULL);
}
if (name && name[0] != '\0')
app_name = g_strdup (name);
else
app_name = g_strdup (g_get_application_name ());
if (exec && exec[0] != '\0')
app_exec = g_strdup (exec);
else
app_exec = g_strjoin (" ", g_get_prgname(), "%u", NULL);
g_bookmark_file_set_app_info (bookmark, uri,
app_name,
app_exec,
-1,
(time_t) -1,
NULL);
g_free (app_exec);
g_free (app_name);
}
/**
* g_bookmark_file_remove_application:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @name: the name of the application
* @error: return location for a #GError or %NULL
*
* Removes application registered with @name from the list of applications
* that have registered a bookmark for @uri inside @bookmark.
*
* In the event the URI cannot be found, %FALSE is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
* In the event that no application with name @app_name has registered
* a bookmark for @uri, %FALSE is returned and error is set to
* #G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED.
*
* Return value: %TRUE if the application was successfully removed.
*
* Since: 2.12
*/
gboolean
g_bookmark_file_remove_application (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *name,
GError **error)
{
GError *set_error;
gboolean retval;
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
g_return_val_if_fail (name != NULL, FALSE);
set_error = NULL;
retval = g_bookmark_file_set_app_info (bookmark, uri,
name,
"",
0,
(time_t) -1,
&set_error);
if (set_error)
{
g_propagate_error (error, set_error);
return FALSE;
}
return retval;
}
/**
* g_bookmark_file_has_application:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @name: the name of the application
* @error: return location for a #GError or %NULL
*
* Checks whether the bookmark for @uri inside @bookmark has been
* registered by application @name.
*
* In the event the URI cannot be found, %FALSE is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
*
* Return value: %TRUE if the application @name was found
*
* Since: 2.12
*/
gboolean
g_bookmark_file_has_application (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *name,
GError **error)
{
BookmarkItem *item;
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
g_return_val_if_fail (name != NULL, FALSE);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return FALSE;
}
return (NULL != bookmark_item_lookup_app_info (item, name));
}
/**
* g_bookmark_file_set_app_info:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @name: an application's name
* @exec: an application's command line
* @count: the number of registrations done for this application
* @stamp: the time of the last registration for this application
* @error: return location for a #GError or %NULL
*
* Sets the meta-data of application @name inside the list of
* applications that have registered a bookmark for @uri inside
* @bookmark.
*
* You should rarely use this function; use g_bookmark_file_add_application()
* and g_bookmark_file_remove_application() instead.
*
* @name can be any UTF-8 encoded string used to identify an
* application.
* @exec can have one of these two modifiers: "\%f", which will
* be expanded as the local file name retrieved from the bookmark's
* URI; "\%u", which will be expanded as the bookmark's URI.
* The expansion is done automatically when retrieving the stored
* command line using the g_bookmark_file_get_app_info() function.
* @count is the number of times the application has registered the
* bookmark; if is < 0, the current registration count will be increased
* by one, if is 0, the application with @name will be removed from
* the list of registered applications.
* @stamp is the Unix time of the last registration; if it is -1, the
* current time will be used.
*
* If you try to remove an application by setting its registration count to
* zero, and no bookmark for @uri is found, %FALSE is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND; similarly,
* in the event that no application @name has registered a bookmark
* for @uri, %FALSE is returned and error is set to
* #G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED. Otherwise, if no bookmark
* for @uri is found, one is created.
*
* Return value: %TRUE if the application's meta-data was successfully
* changed.
*
* Since: 2.12
*/
gboolean
g_bookmark_file_set_app_info (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *name,
const gchar *exec,
gint count,
time_t stamp,
GError **error)
{
BookmarkItem *item;
BookmarkAppInfo *ai;
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
g_return_val_if_fail (name != NULL, FALSE);
g_return_val_if_fail (exec != NULL, FALSE);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
if (count == 0)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return FALSE;
}
else
{
item = bookmark_item_new (uri);
g_bookmark_file_add_item (bookmark, item, NULL);
}
}
if (!item->metadata)
item->metadata = bookmark_metadata_new ();
ai = bookmark_item_lookup_app_info (item, name);
if (!ai)
{
if (count == 0)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED,
_("No application with name '%s' registered a bookmark for '%s'"),
name,
uri);
return FALSE;
}
else
{
ai = bookmark_app_info_new (name);
item->metadata->applications = g_list_prepend (item->metadata->applications, ai);
g_hash_table_replace (item->metadata->apps_by_name, ai->name, ai);
}
}
if (count == 0)
{
item->metadata->applications = g_list_remove (item->metadata->applications, ai);
g_hash_table_remove (item->metadata->apps_by_name, ai->name);
bookmark_app_info_free (ai);
item->modified = time (NULL);
return TRUE;
}
else if (count > 0)
ai->count = count;
else
ai->count += 1;
if (stamp != (time_t) -1)
ai->stamp = stamp;
else
ai->stamp = time (NULL);
if (exec && exec[0] != '\0')
{
g_free (ai->exec);
ai->exec = g_shell_quote (exec);
}
item->modified = time (NULL);
return TRUE;
}
/* expands the application's command line */
static gchar *
expand_exec_line (const gchar *exec_fmt,
const gchar *uri)
{
GString *exec;
gchar ch;
exec = g_string_sized_new (512);
while ((ch = *exec_fmt++) != '\0')
{
if (ch != '%')
{
exec = g_string_append_c (exec, ch);
continue;
}
ch = *exec_fmt++;
switch (ch)
{
case '\0':
goto out;
case 'U':
case 'u':
g_string_append (exec, uri);
break;
case 'F':
case 'f':
{
gchar *file = g_filename_from_uri (uri, NULL, NULL);
if (file)
{
g_string_append (exec, file);
g_free (file);
}
else
{
g_string_free (exec, TRUE);
return NULL;
}
}
break;
case '%':
default:
exec = g_string_append_c (exec, ch);
break;
}
}
out:
return g_string_free (exec, FALSE);
}
/**
* g_bookmark_file_get_app_info:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @name: an application's name
* @exec: (allow-none) (out): return location for the command line of the application, or %NULL
* @count: (allow-none) (out): return location for the registration count, or %NULL
* @stamp: (allow-none) (out): return location for the last registration time, or %NULL
* @error: return location for a #GError, or %NULL
*
* Gets the registration informations of @app_name for the bookmark for
* @uri. See g_bookmark_file_set_app_info() for more informations about
* the returned data.
*
* The string returned in @app_exec must be freed.
*
* In the event the URI cannot be found, %FALSE is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND. In the
* event that no application with name @app_name has registered a bookmark
* for @uri, %FALSE is returned and error is set to
* #G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED. In the event that unquoting
* the command line fails, an error of the #G_SHELL_ERROR domain is
* set and %FALSE is returned.
*
* Return value: %TRUE on success.
*
* Since: 2.12
*/
gboolean
g_bookmark_file_get_app_info (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *name,
gchar **exec,
guint *count,
time_t *stamp,
GError **error)
{
BookmarkItem *item;
BookmarkAppInfo *ai;
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
g_return_val_if_fail (name != NULL, FALSE);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return FALSE;
}
ai = bookmark_item_lookup_app_info (item, name);
if (!ai)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED,
_("No application with name '%s' registered a bookmark for '%s'"),
name,
uri);
return FALSE;
}
if (exec)
{
GError *unquote_error = NULL;
gchar *command_line;
command_line = g_shell_unquote (ai->exec, &unquote_error);
if (unquote_error)
{
g_propagate_error (error, unquote_error);
return FALSE;
}
*exec = expand_exec_line (command_line, uri);
if (!*exec)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_INVALID_URI,
_("Failed to expand exec line '%s' with URI '%s'"),
ai->exec, uri);
g_free (command_line);
return FALSE;
}
else
g_free (command_line);
}
if (count)
*count = ai->count;
if (stamp)
*stamp = ai->stamp;
return TRUE;
}
/**
* g_bookmark_file_get_applications:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @length: (allow-none) (out): return location of the length of the returned list, or %NULL
* @error: return location for a #GError, or %NULL
*
* Retrieves the names of the applications that have registered the
* bookmark for @uri.
*
* In the event the URI cannot be found, %NULL is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
*
* Return value: (array length=length) (transfer full): a newly allocated %NULL-terminated array of strings.
* Use g_strfreev() to free it.
*
* Since: 2.12
*/
gchar **
g_bookmark_file_get_applications (GBookmarkFile *bookmark,
const gchar *uri,
gsize *length,
GError **error)
{
BookmarkItem *item;
GList *l;
gchar **apps;
gsize i, n_apps;
g_return_val_if_fail (bookmark != NULL, NULL);
g_return_val_if_fail (uri != NULL, NULL);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return NULL;
}
if (!item->metadata)
{
if (length)
*length = 0;
return NULL;
}
n_apps = g_list_length (item->metadata->applications);
apps = g_new0 (gchar *, n_apps + 1);
for (l = g_list_last (item->metadata->applications), i = 0;
l != NULL;
l = l->prev)
{
BookmarkAppInfo *ai;
ai = (BookmarkAppInfo *) l->data;
g_warn_if_fail (ai != NULL);
g_warn_if_fail (ai->name != NULL);
apps[i++] = g_strdup (ai->name);
}
apps[i] = NULL;
if (length)
*length = i;
return apps;
}
/**
* g_bookmark_file_get_size:
* @bookmark: a #GBookmarkFile
*
* Gets the number of bookmarks inside @bookmark.
*
* Return value: the number of bookmarks
*
* Since: 2.12
*/
gint
g_bookmark_file_get_size (GBookmarkFile *bookmark)
{
g_return_val_if_fail (bookmark != NULL, 0);
return g_list_length (bookmark->items);
}
/**
* g_bookmark_file_move_item:
* @bookmark: a #GBookmarkFile
* @old_uri: a valid URI
* @new_uri: (allow-none): a valid URI, or %NULL
* @error: return location for a #GError or %NULL
*
* Changes the URI of a bookmark item from @old_uri to @new_uri. Any
* existing bookmark for @new_uri will be overwritten. If @new_uri is
* %NULL, then the bookmark is removed.
*
* In the event the URI cannot be found, %FALSE is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
*
* Return value: %TRUE if the URI was successfully changed
*
* Since: 2.12
*/
gboolean
g_bookmark_file_move_item (GBookmarkFile *bookmark,
const gchar *old_uri,
const gchar *new_uri,
GError **error)
{
BookmarkItem *item;
GError *remove_error;
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (old_uri != NULL, FALSE);
item = g_bookmark_file_lookup_item (bookmark, old_uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
old_uri);
return FALSE;
}
if (new_uri && new_uri[0] != '\0')
{
if (g_bookmark_file_has_item (bookmark, new_uri))
{
remove_error = NULL;
g_bookmark_file_remove_item (bookmark, new_uri, &remove_error);
if (remove_error)
{
g_propagate_error (error, remove_error);
return FALSE;
}
}
g_hash_table_steal (bookmark->items_by_uri, item->uri);
g_free (item->uri);
item->uri = g_strdup (new_uri);
item->modified = time (NULL);
g_hash_table_replace (bookmark->items_by_uri, item->uri, item);
return TRUE;
}
else
{
remove_error = NULL;
g_bookmark_file_remove_item (bookmark, old_uri, &remove_error);
if (remove_error)
{
g_propagate_error (error, remove_error);
return FALSE;
}
return TRUE;
}
}
/**
* g_bookmark_file_set_icon:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @href: (allow-none): the URI of the icon for the bookmark, or %NULL
* @mime_type: the MIME type of the icon for the bookmark
*
* Sets the icon for the bookmark for @uri. If @href is %NULL, unsets
* the currently set icon. @href can either be a full URL for the icon
* file or the icon name following the Icon Naming specification.
*
* If no bookmark for @uri is found one is created.
*
* Since: 2.12
*/
void
g_bookmark_file_set_icon (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *href,
const gchar *mime_type)
{
BookmarkItem *item;
g_return_if_fail (bookmark != NULL);
g_return_if_fail (uri != NULL);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
item = bookmark_item_new (uri);
g_bookmark_file_add_item (bookmark, item, NULL);
}
if (!item->metadata)
item->metadata = bookmark_metadata_new ();
g_free (item->metadata->icon_href);
g_free (item->metadata->icon_mime);
item->metadata->icon_href = g_strdup (href);
if (mime_type && mime_type[0] != '\0')
item->metadata->icon_mime = g_strdup (mime_type);
else
item->metadata->icon_mime = g_strdup ("application/octet-stream");
item->modified = time (NULL);
}
/**
* g_bookmark_file_get_icon:
* @bookmark: a #GBookmarkFile
* @uri: a valid URI
* @href: (allow-none) (out): return location for the icon's location or %NULL
* @mime_type: (allow-none) (out): return location for the icon's MIME type or %NULL
* @error: return location for a #GError or %NULL
*
* Gets the icon of the bookmark for @uri.
*
* In the event the URI cannot be found, %FALSE is returned and
* @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
*
* Return value: %TRUE if the icon for the bookmark for the URI was found.
* You should free the returned strings.
*
* Since: 2.12
*/
gboolean
g_bookmark_file_get_icon (GBookmarkFile *bookmark,
const gchar *uri,
gchar **href,
gchar **mime_type,
GError **error)
{
BookmarkItem *item;
g_return_val_if_fail (bookmark != NULL, FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
item = g_bookmark_file_lookup_item (bookmark, uri);
if (!item)
{
g_set_error (error, G_BOOKMARK_FILE_ERROR,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
_("No bookmark found for URI '%s'"),
uri);
return FALSE;
}
if ((!item->metadata) || (!item->metadata->icon_href))
return FALSE;
if (href)
*href = g_strdup (item->metadata->icon_href);
if (mime_type)
*mime_type = g_strdup (item->metadata->icon_mime);
return TRUE;
}
pkg-config-0.29.1/glib/glib/gbookmarkfile.h 0000664 0001750 0001750 00000022744 12651243552 015407 0000000 0000000 /* gbookmarkfile.h: parsing and building desktop bookmarks
*
* Copyright (C) 2005-2006 Emmanuele Bassi
*
* 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., 59 Temple Place - Suite 330,
*/
#ifndef __G_BOOKMARK_FILE_H__
#define __G_BOOKMARK_FILE_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
#include
G_BEGIN_DECLS
/**
* G_BOOKMARK_FILE_ERROR:
*
* Error domain for bookmark file parsing.
* Errors in this domain will be from the #GBookmarkFileError
* enumeration. See #GError for information on error domains.
*/
#define G_BOOKMARK_FILE_ERROR (g_bookmark_file_error_quark ())
/**
* GBookmarkFileError:
* @G_BOOKMARK_FILE_ERROR_INVALID_URI: URI was ill-formed
* @G_BOOKMARK_FILE_ERROR_INVALID_VALUE: a requested field was not found
* @G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED: a requested application did
* not register a bookmark
* @G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND: a requested URI was not found
* @G_BOOKMARK_FILE_ERROR_READ: document was ill formed
* @G_BOOKMARK_FILE_ERROR_UNKNOWN_ENCODING: the text being parsed was
* in an unknown encoding
* @G_BOOKMARK_FILE_ERROR_WRITE: an error occurred while writing
* @G_BOOKMARK_FILE_ERROR_FILE_NOT_FOUND: requested file was not found
*
* Error codes returned by bookmark file parsing.
*/
typedef enum
{
G_BOOKMARK_FILE_ERROR_INVALID_URI,
G_BOOKMARK_FILE_ERROR_INVALID_VALUE,
G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED,
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
G_BOOKMARK_FILE_ERROR_READ,
G_BOOKMARK_FILE_ERROR_UNKNOWN_ENCODING,
G_BOOKMARK_FILE_ERROR_WRITE,
G_BOOKMARK_FILE_ERROR_FILE_NOT_FOUND
} GBookmarkFileError;
GLIB_AVAILABLE_IN_ALL
GQuark g_bookmark_file_error_quark (void);
/**
* GBookmarkFile:
*
* The GBookmarkFile struct contains only
* private data and should not be directly accessed.
*/
typedef struct _GBookmarkFile GBookmarkFile;
GLIB_AVAILABLE_IN_ALL
GBookmarkFile *g_bookmark_file_new (void);
GLIB_AVAILABLE_IN_ALL
void g_bookmark_file_free (GBookmarkFile *bookmark);
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_load_from_file (GBookmarkFile *bookmark,
const gchar *filename,
GError **error);
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_load_from_data (GBookmarkFile *bookmark,
const gchar *data,
gsize length,
GError **error);
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_load_from_data_dirs (GBookmarkFile *bookmark,
const gchar *file,
gchar **full_path,
GError **error);
GLIB_AVAILABLE_IN_ALL
gchar * g_bookmark_file_to_data (GBookmarkFile *bookmark,
gsize *length,
GError **error) G_GNUC_MALLOC;
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_to_file (GBookmarkFile *bookmark,
const gchar *filename,
GError **error);
GLIB_AVAILABLE_IN_ALL
void g_bookmark_file_set_title (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *title);
GLIB_AVAILABLE_IN_ALL
gchar * g_bookmark_file_get_title (GBookmarkFile *bookmark,
const gchar *uri,
GError **error) G_GNUC_MALLOC;
GLIB_AVAILABLE_IN_ALL
void g_bookmark_file_set_description (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *description);
GLIB_AVAILABLE_IN_ALL
gchar * g_bookmark_file_get_description (GBookmarkFile *bookmark,
const gchar *uri,
GError **error) G_GNUC_MALLOC;
GLIB_AVAILABLE_IN_ALL
void g_bookmark_file_set_mime_type (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *mime_type);
GLIB_AVAILABLE_IN_ALL
gchar * g_bookmark_file_get_mime_type (GBookmarkFile *bookmark,
const gchar *uri,
GError **error) G_GNUC_MALLOC;
GLIB_AVAILABLE_IN_ALL
void g_bookmark_file_set_groups (GBookmarkFile *bookmark,
const gchar *uri,
const gchar **groups,
gsize length);
GLIB_AVAILABLE_IN_ALL
void g_bookmark_file_add_group (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *group);
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_has_group (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *group,
GError **error);
GLIB_AVAILABLE_IN_ALL
gchar ** g_bookmark_file_get_groups (GBookmarkFile *bookmark,
const gchar *uri,
gsize *length,
GError **error) G_GNUC_MALLOC;
GLIB_AVAILABLE_IN_ALL
void g_bookmark_file_add_application (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *name,
const gchar *exec);
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_has_application (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *name,
GError **error);
GLIB_AVAILABLE_IN_ALL
gchar ** g_bookmark_file_get_applications (GBookmarkFile *bookmark,
const gchar *uri,
gsize *length,
GError **error) G_GNUC_MALLOC;
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_set_app_info (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *name,
const gchar *exec,
gint count,
time_t stamp,
GError **error);
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_get_app_info (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *name,
gchar **exec,
guint *count,
time_t *stamp,
GError **error);
GLIB_AVAILABLE_IN_ALL
void g_bookmark_file_set_is_private (GBookmarkFile *bookmark,
const gchar *uri,
gboolean is_private);
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_get_is_private (GBookmarkFile *bookmark,
const gchar *uri,
GError **error);
GLIB_AVAILABLE_IN_ALL
void g_bookmark_file_set_icon (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *href,
const gchar *mime_type);
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_get_icon (GBookmarkFile *bookmark,
const gchar *uri,
gchar **href,
gchar **mime_type,
GError **error);
GLIB_AVAILABLE_IN_ALL
void g_bookmark_file_set_added (GBookmarkFile *bookmark,
const gchar *uri,
time_t added);
GLIB_AVAILABLE_IN_ALL
time_t g_bookmark_file_get_added (GBookmarkFile *bookmark,
const gchar *uri,
GError **error);
GLIB_AVAILABLE_IN_ALL
void g_bookmark_file_set_modified (GBookmarkFile *bookmark,
const gchar *uri,
time_t modified);
GLIB_AVAILABLE_IN_ALL
time_t g_bookmark_file_get_modified (GBookmarkFile *bookmark,
const gchar *uri,
GError **error);
GLIB_AVAILABLE_IN_ALL
void g_bookmark_file_set_visited (GBookmarkFile *bookmark,
const gchar *uri,
time_t visited);
GLIB_AVAILABLE_IN_ALL
time_t g_bookmark_file_get_visited (GBookmarkFile *bookmark,
const gchar *uri,
GError **error);
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_has_item (GBookmarkFile *bookmark,
const gchar *uri);
GLIB_AVAILABLE_IN_ALL
gint g_bookmark_file_get_size (GBookmarkFile *bookmark);
GLIB_AVAILABLE_IN_ALL
gchar ** g_bookmark_file_get_uris (GBookmarkFile *bookmark,
gsize *length) G_GNUC_MALLOC;
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_remove_group (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *group,
GError **error);
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_remove_application (GBookmarkFile *bookmark,
const gchar *uri,
const gchar *name,
GError **error);
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_remove_item (GBookmarkFile *bookmark,
const gchar *uri,
GError **error);
GLIB_AVAILABLE_IN_ALL
gboolean g_bookmark_file_move_item (GBookmarkFile *bookmark,
const gchar *old_uri,
const gchar *new_uri,
GError **error);
G_END_DECLS
#endif /* __G_BOOKMARK_FILE_H__ */
pkg-config-0.29.1/glib/glib/gmappedfile.c 0000664 0001750 0001750 00000025145 12651243552 015041 0000000 0000000 /* GLIB - Library of useful routines for C programming
* gmappedfile.c: Simplified wrapper around the mmap() function.
*
* Copyright 2005 Matthias Clasen
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include
#include
#include
#include
#ifdef HAVE_UNISTD_H
#include
#endif
#ifdef HAVE_MMAP
#include
#endif
#include "glibconfig.h"
#ifdef G_OS_WIN32
#include
#include
#undef fstat
#define fstat(a,b) _fstati64(a,b)
#undef stat
#define stat _stati64
#ifndef S_ISREG
#define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
#endif
#endif
#include "gconvert.h"
#include "gerror.h"
#include "gfileutils.h"
#include "gmappedfile.h"
#include "gmem.h"
#include "gmessages.h"
#include "gstdio.h"
#include "gstrfuncs.h"
#include "gatomic.h"
#include "glibintl.h"
#ifndef _O_BINARY
#define _O_BINARY 0
#endif
#ifndef MAP_FAILED
#define MAP_FAILED ((void *) -1)
#endif
/**
* GMappedFile:
*
* The #GMappedFile represents a file mapping created with
* g_mapped_file_new(). It has only private members and should
* not be accessed directly.
*/
struct _GMappedFile
{
gchar *contents;
gsize length;
gpointer free_func;
int ref_count;
#ifdef G_OS_WIN32
HANDLE mapping;
#endif
};
static void
g_mapped_file_destroy (GMappedFile *file)
{
if (file->length)
{
#ifdef HAVE_MMAP
munmap (file->contents, file->length);
#endif
#ifdef G_OS_WIN32
UnmapViewOfFile (file->contents);
CloseHandle (file->mapping);
#endif
}
g_slice_free (GMappedFile, file);
}
static GMappedFile*
mapped_file_new_from_fd (int fd,
gboolean writable,
const gchar *filename,
GError **error)
{
GMappedFile *file;
struct stat st;
file = g_slice_new0 (GMappedFile);
file->ref_count = 1;
file->free_func = g_mapped_file_destroy;
if (fstat (fd, &st) == -1)
{
int save_errno = errno;
gchar *display_filename = filename ? g_filename_display_name (filename) : NULL;
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (save_errno),
_("Failed to get attributes of file '%s%s%s%s': fstat() failed: %s"),
display_filename ? display_filename : "fd",
display_filename ? "' " : "",
display_filename ? display_filename : "",
display_filename ? "'" : "",
g_strerror (save_errno));
g_free (display_filename);
goto out;
}
/* mmap() on size 0 will fail with EINVAL, so we avoid calling mmap()
* in that case -- but only if we have a regular file; we still want
* attempts to mmap a character device to fail, for example.
*/
if (st.st_size == 0 && S_ISREG (st.st_mode))
{
file->length = 0;
file->contents = NULL;
return file;
}
file->contents = MAP_FAILED;
#ifdef HAVE_MMAP
if (st.st_size > G_MAXSIZE)
{
errno = EINVAL;
}
else
{
file->length = (gsize) st.st_size;
file->contents = (gchar *) mmap (NULL, file->length,
writable ? PROT_READ|PROT_WRITE : PROT_READ,
MAP_PRIVATE, fd, 0);
}
#endif
#ifdef G_OS_WIN32
file->length = st.st_size;
file->mapping = CreateFileMapping ((HANDLE) _get_osfhandle (fd), NULL,
writable ? PAGE_WRITECOPY : PAGE_READONLY,
0, 0,
NULL);
if (file->mapping != NULL)
{
file->contents = MapViewOfFile (file->mapping,
writable ? FILE_MAP_COPY : FILE_MAP_READ,
0, 0,
0);
if (file->contents == NULL)
{
file->contents = MAP_FAILED;
CloseHandle (file->mapping);
file->mapping = NULL;
}
}
#endif
if (file->contents == MAP_FAILED)
{
int save_errno = errno;
gchar *display_filename = filename ? g_filename_display_name (filename) : NULL;
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (save_errno),
_("Failed to map %s%s%s%s: mmap() failed: %s"),
display_filename ? display_filename : "fd",
display_filename ? "' " : "",
display_filename ? display_filename : "",
display_filename ? "'" : "",
g_strerror (save_errno));
g_free (display_filename);
goto out;
}
return file;
out:
g_slice_free (GMappedFile, file);
return NULL;
}
/**
* g_mapped_file_new:
* @filename: The path of the file to load, in the GLib filename encoding
* @writable: whether the mapping should be writable
* @error: return location for a #GError, or %NULL
*
* Maps a file into memory. On UNIX, this is using the mmap() function.
*
* If @writable is %TRUE, the mapped buffer may be modified, otherwise
* it is an error to modify the mapped buffer. Modifications to the buffer
* are not visible to other processes mapping the same file, and are not
* written back to the file.
*
* Note that modifications of the underlying file might affect the contents
* of the #GMappedFile. Therefore, mapping should only be used if the file
* will not be modified, or if all modifications of the file are done
* atomically (e.g. using g_file_set_contents()).
*
* If @filename is the name of an empty, regular file, the function
* will successfully return an empty #GMappedFile. In other cases of
* size 0 (e.g. device files such as /dev/null), @error will be set
* to the #GFileError value #G_FILE_ERROR_INVAL.
*
* Return value: a newly allocated #GMappedFile which must be unref'd
* with g_mapped_file_unref(), or %NULL if the mapping failed.
*
* Since: 2.8
*/
GMappedFile *
g_mapped_file_new (const gchar *filename,
gboolean writable,
GError **error)
{
GMappedFile *file;
int fd;
g_return_val_if_fail (filename != NULL, NULL);
g_return_val_if_fail (!error || *error == NULL, NULL);
fd = g_open (filename, (writable ? O_RDWR : O_RDONLY) | _O_BINARY, 0);
if (fd == -1)
{
int save_errno = errno;
gchar *display_filename = g_filename_display_name (filename);
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (save_errno),
_("Failed to open file '%s': open() failed: %s"),
display_filename,
g_strerror (save_errno));
g_free (display_filename);
return NULL;
}
file = mapped_file_new_from_fd (fd, writable, filename, error);
close (fd);
return file;
}
/**
* g_mapped_file_new_from_fd:
* @fd: The file descriptor of the file to load
* @writable: whether the mapping should be writable
* @error: return location for a #GError, or %NULL
*
* Maps a file into memory. On UNIX, this is using the mmap() function.
*
* If @writable is %TRUE, the mapped buffer may be modified, otherwise
* it is an error to modify the mapped buffer. Modifications to the buffer
* are not visible to other processes mapping the same file, and are not
* written back to the file.
*
* Note that modifications of the underlying file might affect the contents
* of the #GMappedFile. Therefore, mapping should only be used if the file
* will not be modified, or if all modifications of the file are done
* atomically (e.g. using g_file_set_contents()).
*
* Return value: a newly allocated #GMappedFile which must be unref'd
* with g_mapped_file_unref(), or %NULL if the mapping failed.
*
* Since: 2.32
*/
GMappedFile *
g_mapped_file_new_from_fd (gint fd,
gboolean writable,
GError **error)
{
return mapped_file_new_from_fd (fd, writable, NULL, error);
}
/**
* g_mapped_file_get_length:
* @file: a #GMappedFile
*
* Returns the length of the contents of a #GMappedFile.
*
* Returns: the length of the contents of @file.
*
* Since: 2.8
*/
gsize
g_mapped_file_get_length (GMappedFile *file)
{
g_return_val_if_fail (file != NULL, 0);
return file->length;
}
/**
* g_mapped_file_get_contents:
* @file: a #GMappedFile
*
* Returns the contents of a #GMappedFile.
*
* Note that the contents may not be zero-terminated,
* even if the #GMappedFile is backed by a text file.
*
* If the file is empty then %NULL is returned.
*
* Returns: the contents of @file, or %NULL.
*
* Since: 2.8
*/
gchar *
g_mapped_file_get_contents (GMappedFile *file)
{
g_return_val_if_fail (file != NULL, NULL);
return file->contents;
}
/**
* g_mapped_file_free:
* @file: a #GMappedFile
*
* This call existed before #GMappedFile had refcounting and is currently
* exactly the same as g_mapped_file_unref().
*
* Since: 2.8
* Deprecated:2.22: Use g_mapped_file_unref() instead.
*/
void
g_mapped_file_free (GMappedFile *file)
{
g_mapped_file_unref (file);
}
/**
* g_mapped_file_ref:
* @file: a #GMappedFile
*
* Increments the reference count of @file by one. It is safe to call
* this function from any thread.
*
* Return value: the passed in #GMappedFile.
*
* Since: 2.22
**/
GMappedFile *
g_mapped_file_ref (GMappedFile *file)
{
g_return_val_if_fail (file != NULL, NULL);
g_atomic_int_inc (&file->ref_count);
return file;
}
/**
* g_mapped_file_unref:
* @file: a #GMappedFile
*
* Decrements the reference count of @file by one. If the reference count
* drops to 0, unmaps the buffer of @file and frees it.
*
* It is safe to call this function from any thread.
*
* Since 2.22
**/
void
g_mapped_file_unref (GMappedFile *file)
{
g_return_if_fail (file != NULL);
if (g_atomic_int_dec_and_test (&file->ref_count))
g_mapped_file_destroy (file);
}
/**
* g_mapped_file_get_bytes:
* @file: a #GMappedFile
*
* Creates a new #GBytes which references the data mapped from @file.
* The mapped contents of the file must not be modified after creating this
* bytes object, because a #GBytes should be immutable.
*
* Returns: (transfer full): A newly allocated #GBytes referencing data
* from @file
*
* Since: 2.34
**/
GBytes *
g_mapped_file_get_bytes (GMappedFile *file)
{
g_return_val_if_fail (file != NULL, NULL);
return g_bytes_new_with_free_func (file->contents,
file->length,
(GDestroyNotify) g_mapped_file_unref,
g_mapped_file_ref (file));
}
pkg-config-0.29.1/glib/glib/gpattern.h 0000664 0001750 0001750 00000003474 12651243552 014416 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997, 1999 Peter Mattis, Red Hat, Inc.
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __G_PATTERN_H__
#define __G_PATTERN_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
G_BEGIN_DECLS
typedef struct _GPatternSpec GPatternSpec;
GLIB_AVAILABLE_IN_ALL
GPatternSpec* g_pattern_spec_new (const gchar *pattern);
GLIB_AVAILABLE_IN_ALL
void g_pattern_spec_free (GPatternSpec *pspec);
GLIB_AVAILABLE_IN_ALL
gboolean g_pattern_spec_equal (GPatternSpec *pspec1,
GPatternSpec *pspec2);
GLIB_AVAILABLE_IN_ALL
gboolean g_pattern_match (GPatternSpec *pspec,
guint string_length,
const gchar *string,
const gchar *string_reversed);
GLIB_AVAILABLE_IN_ALL
gboolean g_pattern_match_string (GPatternSpec *pspec,
const gchar *string);
GLIB_AVAILABLE_IN_ALL
gboolean g_pattern_match_simple (const gchar *pattern,
const gchar *string);
G_END_DECLS
#endif /* __G_PATTERN_H__ */
pkg-config-0.29.1/glib/glib/gcharset.c 0000664 0001750 0001750 00000035624 12651243552 014367 0000000 0000000 /* gcharset.c - Charset information
*
* Copyright (C) 2011 Red Hat, Inc.
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gcharsetprivate.h"
#include "garray.h"
#include "genviron.h"
#include "ghash.h"
#include "gmessages.h"
#include "gstrfuncs.h"
#include "gthread.h"
#ifdef G_OS_WIN32
#include "gwin32.h"
#endif
#include "libcharset/libcharset.h"
#include
#include
G_LOCK_DEFINE_STATIC (aliases);
static GHashTable *
get_alias_hash (void)
{
static GHashTable *alias_hash = NULL;
const char *aliases;
G_LOCK (aliases);
if (!alias_hash)
{
alias_hash = g_hash_table_new (g_str_hash, g_str_equal);
aliases = _g_locale_get_charset_aliases ();
while (*aliases != '\0')
{
const char *canonical;
const char *alias;
const char **alias_array;
int count = 0;
alias = aliases;
aliases += strlen (aliases) + 1;
canonical = aliases;
aliases += strlen (aliases) + 1;
alias_array = g_hash_table_lookup (alias_hash, canonical);
if (alias_array)
{
while (alias_array[count])
count++;
}
alias_array = g_renew (const char *, alias_array, count + 2);
alias_array[count] = alias;
alias_array[count + 1] = NULL;
g_hash_table_insert (alias_hash, (char *)canonical, alias_array);
}
}
G_UNLOCK (aliases);
return alias_hash;
}
/* As an abuse of the alias table, the following routines gets
* the charsets that are aliases for the canonical name.
*/
const char **
_g_charset_get_aliases (const char *canonical_name)
{
GHashTable *alias_hash = get_alias_hash ();
return g_hash_table_lookup (alias_hash, canonical_name);
}
static gboolean
g_utf8_get_charset_internal (const char *raw_data,
const char **a)
{
const char *charset = g_getenv ("CHARSET");
if (charset && *charset)
{
*a = charset;
if (charset && strstr (charset, "UTF-8"))
return TRUE;
else
return FALSE;
}
/* The libcharset code tries to be thread-safe without
* a lock, but has a memory leak and a missing memory
* barrier, so we lock for it
*/
G_LOCK (aliases);
charset = _g_locale_charset_unalias (raw_data);
G_UNLOCK (aliases);
if (charset && *charset)
{
*a = charset;
if (charset && strstr (charset, "UTF-8"))
return TRUE;
else
return FALSE;
}
/* Assume this for compatibility at present. */
*a = "US-ASCII";
return FALSE;
}
typedef struct _GCharsetCache GCharsetCache;
struct _GCharsetCache {
gboolean is_utf8;
gchar *raw;
gchar *charset;
};
static void
charset_cache_free (gpointer data)
{
GCharsetCache *cache = data;
g_free (cache->raw);
g_free (cache->charset);
g_free (cache);
}
/**
* g_get_charset:
* @charset: return location for character set name
*
* Obtains the character set for the current
* locale; you might use this character set as an argument to
* g_convert(), to convert from the current locale's encoding to some
* other encoding. (Frequently g_locale_to_utf8() and g_locale_from_utf8()
* are nice shortcuts, though.)
*
* On Windows the character set returned by this function is the
* so-called system default ANSI code-page. That is the character set
* used by the "narrow" versions of C library and Win32 functions that
* handle file names. It might be different from the character set
* used by the C library's current locale.
*
* The return value is %TRUE if the locale's encoding is UTF-8, in that
* case you can perhaps avoid calling g_convert().
*
* The string returned in @charset is not allocated, and should not be
* freed.
*
* Return value: %TRUE if the returned charset is UTF-8
*/
gboolean
g_get_charset (const char **charset)
{
static GPrivate cache_private = G_PRIVATE_INIT (charset_cache_free);
GCharsetCache *cache = g_private_get (&cache_private);
const gchar *raw;
if (!cache)
{
cache = g_new0 (GCharsetCache, 1);
g_private_set (&cache_private, cache);
}
G_LOCK (aliases);
raw = _g_locale_charset_raw ();
G_UNLOCK (aliases);
if (!(cache->raw && strcmp (cache->raw, raw) == 0))
{
const gchar *new_charset;
g_free (cache->raw);
g_free (cache->charset);
cache->raw = g_strdup (raw);
cache->is_utf8 = g_utf8_get_charset_internal (raw, &new_charset);
cache->charset = g_strdup (new_charset);
}
if (charset)
*charset = cache->charset;
return cache->is_utf8;
}
/**
* g_get_codeset:
*
* Gets the character set for the current locale.
*
* Return value: a newly allocated string containing the name
* of the character set. This string must be freed with g_free().
*/
gchar *
g_get_codeset (void)
{
const gchar *charset;
g_get_charset (&charset);
return g_strdup (charset);
}
#ifndef G_OS_WIN32
static GHashTable *alias_table = NULL;
/* read an alias file for the locales */
static void
read_aliases (gchar *file)
{
FILE *fp;
char buf[256];
if (!alias_table)
alias_table = g_hash_table_new (g_str_hash, g_str_equal);
fp = fopen (file,"r");
if (!fp)
return;
while (fgets (buf, 256, fp))
{
char *p, *q;
g_strstrip (buf);
/* Line is a comment */
if ((buf[0] == '#') || (buf[0] == '\0'))
continue;
/* Reads first column */
for (p = buf, q = NULL; *p; p++) {
if ((*p == '\t') || (*p == ' ') || (*p == ':')) {
*p = '\0';
q = p+1;
while ((*q == '\t') || (*q == ' ')) {
q++;
}
break;
}
}
/* The line only had one column */
if (!q || *q == '\0')
continue;
/* Read second column */
for (p = q; *p; p++) {
if ((*p == '\t') || (*p == ' ')) {
*p = '\0';
break;
}
}
/* Add to alias table if necessary */
if (!g_hash_table_lookup (alias_table, buf)) {
g_hash_table_insert (alias_table, g_strdup (buf), g_strdup (q));
}
}
fclose (fp);
}
#endif
static char *
unalias_lang (char *lang)
{
#ifndef G_OS_WIN32
char *p;
int i;
if (!alias_table)
read_aliases ("/usr/share/locale/locale.alias");
i = 0;
while ((p = g_hash_table_lookup (alias_table, lang)) && (strcmp (p, lang) != 0))
{
lang = p;
if (i++ == 30)
{
static gboolean said_before = FALSE;
if (!said_before)
g_warning ("Too many alias levels for a locale, "
"may indicate a loop");
said_before = TRUE;
return lang;
}
}
#endif
return lang;
}
/* Mask for components of locale spec. The ordering here is from
* least significant to most significant
*/
enum
{
COMPONENT_CODESET = 1 << 0,
COMPONENT_TERRITORY = 1 << 1,
COMPONENT_MODIFIER = 1 << 2
};
/* Break an X/Open style locale specification into components
*/
static guint
explode_locale (const gchar *locale,
gchar **language,
gchar **territory,
gchar **codeset,
gchar **modifier)
{
const gchar *uscore_pos;
const gchar *at_pos;
const gchar *dot_pos;
guint mask = 0;
uscore_pos = strchr (locale, '_');
dot_pos = strchr (uscore_pos ? uscore_pos : locale, '.');
at_pos = strchr (dot_pos ? dot_pos : (uscore_pos ? uscore_pos : locale), '@');
if (at_pos)
{
mask |= COMPONENT_MODIFIER;
*modifier = g_strdup (at_pos);
}
else
at_pos = locale + strlen (locale);
if (dot_pos)
{
mask |= COMPONENT_CODESET;
*codeset = g_strndup (dot_pos, at_pos - dot_pos);
}
else
dot_pos = at_pos;
if (uscore_pos)
{
mask |= COMPONENT_TERRITORY;
*territory = g_strndup (uscore_pos, dot_pos - uscore_pos);
}
else
uscore_pos = dot_pos;
*language = g_strndup (locale, uscore_pos - locale);
return mask;
}
/*
* Compute all interesting variants for a given locale name -
* by stripping off different components of the value.
*
* For simplicity, we assume that the locale is in
* X/Open format: language[_territory][.codeset][@modifier]
*
* TODO: Extend this to handle the CEN format (see the GNUlibc docs)
* as well. We could just copy the code from glibc wholesale
* but it is big, ugly, and complicated, so I'm reluctant
* to do so when this should handle 99% of the time...
*/
static void
append_locale_variants (GPtrArray *array,
const gchar *locale)
{
gchar *language = NULL;
gchar *territory = NULL;
gchar *codeset = NULL;
gchar *modifier = NULL;
guint mask;
guint i, j;
g_return_if_fail (locale != NULL);
mask = explode_locale (locale, &language, &territory, &codeset, &modifier);
/* Iterate through all possible combinations, from least attractive
* to most attractive.
*/
for (j = 0; j <= mask; ++j)
{
i = mask - j;
if ((i & ~mask) == 0)
{
gchar *val = g_strconcat (language,
(i & COMPONENT_TERRITORY) ? territory : "",
(i & COMPONENT_CODESET) ? codeset : "",
(i & COMPONENT_MODIFIER) ? modifier : "",
NULL);
g_ptr_array_add (array, val);
}
}
g_free (language);
if (mask & COMPONENT_CODESET)
g_free (codeset);
if (mask & COMPONENT_TERRITORY)
g_free (territory);
if (mask & COMPONENT_MODIFIER)
g_free (modifier);
}
/**
* g_get_locale_variants:
* @locale: a locale identifier
*
* Returns a list of derived variants of @locale, which can be used to
* e.g. construct locale-dependent filenames or search paths. The returned
* list is sorted from most desirable to least desirable.
* This function handles territory, charset and extra locale modifiers.
*
* For example, if @locale is "fr_BE", then the returned list
* is "fr_BE", "fr".
*
* If you need the list of variants for the current locale,
* use g_get_language_names().
*
* Returns: (transfer full) (array zero-terminated=1) (element-type utf8): a newly
* allocated array of newly allocated strings with the locale variants. Free with
* g_strfreev().
*
* Since: 2.28
*/
gchar **
g_get_locale_variants (const gchar *locale)
{
GPtrArray *array;
g_return_val_if_fail (locale != NULL, NULL);
array = g_ptr_array_sized_new (8);
append_locale_variants (array, locale);
g_ptr_array_add (array, NULL);
return (gchar **) g_ptr_array_free (array, FALSE);
}
/* The following is (partly) taken from the gettext package.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. */
static const gchar *
guess_category_value (const gchar *category_name)
{
const gchar *retval;
/* The highest priority value is the 'LANGUAGE' environment
variable. This is a GNU extension. */
retval = g_getenv ("LANGUAGE");
if ((retval != NULL) && (retval[0] != '\0'))
return retval;
/* 'LANGUAGE' is not set. So 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. */
/* Setting of LC_ALL overwrites all other. */
retval = g_getenv ("LC_ALL");
if ((retval != NULL) && (retval[0] != '\0'))
return retval;
/* Next comes the name of the desired category. */
retval = g_getenv (category_name);
if ((retval != NULL) && (retval[0] != '\0'))
return retval;
/* Last possibility is the LANG environment variable. */
retval = g_getenv ("LANG");
if ((retval != NULL) && (retval[0] != '\0'))
return retval;
#ifdef G_PLATFORM_WIN32
/* g_win32_getlocale() first checks for LC_ALL, LC_MESSAGES and
* LANG, which we already did above. Oh well. The main point of
* calling g_win32_getlocale() is to get the thread's locale as used
* by Windows and the Microsoft C runtime (in the "English_United
* States" format) translated into the Unixish format.
*/
{
char *locale = g_win32_getlocale ();
retval = g_intern_string (locale);
g_free (locale);
return retval;
}
#endif
return NULL;
}
typedef struct _GLanguageNamesCache GLanguageNamesCache;
struct _GLanguageNamesCache {
gchar *languages;
gchar **language_names;
};
static void
language_names_cache_free (gpointer data)
{
GLanguageNamesCache *cache = data;
g_free (cache->languages);
g_strfreev (cache->language_names);
g_free (cache);
}
/**
* g_get_language_names:
*
* Computes a list of applicable locale names, which can be used to
* e.g. construct locale-dependent filenames or search paths. The returned
* list is sorted from most desirable to least desirable and always contains
* the default locale "C".
*
* For example, if LANGUAGE=de:en_US, then the returned list is
* "de", "en_US", "en", "C".
*
* This function consults the environment variables LANGUAGE,
* LC_ALL, LC_MESSAGES and LANG
* to find the list of locales specified by the user.
*
* Return value: (array zero-terminated=1) (transfer none): a %NULL-terminated array of strings owned by GLib
* that must not be modified or freed.
*
* Since: 2.6
**/
const gchar * const *
g_get_language_names (void)
{
static GPrivate cache_private = G_PRIVATE_INIT (language_names_cache_free);
GLanguageNamesCache *cache = g_private_get (&cache_private);
const gchar *value;
if (!cache)
{
cache = g_new0 (GLanguageNamesCache, 1);
g_private_set (&cache_private, cache);
}
value = guess_category_value ("LC_MESSAGES");
if (!value)
value = "C";
if (!(cache->languages && strcmp (cache->languages, value) == 0))
{
GPtrArray *array;
gchar **alist, **a;
g_free (cache->languages);
g_strfreev (cache->language_names);
cache->languages = g_strdup (value);
array = g_ptr_array_sized_new (8);
alist = g_strsplit (value, ":", 0);
for (a = alist; *a; a++)
append_locale_variants (array, unalias_lang (*a));
g_strfreev (alist);
g_ptr_array_add (array, g_strdup ("C"));
g_ptr_array_add (array, NULL);
cache->language_names = (gchar **) g_ptr_array_free (array, FALSE);
}
return (const gchar * const *) cache->language_names;
}
pkg-config-0.29.1/glib/glib/gthreadpool.h 0000664 0001750 0001750 00000007213 12651243552 015075 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __G_THREADPOOL_H__
#define __G_THREADPOOL_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
G_BEGIN_DECLS
typedef struct _GThreadPool GThreadPool;
/* Thread Pools
*/
struct _GThreadPool
{
GFunc func;
gpointer user_data;
gboolean exclusive;
};
GLIB_AVAILABLE_IN_ALL
GThreadPool * g_thread_pool_new (GFunc func,
gpointer user_data,
gint max_threads,
gboolean exclusive,
GError **error);
GLIB_AVAILABLE_IN_ALL
void g_thread_pool_free (GThreadPool *pool,
gboolean immediate,
gboolean wait_);
GLIB_AVAILABLE_IN_ALL
gboolean g_thread_pool_push (GThreadPool *pool,
gpointer data,
GError **error);
GLIB_AVAILABLE_IN_ALL
guint g_thread_pool_unprocessed (GThreadPool *pool);
GLIB_AVAILABLE_IN_ALL
void g_thread_pool_set_sort_function (GThreadPool *pool,
GCompareDataFunc func,
gpointer user_data);
GLIB_AVAILABLE_IN_ALL
gboolean g_thread_pool_set_max_threads (GThreadPool *pool,
gint max_threads,
GError **error);
GLIB_AVAILABLE_IN_ALL
gint g_thread_pool_get_max_threads (GThreadPool *pool);
GLIB_AVAILABLE_IN_ALL
guint g_thread_pool_get_num_threads (GThreadPool *pool);
GLIB_AVAILABLE_IN_ALL
void g_thread_pool_set_max_unused_threads (gint max_threads);
GLIB_AVAILABLE_IN_ALL
gint g_thread_pool_get_max_unused_threads (void);
GLIB_AVAILABLE_IN_ALL
guint g_thread_pool_get_num_unused_threads (void);
GLIB_AVAILABLE_IN_ALL
void g_thread_pool_stop_unused_threads (void);
GLIB_AVAILABLE_IN_ALL
void g_thread_pool_set_max_idle_time (guint interval);
GLIB_AVAILABLE_IN_ALL
guint g_thread_pool_get_max_idle_time (void);
G_END_DECLS
#endif /* __G_THREADPOOL_H__ */
pkg-config-0.29.1/glib/glib/glib-unix.c 0000664 0001750 0001750 00000027774 12651243552 014474 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 2011 Red Hat, Inc.
*
* glib-unix.c: UNIX specific API wrappers and convenience functions
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Colin Walters
*/
#include "config.h"
/* To make bionic export pipe2() */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include "glib-unix.h"
#include "gmain-internal.h"
#include
/**
* SECTION:gunix
* @title: UNIX-specific utilities and integration
* @short_description: pipes, signal handling
* @include: glib-unix.h
*
* Most of GLib is intended to be portable; in contrast, this set of
* functions is designed for programs which explicitly target UNIX,
* or are using it to build higher level abstractions which would be
* conditionally compiled if the platform matches G_OS_UNIX.
*
* To use these functions, you must explicitly include the
* "glib-unix.h" header.
*/
G_DEFINE_QUARK (g-unix-error-quark, g_unix_error)
static gboolean
g_unix_set_error_from_errno (GError **error,
gint saved_errno)
{
g_set_error_literal (error,
G_UNIX_ERROR,
0,
g_strerror (saved_errno));
errno = saved_errno;
return FALSE;
}
/**
* g_unix_open_pipe:
* @fds: Array of two integers
* @flags: Bitfield of file descriptor flags, see "man 2 fcntl"
* @error: a #GError
*
* Similar to the UNIX pipe() call, but on modern systems like Linux
* uses the pipe2() system call, which atomically creates a pipe with
* the configured flags. The only supported flag currently is
* FD_CLOEXEC. If for example you want to configure
* O_NONBLOCK, that must still be done separately with
* fcntl().
*
* This function does *not* take O_CLOEXEC, it takes
* FD_CLOEXEC as if for fcntl(); these are
* different on Linux/glibc.
*
* Returns: %TRUE on success, %FALSE if not (and errno will be set).
*
* Since: 2.30
*/
gboolean
g_unix_open_pipe (int *fds,
int flags,
GError **error)
{
int ecode;
/* We only support FD_CLOEXEC */
g_return_val_if_fail ((flags & (FD_CLOEXEC)) == flags, FALSE);
#ifdef HAVE_PIPE2
{
int pipe2_flags = 0;
if (flags & FD_CLOEXEC)
pipe2_flags |= O_CLOEXEC;
/* Atomic */
ecode = pipe2 (fds, pipe2_flags);
if (ecode == -1 && errno != ENOSYS)
return g_unix_set_error_from_errno (error, errno);
else if (ecode == 0)
return TRUE;
/* Fall through on -ENOSYS, we must be running on an old kernel */
}
#endif
ecode = pipe (fds);
if (ecode == -1)
return g_unix_set_error_from_errno (error, errno);
if (flags == 0)
return TRUE;
ecode = fcntl (fds[0], F_SETFD, flags);
if (ecode == -1)
{
int saved_errno = errno;
close (fds[0]);
close (fds[1]);
return g_unix_set_error_from_errno (error, saved_errno);
}
ecode = fcntl (fds[1], F_SETFD, flags);
if (ecode == -1)
{
int saved_errno = errno;
close (fds[0]);
close (fds[1]);
return g_unix_set_error_from_errno (error, saved_errno);
}
return TRUE;
}
/**
* g_unix_set_fd_nonblocking:
* @fd: A file descriptor
* @nonblock: If %TRUE, set the descriptor to be non-blocking
* @error: a #GError
*
* Control the non-blocking state of the given file descriptor,
* according to @nonblock. On most systems this uses O_NONBLOCK, but
* on some older ones may use O_NDELAY.
*
* Returns: %TRUE if successful
*
* Since: 2.30
*/
gboolean
g_unix_set_fd_nonblocking (gint fd,
gboolean nonblock,
GError **error)
{
#ifdef F_GETFL
glong fcntl_flags;
fcntl_flags = fcntl (fd, F_GETFL);
if (fcntl_flags == -1)
return g_unix_set_error_from_errno (error, errno);
if (nonblock)
{
#ifdef O_NONBLOCK
fcntl_flags |= O_NONBLOCK;
#else
fcntl_flags |= O_NDELAY;
#endif
}
else
{
#ifdef O_NONBLOCK
fcntl_flags &= ~O_NONBLOCK;
#else
fcntl_flags &= ~O_NDELAY;
#endif
}
if (fcntl (fd, F_SETFL, fcntl_flags) == -1)
return g_unix_set_error_from_errno (error, errno);
return TRUE;
#else
return g_unix_set_error_from_errno (error, EINVAL);
#endif
}
/**
* g_unix_signal_source_new:
* @signum: A signal number
*
* Create a #GSource that will be dispatched upon delivery of the UNIX
* signal @signum. In GLib versions before 2.36, only
* SIGHUP, SIGINT,
* SIGTERM can be monitored. In GLib 2.36,
* SIGUSR1 and SIGUSR2 were
* added.
*
* Note that unlike the UNIX default, all sources which have created a
* watch will be dispatched, regardless of which underlying thread
* invoked g_unix_signal_source_new().
*
* For example, an effective use of this function is to handle SIGTERM
* cleanly; flushing any outstanding files, and then calling
* g_main_loop_quit (). It is not safe to do any of this a regular
* UNIX signal handler; your handler may be invoked while malloc() or
* another library function is running, causing reentrancy if you
* attempt to use it from the handler. None of the GLib/GObject API
* is safe against this kind of reentrancy.
*
* The interaction of this source when combined with native UNIX
* functions like sigprocmask() is not defined.
*
* The source will not initially be associated with any #GMainContext
* and must be added to one with g_source_attach() before it will be
* executed.
*
* Returns: A newly created #GSource
*
* Since: 2.30
*/
GSource *
g_unix_signal_source_new (int signum)
{
g_return_val_if_fail (signum == SIGHUP || signum == SIGINT || signum == SIGTERM ||
signum == SIGUSR1 || signum == SIGUSR2, NULL);
return _g_main_create_unix_signal_watch (signum);
}
/**
* g_unix_signal_add_full:
* @priority: the priority of the signal source. Typically this will be in
* the range between #G_PRIORITY_DEFAULT and #G_PRIORITY_HIGH.
* @signum: Signal number
* @handler: Callback
* @user_data: Data for @handler
* @notify: #GDestroyNotify for @handler
*
* A convenience function for g_unix_signal_source_new(), which
* attaches to the default #GMainContext. You can remove the watch
* using g_source_remove().
*
* Returns: An ID (greater than 0) for the event source
*
* Rename to: g_unix_signal_add
* Since: 2.30
*/
guint
g_unix_signal_add_full (int priority,
int signum,
GSourceFunc handler,
gpointer user_data,
GDestroyNotify notify)
{
guint id;
GSource *source;
source = g_unix_signal_source_new (signum);
if (priority != G_PRIORITY_DEFAULT)
g_source_set_priority (source, priority);
g_source_set_callback (source, handler, user_data, notify);
id = g_source_attach (source, NULL);
g_source_unref (source);
return id;
}
/**
* g_unix_signal_add:
* @signum: Signal number
* @handler: Callback
* @user_data: Data for @handler
*
* A convenience function for g_unix_signal_source_new(), which
* attaches to the default #GMainContext. You can remove the watch
* using g_source_remove().
*
* Returns: An ID (greater than 0) for the event source
*
* Since: 2.30
*/
guint
g_unix_signal_add (int signum,
GSourceFunc handler,
gpointer user_data)
{
return g_unix_signal_add_full (G_PRIORITY_DEFAULT, signum, handler, user_data, NULL);
}
typedef struct
{
GSource source;
gint fd;
gpointer tag;
} GUnixFDSource;
static gboolean
g_unix_fd_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
GUnixFDSource *fd_source = (GUnixFDSource *) source;
GUnixFDSourceFunc func = (GUnixFDSourceFunc) callback;
if (!callback)
{
g_warning ("GUnixFDSource dispatched without callback\n"
"You must call g_source_set_callback().");
return FALSE;
}
return (* func) (fd_source->fd, g_source_query_unix_fd (source, fd_source->tag), user_data);
}
GSourceFuncs g_unix_fd_source_funcs = {
NULL, NULL, g_unix_fd_source_dispatch, NULL
};
/**
* g_unix_fd_source_new:
* @fd: a file descriptor
* @condition: IO conditions to watch for on @fd
*
* Creates a #GSource to watch for a particular IO condition on a file
* descriptor.
*
* The source will never close the fd -- you must do it yourself.
*
* Returns: the newly created #GSource
*
* Since: 2.36
**/
GSource *
g_unix_fd_source_new (gint fd,
GIOCondition condition)
{
GUnixFDSource *fd_source;
GSource *source;
source = g_source_new (&g_unix_fd_source_funcs, sizeof (GUnixFDSource));
fd_source = (GUnixFDSource *) source;
fd_source->fd = fd;
fd_source->tag = g_source_add_unix_fd (source, fd, condition);
return source;
}
/**
* g_unix_fd_add_full:
* @priority: the priority of the source
* @fd: a file descriptor
* @condition: IO conditions to watch for on @fd
* @function: a #GUnixFDSourceFunc
* @user_data: data to pass to @function
* @notify: function to call when the idle is removed, or %NULL
*
* Sets a function to be called when the IO condition, as specified by
* @condition becomes true for @fd.
*
* This is the same as g_unix_fd_add(), except that it allows you to
* specify a non-default priority and a provide a #GDestroyNotify for
* @user_data.
*
* Returns: the ID (greater than 0) of the event source
*
* Since: 2.36
**/
guint
g_unix_fd_add_full (gint priority,
gint fd,
GIOCondition condition,
GUnixFDSourceFunc function,
gpointer user_data,
GDestroyNotify notify)
{
GSource *source;
guint id;
g_return_val_if_fail (function != NULL, 0);
source = g_unix_fd_source_new (fd, condition);
if (priority != G_PRIORITY_DEFAULT)
g_source_set_priority (source, priority);
g_source_set_callback (source, (GSourceFunc) function, user_data, notify);
id = g_source_attach (source, NULL);
g_source_unref (source);
return id;
}
/**
* g_unix_fd_add:
* @fd: a file descriptor
* @condition: IO conditions to watch for on @fd
* @function: a #GPollFDFunc
* @user_data: data to pass to @function
*
* Sets a function to be called when the IO condition, as specified by
* @condition becomes true for @fd.
*
* @function will be called when the specified IO condition becomes
* %TRUE. The function is expected to clear whatever event caused the
* IO condition to become true and return %TRUE in order to be notified
* when it happens again. If @function returns %FALSE then the watch
* will be cancelled.
*
* The return value of this function can be passed to g_source_remove()
* to cancel the watch at any time that it exists.
*
* The source will never close the fd -- you must do it yourself.
*
* Returns: the ID (greater than 0) of the event source
*
* Since: 2.36
**/
guint
g_unix_fd_add (gint fd,
GIOCondition condition,
GUnixFDSourceFunc function,
gpointer user_data)
{
return g_unix_fd_add_full (G_PRIORITY_DEFAULT, fd, condition, function, user_data, NULL);
}
pkg-config-0.29.1/glib/glib/gmessages.h 0000664 0001750 0001750 00000033631 12651243552 014546 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __G_MESSAGES_H__
#define __G_MESSAGES_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
#include
#include
/* Suppress warnings when GCC is in -pedantic mode and not -std=c99
*/
#if (__GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
#pragma GCC system_header
#endif
G_BEGIN_DECLS
/* calculate a string size, guaranteed to fit format + args.
*/
GLIB_AVAILABLE_IN_ALL
gsize g_printf_string_upper_bound (const gchar* format,
va_list args) G_GNUC_PRINTF(1, 0);
/* Log level shift offset for user defined
* log levels (0-7 are used by GLib).
*/
#define G_LOG_LEVEL_USER_SHIFT (8)
/* Glib log levels and flags.
*/
typedef enum
{
/* log flags */
G_LOG_FLAG_RECURSION = 1 << 0,
G_LOG_FLAG_FATAL = 1 << 1,
/* GLib log levels */
G_LOG_LEVEL_ERROR = 1 << 2, /* always fatal */
G_LOG_LEVEL_CRITICAL = 1 << 3,
G_LOG_LEVEL_WARNING = 1 << 4,
G_LOG_LEVEL_MESSAGE = 1 << 5,
G_LOG_LEVEL_INFO = 1 << 6,
G_LOG_LEVEL_DEBUG = 1 << 7,
G_LOG_LEVEL_MASK = ~(G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL)
} GLogLevelFlags;
/* GLib log levels that are considered fatal by default */
#define G_LOG_FATAL_MASK (G_LOG_FLAG_RECURSION | G_LOG_LEVEL_ERROR)
typedef void (*GLogFunc) (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data);
/* Logging mechanism
*/
GLIB_AVAILABLE_IN_ALL
guint g_log_set_handler (const gchar *log_domain,
GLogLevelFlags log_levels,
GLogFunc log_func,
gpointer user_data);
GLIB_AVAILABLE_IN_ALL
void g_log_remove_handler (const gchar *log_domain,
guint handler_id);
GLIB_AVAILABLE_IN_ALL
void g_log_default_handler (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer unused_data);
GLIB_AVAILABLE_IN_ALL
GLogFunc g_log_set_default_handler (GLogFunc log_func,
gpointer user_data);
GLIB_AVAILABLE_IN_ALL
void g_log (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *format,
...) G_GNUC_PRINTF (3, 4);
GLIB_AVAILABLE_IN_ALL
void g_logv (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *format,
va_list args) G_GNUC_PRINTF(3, 0);
GLIB_AVAILABLE_IN_ALL
GLogLevelFlags g_log_set_fatal_mask (const gchar *log_domain,
GLogLevelFlags fatal_mask);
GLIB_AVAILABLE_IN_ALL
GLogLevelFlags g_log_set_always_fatal (GLogLevelFlags fatal_mask);
/* internal */
void _g_log_fallback_handler (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer unused_data);
/* Internal functions, used to implement the following macros */
GLIB_AVAILABLE_IN_ALL
void g_return_if_fail_warning (const char *log_domain,
const char *pretty_function,
const char *expression) G_ANALYZER_NORETURN;
GLIB_AVAILABLE_IN_ALL
void g_warn_message (const char *domain,
const char *file,
int line,
const char *func,
const char *warnexpr) G_ANALYZER_NORETURN;
GLIB_DEPRECATED
void g_assert_warning (const char *log_domain,
const char *file,
const int line,
const char *pretty_function,
const char *expression) G_GNUC_NORETURN;
#ifndef G_LOG_DOMAIN
#define G_LOG_DOMAIN ((gchar*) 0)
#endif /* G_LOG_DOMAIN */
#if defined(G_HAVE_ISO_VARARGS) && !G_ANALYZER_ANALYZING
/* for(;;) ; so that GCC knows that control doesn't go past g_error().
* Put space before ending semicolon to avoid C++ build warnings.
*/
#define g_error(...) G_STMT_START { \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_ERROR, \
__VA_ARGS__); \
for (;;) ; \
} G_STMT_END
#define g_message(...) g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_MESSAGE, \
__VA_ARGS__)
#define g_critical(...) g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
__VA_ARGS__)
#define g_warning(...) g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_WARNING, \
__VA_ARGS__)
#define g_debug(...) g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_DEBUG, \
__VA_ARGS__)
#elif defined(G_HAVE_GNUC_VARARGS) && !G_ANALYZER_ANALYZING
#define g_error(format...) G_STMT_START { \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_ERROR, \
format); \
for (;;) ; \
} G_STMT_END
#define g_message(format...) g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_MESSAGE, \
format)
#define g_critical(format...) g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
format)
#define g_warning(format...) g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_WARNING, \
format)
#define g_debug(format...) g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_DEBUG, \
format)
#else /* no varargs macros */
static void g_error (const gchar *format, ...) G_ANALYZER_NORETURN;
static void g_critical (const gchar *format, ...) G_ANALYZER_NORETURN;
static void
g_error (const gchar *format,
...)
{
va_list args;
va_start (args, format);
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, format, args);
va_end (args);
for(;;) ;
}
static void
g_message (const gchar *format,
...)
{
va_list args;
va_start (args, format);
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, format, args);
va_end (args);
}
static void
g_critical (const gchar *format,
...)
{
va_list args;
va_start (args, format);
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, format, args);
va_end (args);
}
static void
g_warning (const gchar *format,
...)
{
va_list args;
va_start (args, format);
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, format, args);
va_end (args);
}
static void
g_debug (const gchar *format,
...)
{
va_list args;
va_start (args, format);
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format, args);
va_end (args);
}
#endif /* !__GNUC__ */
/**
* GPrintFunc:
* @string: the message to output
*
* Specifies the type of the print handler functions.
* These are called with the complete formatted string to output.
*/
typedef void (*GPrintFunc) (const gchar *string);
GLIB_AVAILABLE_IN_ALL
void g_print (const gchar *format,
...) G_GNUC_PRINTF (1, 2);
GLIB_AVAILABLE_IN_ALL
GPrintFunc g_set_print_handler (GPrintFunc func);
GLIB_AVAILABLE_IN_ALL
void g_printerr (const gchar *format,
...) G_GNUC_PRINTF (1, 2);
GLIB_AVAILABLE_IN_ALL
GPrintFunc g_set_printerr_handler (GPrintFunc func);
/**
* g_warn_if_reached:
*
* Logs a critical warning.
*
* Since: 2.16
*/
#define g_warn_if_reached() \
do { \
g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, NULL); \
} while (0)
/**
* g_warn_if_fail:
* @expr: the expression to check
*
* Logs a warning if the expression is not true.
*
* Since: 2.16
*/
#define g_warn_if_fail(expr) \
do { \
if G_LIKELY (expr) ; \
else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, #expr); \
} while (0)
#ifdef G_DISABLE_CHECKS
/**
* g_return_if_fail:
* @expr: the expression to check
*
* Verifies that the expression evaluates to %TRUE. If the expression
* evaluates to %FALSE, a critical message is logged and the current
* function returns. This can only be used in functions which do not
* return a value.
*
* If G_DISABLE_CHECKS is defined then the check is not performed. You
* should therefore not depend on any side effects of @expr.
*/
#define g_return_if_fail(expr) G_STMT_START{ (void)0; }G_STMT_END
/**
* g_return_val_if_fail:
* @expr: the expression to check
* @val: the value to return from the current function
* if the expression is not true
*
* Verifies that the expression evaluates to %TRUE. If the expression
* evaluates to %FALSE, a critical message is logged and @val is
* returned from the current function.
*
* If G_DISABLE_CHECKS is defined then the check is not performed. You
* should therefore not depend on any side effects of @expr.
*/
#define g_return_val_if_fail(expr,val) G_STMT_START{ (void)0; }G_STMT_END
/**
* g_return_if_reached:
*
* Logs a critical message and returns from the current function.
* This can only be used in functions which do not return a value.
*/
#define g_return_if_reached() G_STMT_START{ return; }G_STMT_END
/**
* g_return_val_if_reached:
* @val: the value to return from the current function
*
* Logs a critical message and returns @val.
*/
#define g_return_val_if_reached(val) G_STMT_START{ return (val); }G_STMT_END
#else /* !G_DISABLE_CHECKS */
#ifdef __GNUC__
#define g_return_if_fail(expr) G_STMT_START{ \
if G_LIKELY(expr) { } else \
{ \
g_return_if_fail_warning (G_LOG_DOMAIN, \
__PRETTY_FUNCTION__, \
#expr); \
return; \
}; }G_STMT_END
#define g_return_val_if_fail(expr,val) G_STMT_START{ \
if G_LIKELY(expr) { } else \
{ \
g_return_if_fail_warning (G_LOG_DOMAIN, \
__PRETTY_FUNCTION__, \
#expr); \
return (val); \
}; }G_STMT_END
#define g_return_if_reached() G_STMT_START{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
"file %s: line %d (%s): should not be reached", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__); \
return; }G_STMT_END
#define g_return_val_if_reached(val) G_STMT_START{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
"file %s: line %d (%s): should not be reached", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__); \
return (val); }G_STMT_END
#else /* !__GNUC__ */
#define g_return_if_fail(expr) G_STMT_START{ \
if (expr) { } else \
{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
"file %s: line %d: assertion '%s' failed", \
__FILE__, \
__LINE__, \
#expr); \
return; \
}; }G_STMT_END
#define g_return_val_if_fail(expr, val) G_STMT_START{ \
if (expr) { } else \
{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
"file %s: line %d: assertion '%s' failed", \
__FILE__, \
__LINE__, \
#expr); \
return (val); \
}; }G_STMT_END
#define g_return_if_reached() G_STMT_START{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
"file %s: line %d: should not be reached", \
__FILE__, \
__LINE__); \
return; }G_STMT_END
#define g_return_val_if_reached(val) G_STMT_START{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
"file %s: line %d: should not be reached", \
__FILE__, \
__LINE__); \
return (val); }G_STMT_END
#endif /* !__GNUC__ */
#endif /* !G_DISABLE_CHECKS */
G_END_DECLS
#endif /* __G_MESSAGES_H__ */
pkg-config-0.29.1/glib/glib/gspawn-win32.c 0000664 0001750 0001750 00000114105 12651243552 015016 0000000 0000000 /* gspawn-win32.c - Process launching on Win32
*
* Copyright 2000 Red Hat, Inc.
* Copyright 2003 Tor Lillqvist
*
* GLib 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 of the
* License, or (at your option) any later version.
*
* GLib 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 GLib; see the file COPYING.LIB. If not, write
* to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Implementation details on Win32.
*
* - There is no way to set the no-inherit flag for
* a "file descriptor" in the MS C runtime. The flag is there,
* and the dospawn() function uses it, but unfortunately
* this flag can only be set when opening the file.
* - As there is no fork(), we cannot reliably change directory
* before starting the child process. (There might be several threads
* running, and the current directory is common for all threads.)
*
* Thus, we must in many cases use a helper program to handle closing
* of (inherited) file descriptors and changing of directory. The
* helper process is also needed if the standard input, standard
* output, or standard error of the process to be run are supposed to
* be redirected somewhere.
*
* The structure of the source code in this file is a mess, I know.
*/
/* Define this to get some logging all the time */
/* #define G_SPAWN_WIN32_DEBUG */
#include "config.h"
#include "glib.h"
#include "glib-private.h"
#include "gprintfint.h"
#include "glibintl.h"
#include "gthread.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifndef GSPAWN_HELPER
#ifdef G_SPAWN_WIN32_DEBUG
static int debug = 1;
#define SETUP_DEBUG() /* empty */
#else
static int debug = -1;
#define SETUP_DEBUG() \
G_STMT_START \
{ \
if (debug == -1) \
{ \
if (getenv ("G_SPAWN_WIN32_DEBUG") != NULL) \
debug = 1; \
else \
debug = 0; \
} \
} \
G_STMT_END
#endif
#endif
enum
{
CHILD_NO_ERROR,
CHILD_CHDIR_FAILED,
CHILD_SPAWN_FAILED,
};
enum {
ARG_CHILD_ERR_REPORT = 1,
ARG_HELPER_SYNC,
ARG_STDIN,
ARG_STDOUT,
ARG_STDERR,
ARG_WORKING_DIRECTORY,
ARG_CLOSE_DESCRIPTORS,
ARG_USE_PATH,
ARG_WAIT,
ARG_PROGRAM,
ARG_COUNT = ARG_PROGRAM
};
static int
dup_noninherited (int fd,
int mode)
{
HANDLE filehandle;
DuplicateHandle (GetCurrentProcess (), (LPHANDLE) _get_osfhandle (fd),
GetCurrentProcess (), &filehandle,
0, FALSE, DUPLICATE_SAME_ACCESS);
close (fd);
return _open_osfhandle ((gintptr) filehandle, mode | _O_NOINHERIT);
}
#ifndef GSPAWN_HELPER
#ifdef _WIN64
#define HELPER_PROCESS "gspawn-win64-helper"
#else
#define HELPER_PROCESS "gspawn-win32-helper"
#endif
static gchar *
protect_argv_string (const gchar *string)
{
const gchar *p = string;
gchar *retval, *q;
gint len = 0;
gboolean need_dblquotes = FALSE;
while (*p)
{
if (*p == ' ' || *p == '\t')
need_dblquotes = TRUE;
else if (*p == '"')
len++;
else if (*p == '\\')
{
const gchar *pp = p;
while (*pp && *pp == '\\')
pp++;
if (*pp == '"')
len++;
}
len++;
p++;
}
q = retval = g_malloc (len + need_dblquotes*2 + 1);
p = string;
if (need_dblquotes)
*q++ = '"';
while (*p)
{
if (*p == '"')
*q++ = '\\';
else if (*p == '\\')
{
const gchar *pp = p;
while (*pp && *pp == '\\')
pp++;
if (*pp == '"')
*q++ = '\\';
}
*q++ = *p;
p++;
}
if (need_dblquotes)
*q++ = '"';
*q++ = '\0';
return retval;
}
static gint
protect_argv (gchar **argv,
gchar ***new_argv)
{
gint i;
gint argc = 0;
while (argv[argc])
++argc;
*new_argv = g_new (gchar *, argc+1);
/* Quote each argv element if necessary, so that it will get
* reconstructed correctly in the C runtime startup code. Note that
* the unquoting algorithm in the C runtime is really weird, and
* rather different than what Unix shells do. See stdargv.c in the C
* runtime sources (in the Platform SDK, in src/crt).
*
* Note that an new_argv[0] constructed by this function should
* *not* be passed as the filename argument to a spawn* or exec*
* family function. That argument should be the real file name
* without any quoting.
*/
for (i = 0; i < argc; i++)
(*new_argv)[i] = protect_argv_string (argv[i]);
(*new_argv)[argc] = NULL;
return argc;
}
G_DEFINE_QUARK (g-exec-error-quark, g_spawn_error)
G_DEFINE_QUARK (g-spawn-exit-error-quark, g_spawn_exit_error)
gboolean
g_spawn_async_utf8 (const gchar *working_directory,
gchar **argv,
gchar **envp,
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
GPid *child_handle,
GError **error)
{
g_return_val_if_fail (argv != NULL, FALSE);
return g_spawn_async_with_pipes_utf8 (working_directory,
argv, envp,
flags,
child_setup,
user_data,
child_handle,
NULL, NULL, NULL,
error);
}
/* Avoids a danger in threaded situations (calling close()
* on a file descriptor twice, and another thread has
* re-opened it since the first close)
*/
static void
close_and_invalidate (gint *fd)
{
if (*fd < 0)
return;
close (*fd);
*fd = -1;
}
typedef enum
{
READ_FAILED = 0, /* FALSE */
READ_OK,
READ_EOF
} ReadResult;
static ReadResult
read_data (GString *str,
GIOChannel *iochannel,
GError **error)
{
GIOStatus giostatus;
gsize bytes;
gchar buf[4096];
again:
giostatus = g_io_channel_read_chars (iochannel, buf, sizeof (buf), &bytes, NULL);
if (bytes == 0)
return READ_EOF;
else if (bytes > 0)
{
g_string_append_len (str, buf, bytes);
return READ_OK;
}
else if (giostatus == G_IO_STATUS_AGAIN)
goto again;
else if (giostatus == G_IO_STATUS_ERROR)
{
g_set_error_literal (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
_("Failed to read data from child process"));
return READ_FAILED;
}
else
return READ_OK;
}
static gboolean
make_pipe (gint p[2],
GError **error)
{
if (_pipe (p, 4096, _O_BINARY) < 0)
{
int errsv = errno;
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
_("Failed to create pipe for communicating with child process (%s)"),
g_strerror (errsv));
return FALSE;
}
else
return TRUE;
}
/* The helper process writes a status report back to us, through a
* pipe, consisting of two ints.
*/
static gboolean
read_helper_report (int fd,
gintptr report[2],
GError **error)
{
gint bytes = 0;
while (bytes < sizeof(gintptr)*2)
{
gint chunk;
if (debug)
g_print ("%s:read_helper_report: read %" G_GSIZE_FORMAT "...\n",
__FILE__,
sizeof(gintptr)*2 - bytes);
chunk = read (fd, ((gchar*)report) + bytes,
sizeof(gintptr)*2 - bytes);
if (debug)
g_print ("...got %d bytes\n", chunk);
if (chunk < 0)
{
int errsv = errno;
/* Some weird shit happened, bail out */
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
_("Failed to read from child pipe (%s)"),
g_strerror (errsv));
return FALSE;
}
else if (chunk == 0)
{
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
_("Failed to read from child pipe (%s)"),
"EOF");
break; /* EOF */
}
else
bytes += chunk;
}
if (bytes < sizeof(gintptr)*2)
return FALSE;
return TRUE;
}
static void
set_child_error (gintptr report[2],
const gchar *working_directory,
GError **error)
{
switch (report[0])
{
case CHILD_CHDIR_FAILED:
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
_("Failed to change to directory '%s' (%s)"),
working_directory,
g_strerror (report[1]));
break;
case CHILD_SPAWN_FAILED:
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
_("Failed to execute child process (%s)"),
g_strerror (report[1]));
break;
default:
g_assert_not_reached ();
}
}
static gboolean
utf8_charv_to_wcharv (char **utf8_charv,
wchar_t ***wcharv,
int *error_index,
GError **error)
{
wchar_t **retval = NULL;
*wcharv = NULL;
if (utf8_charv != NULL)
{
int n = 0, i;
while (utf8_charv[n])
n++;
retval = g_new (wchar_t *, n + 1);
for (i = 0; i < n; i++)
{
retval[i] = g_utf8_to_utf16 (utf8_charv[i], -1, NULL, NULL, error);
if (retval[i] == NULL)
{
if (error_index)
*error_index = i;
while (i)
g_free (retval[--i]);
g_free (retval);
return FALSE;
}
}
retval[n] = NULL;
}
*wcharv = retval;
return TRUE;
}
static gboolean
do_spawn_directly (gint *exit_status,
gboolean do_return_handle,
GSpawnFlags flags,
gchar **argv,
char **envp,
char **protected_argv,
GPid *child_handle,
GError **error)
{
const int mode = (exit_status == NULL) ? P_NOWAIT : P_WAIT;
char **new_argv;
gintptr rc = -1;
int saved_errno;
GError *conv_error = NULL;
gint conv_error_index;
wchar_t *wargv0, **wargv, **wenvp;
new_argv = (flags & G_SPAWN_FILE_AND_ARGV_ZERO) ? protected_argv + 1 : protected_argv;
wargv0 = g_utf8_to_utf16 (argv[0], -1, NULL, NULL, &conv_error);
if (wargv0 == NULL)
{
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
_("Invalid program name: %s"),
conv_error->message);
g_error_free (conv_error);
return FALSE;
}
if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error))
{
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
_("Invalid string in argument vector at %d: %s"),
conv_error_index, conv_error->message);
g_error_free (conv_error);
g_free (wargv0);
return FALSE;
}
if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
{
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
_("Invalid string in environment: %s"),
conv_error->message);
g_error_free (conv_error);
g_free (wargv0);
g_strfreev ((gchar **) wargv);
return FALSE;
}
if (flags & G_SPAWN_SEARCH_PATH)
if (wenvp != NULL)
rc = _wspawnvpe (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
else
rc = _wspawnvp (mode, wargv0, (const wchar_t **) wargv);
else
if (wenvp != NULL)
rc = _wspawnve (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
else
rc = _wspawnv (mode, wargv0, (const wchar_t **) wargv);
g_free (wargv0);
g_strfreev ((gchar **) wargv);
g_strfreev ((gchar **) wenvp);
saved_errno = errno;
if (rc == -1 && saved_errno != 0)
{
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
_("Failed to execute child process (%s)"),
g_strerror (saved_errno));
return FALSE;
}
if (exit_status == NULL)
{
if (child_handle && do_return_handle)
*child_handle = (GPid) rc;
else
{
CloseHandle ((HANDLE) rc);
if (child_handle)
*child_handle = 0;
}
}
else
*exit_status = rc;
return TRUE;
}
static gboolean
do_spawn_with_pipes (gint *exit_status,
gboolean do_return_handle,
const gchar *working_directory,
gchar **argv,
char **envp,
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
GPid *child_handle,
gint *standard_input,
gint *standard_output,
gint *standard_error,
gint *err_report,
GError **error)
{
char **protected_argv;
char args[ARG_COUNT][10];
char **new_argv;
int i;
gintptr rc = -1;
int saved_errno;
int argc;
int stdin_pipe[2] = { -1, -1 };
int stdout_pipe[2] = { -1, -1 };
int stderr_pipe[2] = { -1, -1 };
int child_err_report_pipe[2] = { -1, -1 };
int helper_sync_pipe[2] = { -1, -1 };
gintptr helper_report[2];
static gboolean warned_about_child_setup = FALSE;
GError *conv_error = NULL;
gint conv_error_index;
gchar *helper_process;
CONSOLE_CURSOR_INFO cursor_info;
wchar_t *whelper, **wargv, **wenvp;
gchar *glib_dll_directory;
if (child_setup && !warned_about_child_setup)
{
warned_about_child_setup = TRUE;
g_warning ("passing a child setup function to the g_spawn functions is pointless on Windows and it is ignored");
}
argc = protect_argv (argv, &protected_argv);
if (!standard_input && !standard_output && !standard_error &&
(flags & G_SPAWN_CHILD_INHERITS_STDIN) &&
!(flags & G_SPAWN_STDOUT_TO_DEV_NULL) &&
!(flags & G_SPAWN_STDERR_TO_DEV_NULL) &&
(working_directory == NULL || !*working_directory) &&
(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
{
/* We can do without the helper process */
gboolean retval =
do_spawn_directly (exit_status, do_return_handle, flags,
argv, envp, protected_argv,
child_handle, error);
g_strfreev (protected_argv);
return retval;
}
if (standard_input && !make_pipe (stdin_pipe, error))
goto cleanup_and_fail;
if (standard_output && !make_pipe (stdout_pipe, error))
goto cleanup_and_fail;
if (standard_error && !make_pipe (stderr_pipe, error))
goto cleanup_and_fail;
if (!make_pipe (child_err_report_pipe, error))
goto cleanup_and_fail;
if (!make_pipe (helper_sync_pipe, error))
goto cleanup_and_fail;
new_argv = g_new (char *, argc + 1 + ARG_COUNT);
if (GetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cursor_info))
helper_process = HELPER_PROCESS "-console.exe";
else
helper_process = HELPER_PROCESS ".exe";
glib_dll_directory = _glib_get_dll_directory ();
if (glib_dll_directory != NULL)
{
helper_process = g_build_filename (glib_dll_directory, helper_process, NULL);
g_free (glib_dll_directory);
}
else
helper_process = g_strdup (helper_process);
new_argv[0] = protect_argv_string (helper_process);
_g_sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_pipe[1]);
new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
/* Make the read end of the child error report pipe
* noninherited. Otherwise it will needlessly be inherited by the
* helper process, and the started actual user process. As such that
* shouldn't harm, but it is unnecessary.
*/
child_err_report_pipe[0] = dup_noninherited (child_err_report_pipe[0], _O_RDONLY);
if (flags & G_SPAWN_FILE_AND_ARGV_ZERO)
{
/* Overload ARG_CHILD_ERR_REPORT to also encode the
* G_SPAWN_FILE_AND_ARGV_ZERO functionality.
*/
strcat (args[ARG_CHILD_ERR_REPORT], "#");
}
_g_sprintf (args[ARG_HELPER_SYNC], "%d", helper_sync_pipe[0]);
new_argv[ARG_HELPER_SYNC] = args[ARG_HELPER_SYNC];
/* Make the write end of the sync pipe noninherited. Otherwise the
* helper process will inherit it, and thus if this process happens
* to crash before writing the sync byte to the pipe, the helper
* process won't read but won't get any EOF either, as it has the
* write end open itself.
*/
helper_sync_pipe[1] = dup_noninherited (helper_sync_pipe[1], _O_WRONLY);
if (standard_input)
{
_g_sprintf (args[ARG_STDIN], "%d", stdin_pipe[0]);
new_argv[ARG_STDIN] = args[ARG_STDIN];
}
else if (flags & G_SPAWN_CHILD_INHERITS_STDIN)
{
/* Let stdin be alone */
new_argv[ARG_STDIN] = "-";
}
else
{
/* Keep process from blocking on a read of stdin */
new_argv[ARG_STDIN] = "z";
}
if (standard_output)
{
_g_sprintf (args[ARG_STDOUT], "%d", stdout_pipe[1]);
new_argv[ARG_STDOUT] = args[ARG_STDOUT];
}
else if (flags & G_SPAWN_STDOUT_TO_DEV_NULL)
{
new_argv[ARG_STDOUT] = "z";
}
else
{
new_argv[ARG_STDOUT] = "-";
}
if (standard_error)
{
_g_sprintf (args[ARG_STDERR], "%d", stderr_pipe[1]);
new_argv[ARG_STDERR] = args[ARG_STDERR];
}
else if (flags & G_SPAWN_STDERR_TO_DEV_NULL)
{
new_argv[ARG_STDERR] = "z";
}
else
{
new_argv[ARG_STDERR] = "-";
}
if (working_directory && *working_directory)
new_argv[ARG_WORKING_DIRECTORY] = protect_argv_string (working_directory);
else
new_argv[ARG_WORKING_DIRECTORY] = g_strdup ("-");
if (!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
else
new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
if (flags & G_SPAWN_SEARCH_PATH)
new_argv[ARG_USE_PATH] = "y";
else
new_argv[ARG_USE_PATH] = "-";
if (exit_status == NULL)
new_argv[ARG_WAIT] = "-";
else
new_argv[ARG_WAIT] = "w";
for (i = 0; i <= argc; i++)
new_argv[ARG_PROGRAM + i] = protected_argv[i];
SETUP_DEBUG();
if (debug)
{
g_print ("calling %s with argv:\n", helper_process);
for (i = 0; i < argc + 1 + ARG_COUNT; i++)
g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
}
if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error))
{
if (conv_error_index == ARG_WORKING_DIRECTORY)
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
_("Invalid working directory: %s"),
conv_error->message);
else
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
_("Invalid string in argument vector at %d: %s"),
conv_error_index - ARG_PROGRAM, conv_error->message);
g_error_free (conv_error);
g_strfreev (protected_argv);
g_free (new_argv[0]);
g_free (new_argv[ARG_WORKING_DIRECTORY]);
g_free (new_argv);
g_free (helper_process);
goto cleanup_and_fail;
}
if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
{
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
_("Invalid string in environment: %s"),
conv_error->message);
g_error_free (conv_error);
g_strfreev (protected_argv);
g_free (new_argv[0]);
g_free (new_argv[ARG_WORKING_DIRECTORY]);
g_free (new_argv);
g_free (helper_process);
g_strfreev ((gchar **) wargv);
goto cleanup_and_fail;
}
whelper = g_utf8_to_utf16 (helper_process, -1, NULL, NULL, NULL);
g_free (helper_process);
if (wenvp != NULL)
rc = _wspawnvpe (P_NOWAIT, whelper, (const wchar_t **) wargv, (const wchar_t **) wenvp);
else
rc = _wspawnvp (P_NOWAIT, whelper, (const wchar_t **) wargv);
saved_errno = errno;
g_free (whelper);
g_strfreev ((gchar **) wargv);
g_strfreev ((gchar **) wenvp);
/* Close the other process's ends of the pipes in this process,
* otherwise the reader will never get EOF.
*/
close_and_invalidate (&child_err_report_pipe[1]);
close_and_invalidate (&helper_sync_pipe[0]);
close_and_invalidate (&stdin_pipe[0]);
close_and_invalidate (&stdout_pipe[1]);
close_and_invalidate (&stderr_pipe[1]);
g_strfreev (protected_argv);
g_free (new_argv[0]);
g_free (new_argv[ARG_WORKING_DIRECTORY]);
g_free (new_argv);
/* Check if gspawn-win32-helper couldn't be run */
if (rc == -1 && saved_errno != 0)
{
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
_("Failed to execute helper program (%s)"),
g_strerror (saved_errno));
goto cleanup_and_fail;
}
if (exit_status != NULL)
{
/* Synchronous case. Pass helper's report pipe back to caller,
* which takes care of reading it after the grandchild has
* finished.
*/
g_assert (err_report != NULL);
*err_report = child_err_report_pipe[0];
write (helper_sync_pipe[1], " ", 1);
close_and_invalidate (&helper_sync_pipe[1]);
}
else
{
/* Asynchronous case. We read the helper's report right away. */
if (!read_helper_report (child_err_report_pipe[0], helper_report, error))
goto cleanup_and_fail;
close_and_invalidate (&child_err_report_pipe[0]);
switch (helper_report[0])
{
case CHILD_NO_ERROR:
if (child_handle && do_return_handle)
{
/* rc is our HANDLE for gspawn-win32-helper. It has
* told us the HANDLE of its child. Duplicate that into
* a HANDLE valid in this process.
*/
if (!DuplicateHandle ((HANDLE) rc, (HANDLE) helper_report[1],
GetCurrentProcess (), (LPHANDLE) child_handle,
0, TRUE, DUPLICATE_SAME_ACCESS))
{
char *emsg = g_win32_error_message (GetLastError ());
g_print("%s\n", emsg);
*child_handle = 0;
}
}
else if (child_handle)
*child_handle = 0;
write (helper_sync_pipe[1], " ", 1);
close_and_invalidate (&helper_sync_pipe[1]);
break;
default:
write (helper_sync_pipe[1], " ", 1);
close_and_invalidate (&helper_sync_pipe[1]);
set_child_error (helper_report, working_directory, error);
goto cleanup_and_fail;
}
}
/* Success against all odds! return the information */
if (standard_input)
*standard_input = stdin_pipe[1];
if (standard_output)
*standard_output = stdout_pipe[0];
if (standard_error)
*standard_error = stderr_pipe[0];
if (rc != -1)
CloseHandle ((HANDLE) rc);
return TRUE;
cleanup_and_fail:
if (rc != -1)
CloseHandle ((HANDLE) rc);
if (child_err_report_pipe[0] != -1)
close (child_err_report_pipe[0]);
if (child_err_report_pipe[1] != -1)
close (child_err_report_pipe[1]);
if (helper_sync_pipe[0] != -1)
close (helper_sync_pipe[0]);
if (helper_sync_pipe[1] != -1)
close (helper_sync_pipe[1]);
if (stdin_pipe[0] != -1)
close (stdin_pipe[0]);
if (stdin_pipe[1] != -1)
close (stdin_pipe[1]);
if (stdout_pipe[0] != -1)
close (stdout_pipe[0]);
if (stdout_pipe[1] != -1)
close (stdout_pipe[1]);
if (stderr_pipe[0] != -1)
close (stderr_pipe[0]);
if (stderr_pipe[1] != -1)
close (stderr_pipe[1]);
return FALSE;
}
gboolean
g_spawn_sync_utf8 (const gchar *working_directory,
gchar **argv,
gchar **envp,
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
gchar **standard_output,
gchar **standard_error,
gint *exit_status,
GError **error)
{
gint outpipe = -1;
gint errpipe = -1;
gint reportpipe = -1;
GIOChannel *outchannel = NULL;
GIOChannel *errchannel = NULL;
GPollFD outfd, errfd;
GPollFD fds[2];
gint nfds;
gint outindex = -1;
gint errindex = -1;
gint ret;
GString *outstr = NULL;
GString *errstr = NULL;
gboolean failed;
gint status;
g_return_val_if_fail (argv != NULL, FALSE);
g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
g_return_val_if_fail (standard_output == NULL ||
!(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
g_return_val_if_fail (standard_error == NULL ||
!(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
/* Just to ensure segfaults if callers try to use
* these when an error is reported.
*/
if (standard_output)
*standard_output = NULL;
if (standard_error)
*standard_error = NULL;
if (!do_spawn_with_pipes (&status,
FALSE,
working_directory,
argv,
envp,
flags,
child_setup,
NULL,
NULL,
standard_output ? &outpipe : NULL,
standard_error ? &errpipe : NULL,
&reportpipe,
error))
return FALSE;
/* Read data from child. */
failed = FALSE;
if (outpipe >= 0)
{
outstr = g_string_new (NULL);
outchannel = g_io_channel_win32_new_fd (outpipe);
g_io_channel_set_encoding (outchannel, NULL, NULL);
g_io_channel_set_buffered (outchannel, FALSE);
g_io_channel_win32_make_pollfd (outchannel,
G_IO_IN | G_IO_ERR | G_IO_HUP,
&outfd);
if (debug)
g_print ("outfd=%p\n", (HANDLE) outfd.fd);
}
if (errpipe >= 0)
{
errstr = g_string_new (NULL);
errchannel = g_io_channel_win32_new_fd (errpipe);
g_io_channel_set_encoding (errchannel, NULL, NULL);
g_io_channel_set_buffered (errchannel, FALSE);
g_io_channel_win32_make_pollfd (errchannel,
G_IO_IN | G_IO_ERR | G_IO_HUP,
&errfd);
if (debug)
g_print ("errfd=%p\n", (HANDLE) errfd.fd);
}
/* Read data until we get EOF on all pipes. */
while (!failed && (outpipe >= 0 || errpipe >= 0))
{
nfds = 0;
if (outpipe >= 0)
{
fds[nfds] = outfd;
outindex = nfds;
nfds++;
}
if (errpipe >= 0)
{
fds[nfds] = errfd;
errindex = nfds;
nfds++;
}
if (debug)
g_print ("g_spawn_sync: calling g_io_channel_win32_poll, nfds=%d\n",
nfds);
ret = g_io_channel_win32_poll (fds, nfds, -1);
if (ret < 0)
{
failed = TRUE;
g_set_error_literal (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
_("Unexpected error in g_io_channel_win32_poll() reading data from a child process"));
break;
}
if (outpipe >= 0 && (fds[outindex].revents & G_IO_IN))
{
switch (read_data (outstr, outchannel, error))
{
case READ_FAILED:
if (debug)
g_print ("g_spawn_sync: outchannel: READ_FAILED\n");
failed = TRUE;
break;
case READ_EOF:
if (debug)
g_print ("g_spawn_sync: outchannel: READ_EOF\n");
g_io_channel_unref (outchannel);
outchannel = NULL;
close_and_invalidate (&outpipe);
break;
default:
if (debug)
g_print ("g_spawn_sync: outchannel: OK\n");
break;
}
if (failed)
break;
}
if (errpipe >= 0 && (fds[errindex].revents & G_IO_IN))
{
switch (read_data (errstr, errchannel, error))
{
case READ_FAILED:
if (debug)
g_print ("g_spawn_sync: errchannel: READ_FAILED\n");
failed = TRUE;
break;
case READ_EOF:
if (debug)
g_print ("g_spawn_sync: errchannel: READ_EOF\n");
g_io_channel_unref (errchannel);
errchannel = NULL;
close_and_invalidate (&errpipe);
break;
default:
if (debug)
g_print ("g_spawn_sync: errchannel: OK\n");
break;
}
if (failed)
break;
}
}
if (reportpipe == -1)
{
/* No helper process, exit status of actual spawned process
* already available.
*/
if (exit_status)
*exit_status = status;
}
else
{
/* Helper process was involved. Read its report now after the
* grandchild has finished.
*/
gintptr helper_report[2];
if (!read_helper_report (reportpipe, helper_report, error))
failed = TRUE;
else
{
switch (helper_report[0])
{
case CHILD_NO_ERROR:
if (exit_status)
*exit_status = helper_report[1];
break;
default:
set_child_error (helper_report, working_directory, error);
failed = TRUE;
break;
}
}
close_and_invalidate (&reportpipe);
}
/* These should only be open still if we had an error. */
if (outchannel != NULL)
g_io_channel_unref (outchannel);
if (errchannel != NULL)
g_io_channel_unref (errchannel);
if (outpipe >= 0)
close_and_invalidate (&outpipe);
if (errpipe >= 0)
close_and_invalidate (&errpipe);
if (failed)
{
if (outstr)
g_string_free (outstr, TRUE);
if (errstr)
g_string_free (errstr, TRUE);
return FALSE;
}
else
{
if (standard_output)
*standard_output = g_string_free (outstr, FALSE);
if (standard_error)
*standard_error = g_string_free (errstr, FALSE);
return TRUE;
}
}
gboolean
g_spawn_async_with_pipes_utf8 (const gchar *working_directory,
gchar **argv,
gchar **envp,
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
GPid *child_handle,
gint *standard_input,
gint *standard_output,
gint *standard_error,
GError **error)
{
g_return_val_if_fail (argv != NULL, FALSE);
g_return_val_if_fail (standard_output == NULL ||
!(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
g_return_val_if_fail (standard_error == NULL ||
!(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
/* can't inherit stdin if we have an input pipe. */
g_return_val_if_fail (standard_input == NULL ||
!(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
return do_spawn_with_pipes (NULL,
(flags & G_SPAWN_DO_NOT_REAP_CHILD),
working_directory,
argv,
envp,
flags,
child_setup,
child_handle,
standard_input,
standard_output,
standard_error,
NULL,
error);
}
gboolean
g_spawn_command_line_sync_utf8 (const gchar *command_line,
gchar **standard_output,
gchar **standard_error,
gint *exit_status,
GError **error)
{
gboolean retval;
gchar **argv = 0;
g_return_val_if_fail (command_line != NULL, FALSE);
if (!g_shell_parse_argv (command_line,
NULL, &argv,
error))
return FALSE;
retval = g_spawn_sync_utf8 (NULL,
argv,
NULL,
G_SPAWN_SEARCH_PATH,
NULL,
NULL,
standard_output,
standard_error,
exit_status,
error);
g_strfreev (argv);
return retval;
}
gboolean
g_spawn_command_line_async_utf8 (const gchar *command_line,
GError **error)
{
gboolean retval;
gchar **argv = 0;
g_return_val_if_fail (command_line != NULL, FALSE);
if (!g_shell_parse_argv (command_line,
NULL, &argv,
error))
return FALSE;
retval = g_spawn_async_utf8 (NULL,
argv,
NULL,
G_SPAWN_SEARCH_PATH,
NULL,
NULL,
NULL,
error);
g_strfreev (argv);
return retval;
}
void
g_spawn_close_pid (GPid pid)
{
CloseHandle (pid);
}
gboolean
g_spawn_check_exit_status (gint exit_status,
GError **error)
{
gboolean ret = FALSE;
if (exit_status != 0)
{
g_set_error (error, G_SPAWN_EXIT_ERROR, exit_status,
_("Child process exited with code %ld"),
(long) exit_status);
goto out;
}
ret = TRUE;
out:
return ret;
}
#if !defined (_WIN64)
/* Binary compatibility versions that take system codepage pathnames,
* argument vectors and environments. These get used only by code
* built against 2.8.1 or earlier. Code built against 2.8.2 or later
* will use the _utf8 versions above (see the #defines in gspawn.h).
*/
#undef g_spawn_async
#undef g_spawn_async_with_pipes
#undef g_spawn_sync
#undef g_spawn_command_line_sync
#undef g_spawn_command_line_async
static gboolean
setup_utf8_copies (const gchar *working_directory,
gchar **utf8_working_directory,
gchar **argv,
gchar ***utf8_argv,
gchar **envp,
gchar ***utf8_envp,
GError **error)
{
gint i, argc, envc;
if (working_directory == NULL)
*utf8_working_directory = NULL;
else
{
GError *conv_error = NULL;
*utf8_working_directory = g_locale_to_utf8 (working_directory, -1, NULL, NULL, &conv_error);
if (*utf8_working_directory == NULL)
{
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
_("Invalid working directory: %s"),
conv_error->message);
g_error_free (conv_error);
return FALSE;
}
}
argc = 0;
while (argv[argc])
++argc;
*utf8_argv = g_new (gchar *, argc + 1);
for (i = 0; i < argc; i++)
{
GError *conv_error = NULL;
(*utf8_argv)[i] = g_locale_to_utf8 (argv[i], -1, NULL, NULL, &conv_error);
if ((*utf8_argv)[i] == NULL)
{
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
_("Invalid string in argument vector at %d: %s"),
i, conv_error->message);
g_error_free (conv_error);
g_strfreev (*utf8_argv);
*utf8_argv = NULL;
g_free (*utf8_working_directory);
*utf8_working_directory = NULL;
return FALSE;
}
}
(*utf8_argv)[argc] = NULL;
if (envp == NULL)
{
*utf8_envp = NULL;
}
else
{
envc = 0;
while (envp[envc])
++envc;
*utf8_envp = g_new (gchar *, envc + 1);
for (i = 0; i < envc; i++)
{
GError *conv_error = NULL;
(*utf8_envp)[i] = g_locale_to_utf8 (envp[i], -1, NULL, NULL, &conv_error);
if ((*utf8_envp)[i] == NULL)
{
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
_("Invalid string in environment: %s"),
conv_error->message);
g_error_free (conv_error);
g_strfreev (*utf8_envp);
*utf8_envp = NULL;
g_strfreev (*utf8_argv);
*utf8_argv = NULL;
g_free (*utf8_working_directory);
*utf8_working_directory = NULL;
return FALSE;
}
}
(*utf8_envp)[envc] = NULL;
}
return TRUE;
}
static void
free_utf8_copies (gchar *utf8_working_directory,
gchar **utf8_argv,
gchar **utf8_envp)
{
g_free (utf8_working_directory);
g_strfreev (utf8_argv);
g_strfreev (utf8_envp);
}
gboolean
g_spawn_async_with_pipes (const gchar *working_directory,
gchar **argv,
gchar **envp,
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
GPid *child_handle,
gint *standard_input,
gint *standard_output,
gint *standard_error,
GError **error)
{
gchar *utf8_working_directory;
gchar **utf8_argv;
gchar **utf8_envp;
gboolean retval;
if (!setup_utf8_copies (working_directory, &utf8_working_directory,
argv, &utf8_argv,
envp, &utf8_envp,
error))
return FALSE;
retval = g_spawn_async_with_pipes_utf8 (utf8_working_directory,
utf8_argv, utf8_envp,
flags, child_setup, user_data,
child_handle,
standard_input, standard_output, standard_error,
error);
free_utf8_copies (utf8_working_directory, utf8_argv, utf8_envp);
return retval;
}
gboolean
g_spawn_async (const gchar *working_directory,
gchar **argv,
gchar **envp,
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
GPid *child_handle,
GError **error)
{
return g_spawn_async_with_pipes (working_directory,
argv, envp,
flags,
child_setup,
user_data,
child_handle,
NULL, NULL, NULL,
error);
}
gboolean
g_spawn_sync (const gchar *working_directory,
gchar **argv,
gchar **envp,
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
gchar **standard_output,
gchar **standard_error,
gint *exit_status,
GError **error)
{
gchar *utf8_working_directory;
gchar **utf8_argv;
gchar **utf8_envp;
gboolean retval;
if (!setup_utf8_copies (working_directory, &utf8_working_directory,
argv, &utf8_argv,
envp, &utf8_envp,
error))
return FALSE;
retval = g_spawn_sync_utf8 (utf8_working_directory,
utf8_argv, utf8_envp,
flags, child_setup, user_data,
standard_output, standard_error, exit_status,
error);
free_utf8_copies (utf8_working_directory, utf8_argv, utf8_envp);
return retval;
}
gboolean
g_spawn_command_line_sync (const gchar *command_line,
gchar **standard_output,
gchar **standard_error,
gint *exit_status,
GError **error)
{
gboolean retval;
gchar **argv = 0;
g_return_val_if_fail (command_line != NULL, FALSE);
if (!g_shell_parse_argv (command_line,
NULL, &argv,
error))
return FALSE;
retval = g_spawn_sync (NULL,
argv,
NULL,
G_SPAWN_SEARCH_PATH,
NULL,
NULL,
standard_output,
standard_error,
exit_status,
error);
g_strfreev (argv);
return retval;
}
gboolean
g_spawn_command_line_async (const gchar *command_line,
GError **error)
{
gboolean retval;
gchar **argv = 0;
g_return_val_if_fail (command_line != NULL, FALSE);
if (!g_shell_parse_argv (command_line,
NULL, &argv,
error))
return FALSE;
retval = g_spawn_async (NULL,
argv,
NULL,
G_SPAWN_SEARCH_PATH,
NULL,
NULL,
NULL,
error);
g_strfreev (argv);
return retval;
}
#endif /* !_WIN64 */
#endif /* !GSPAWN_HELPER */
pkg-config-0.29.1/glib/glib/goption.c 0000664 0001750 0001750 00000214230 12651243552 014236 0000000 0000000 /* goption.c - Option parser
*
* Copyright (C) 1999, 2003 Red Hat Software
* Copyright (C) 2004 Anders Carlsson
*
* 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:option
* @Short_description: parses commandline options
* @Title: Commandline option parser
*
* The GOption commandline parser is intended to be a simpler replacement
* for the popt library. It supports short and long commandline options,
* as shown in the following example:
*
* testtreemodel -r 1 --max-size 20 --rand --display=:1.0 -vb -- file1 file2
*
* The example demonstrates a number of features of the GOption
* commandline parser
*
* Options can be single letters, prefixed by a single dash. Multiple
* short options can be grouped behind a single dash.
*
* Long options are prefixed by two consecutive dashes.
*
* Options can have an extra argument, which can be a number, a string or
* a filename. For long options, the extra argument can be appended with
* an equals sign after the option name, which is useful if the extra
* argument starts with a dash, which would otherwise cause it to be
* interpreted as another option.
*
* Non-option arguments are returned to the application as rest arguments.
*
* An argument consisting solely of two dashes turns off further parsing,
* any remaining arguments (even those starting with a dash) are returned
* to the application as rest arguments.
*
*
* Another important feature of GOption is that it can automatically
* generate nicely formatted help output. Unless it is explicitly turned
* off with g_option_context_set_help_enabled(), GOption will recognize
* the , ,
* and
* groupname options
* (where groupname is the name of a
* #GOptionGroup) and write a text similar to the one shown in the
* following example to stdout.
*
*
* Usage:
* testtreemodel [OPTION...] - test tree model performance
*
* Help Options:
* -h, --help Show help options
* --help-all Show all help options
* --help-gtk Show GTK+ Options
*
* Application Options:
* -r, --repeats=N Average over N repetitions
* -m, --max-size=M Test up to 2^M items
* --display=DISPLAY X display to use
* -v, --verbose Be verbose
* -b, --beep Beep when done
* --rand Randomize the data
*
*
* GOption groups options in #GOptionGroups, which makes it easy to
* incorporate options from multiple sources. The intended use for this is
* to let applications collect option groups from the libraries it uses,
* add them to their #GOptionContext, and parse all options by a single call
* to g_option_context_parse(). See gtk_get_option_group() for an example.
*
* If an option is declared to be of type string or filename, GOption takes
* care of converting it to the right encoding; strings are returned in
* UTF-8, filenames are returned in the GLib filename encoding. Note that
* this only works if setlocale() has been called before
* g_option_context_parse().
*
* Here is a complete example of setting up GOption to parse the example
* commandline above and produce the example help output.
*
*
* static gint repeats = 2;
* static gint max_size = 8;
* static gboolean verbose = FALSE;
* static gboolean beep = FALSE;
* static gboolean rand = FALSE;
*
* static GOptionEntry entries[] =
* {
* { "repeats", 'r', 0, G_OPTION_ARG_INT, &repeats, "Average over N repetitions", "N" },
* { "max-size", 'm', 0, G_OPTION_ARG_INT, &max_size, "Test up to 2^M items", "M" },
* { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL },
* { "beep", 'b', 0, G_OPTION_ARG_NONE, &beep, "Beep when done", NULL },
* { "rand", 0, 0, G_OPTION_ARG_NONE, &rand, "Randomize the data", NULL },
* { NULL }
* };
*
* int
* main (int argc, char *argv[])
* {
* GError *error = NULL;
* GOptionContext *context;
*
* context = g_option_context_new ("- test tree model performance");
* g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
* g_option_context_add_group (context, gtk_get_option_group (TRUE));
* if (!g_option_context_parse (context, &argc, &argv, &error))
* {
* g_print ("option parsing failed: %s\n", error->message);
* exit (1);
* }
*
* /* ... */
*
* }
*
*/
#include "config.h"
#include
#include
#include
#include
#if defined __OpenBSD__
#include
#include
#include
#include
#endif
#include "goption.h"
#include "gprintf.h"
#include "glibintl.h"
#define TRANSLATE(group, str) (((group)->translate_func ? (* (group)->translate_func) ((str), (group)->translate_data) : (str)))
#define NO_ARG(entry) ((entry)->arg == G_OPTION_ARG_NONE || \
((entry)->arg == G_OPTION_ARG_CALLBACK && \
((entry)->flags & G_OPTION_FLAG_NO_ARG)))
#define OPTIONAL_ARG(entry) ((entry)->arg == G_OPTION_ARG_CALLBACK && \
(entry)->flags & G_OPTION_FLAG_OPTIONAL_ARG)
typedef struct
{
GOptionArg arg_type;
gpointer arg_data;
union
{
gboolean bool;
gint integer;
gchar *str;
gchar **array;
gdouble dbl;
gint64 int64;
} prev;
union
{
gchar *str;
struct
{
gint len;
gchar **data;
} array;
} allocated;
} Change;
typedef struct
{
gchar **ptr;
gchar *value;
} PendingNull;
struct _GOptionContext
{
GList *groups;
gchar *parameter_string;
gchar *summary;
gchar *description;
GTranslateFunc translate_func;
GDestroyNotify translate_notify;
gpointer translate_data;
guint help_enabled : 1;
guint ignore_unknown : 1;
GOptionGroup *main_group;
/* We keep a list of change so we can revert them */
GList *changes;
/* We also keep track of all argv elements
* that should be NULLed or modified.
*/
GList *pending_nulls;
};
struct _GOptionGroup
{
gchar *name;
gchar *description;
gchar *help_description;
GDestroyNotify destroy_notify;
gpointer user_data;
GTranslateFunc translate_func;
GDestroyNotify translate_notify;
gpointer translate_data;
GOptionEntry *entries;
gint n_entries;
GOptionParseFunc pre_parse_func;
GOptionParseFunc post_parse_func;
GOptionErrorFunc error_func;
};
static void free_changes_list (GOptionContext *context,
gboolean revert);
static void free_pending_nulls (GOptionContext *context,
gboolean perform_nulls);
static int
_g_unichar_get_width (gunichar c)
{
if (G_UNLIKELY (g_unichar_iszerowidth (c)))
return 0;
/* we ignore the fact that we should call g_unichar_iswide_cjk() under
* some locales (legacy East Asian ones) */
if (g_unichar_iswide (c))
return 2;
return 1;
}
static glong
_g_utf8_strwidth (const gchar *p)
{
glong len = 0;
g_return_val_if_fail (p != NULL, 0);
while (*p)
{
len += _g_unichar_get_width (g_utf8_get_char (p));
p = g_utf8_next_char (p);
}
return len;
}
G_DEFINE_QUARK (g-option-context-error-quark, g_option_error)
/**
* g_option_context_new:
* @parameter_string: (allow-none): a string which is displayed in
* the first line of output, after the
* usage summary
* programname [OPTION...]
*
* Creates a new option context.
*
* The @parameter_string can serve multiple purposes. It can be used
* to add descriptions for "rest" arguments, which are not parsed by
* the #GOptionContext, typically something like "FILES" or
* "FILE1 FILE2...". If you are using #G_OPTION_REMAINING for
* collecting "rest" arguments, GLib handles this automatically by
* using the @arg_description of the corresponding #GOptionEntry in
* the usage summary.
*
* Another usage is to give a short summary of the program
* functionality, like " - frob the strings", which will be displayed
* in the same line as the usage. For a longer description of the
* program functionality that should be displayed as a paragraph
* below the usage line, use g_option_context_set_summary().
*
* Note that the @parameter_string is translated using the
* function set with g_option_context_set_translate_func(), so
* it should normally be passed untranslated.
*
* Returns: a newly created #GOptionContext, which must be
* freed with g_option_context_free() after use.
*
* Since: 2.6
*/
GOptionContext *
g_option_context_new (const gchar *parameter_string)
{
GOptionContext *context;
context = g_new0 (GOptionContext, 1);
context->parameter_string = g_strdup (parameter_string);
context->help_enabled = TRUE;
context->ignore_unknown = FALSE;
return context;
}
/**
* g_option_context_free:
* @context: a #GOptionContext
*
* Frees context and all the groups which have been
* added to it.
*
* Please note that parsed arguments need to be freed separately (see
* #GOptionEntry).
*
* Since: 2.6
*/
void g_option_context_free (GOptionContext *context)
{
g_return_if_fail (context != NULL);
g_list_free_full (context->groups, (GDestroyNotify) g_option_group_free);
if (context->main_group)
g_option_group_free (context->main_group);
free_changes_list (context, FALSE);
free_pending_nulls (context, FALSE);
g_free (context->parameter_string);
g_free (context->summary);
g_free (context->description);
if (context->translate_notify)
(* context->translate_notify) (context->translate_data);
g_free (context);
}
/**
* g_option_context_set_help_enabled:
* @context: a #GOptionContext
* @help_enabled: %TRUE to enable , %FALSE to disable it
*
* Enables or disables automatic generation of
* output. By default, g_option_context_parse() recognizes
* , ,
* ,
* and groupname and creates
* suitable output to stdout.
*
* Since: 2.6
*/
void g_option_context_set_help_enabled (GOptionContext *context,
gboolean help_enabled)
{
g_return_if_fail (context != NULL);
context->help_enabled = help_enabled;
}
/**
* g_option_context_get_help_enabled:
* @context: a #GOptionContext
*
* Returns whether automatic generation
* is turned on for @context. See g_option_context_set_help_enabled().
*
* Returns: %TRUE if automatic help generation is turned on.
*
* Since: 2.6
*/
gboolean
g_option_context_get_help_enabled (GOptionContext *context)
{
g_return_val_if_fail (context != NULL, FALSE);
return context->help_enabled;
}
/**
* g_option_context_set_ignore_unknown_options:
* @context: a #GOptionContext
* @ignore_unknown: %TRUE to ignore unknown options, %FALSE to produce
* an error when unknown options are met
*
* Sets whether to ignore unknown options or not. If an argument is
* ignored, it is left in the @argv array after parsing. By default,
* g_option_context_parse() treats unknown options as error.
*
* This setting does not affect non-option arguments (i.e. arguments
* which don't start with a dash). But note that GOption cannot reliably
* determine whether a non-option belongs to a preceding unknown option.
*
* Since: 2.6
**/
void
g_option_context_set_ignore_unknown_options (GOptionContext *context,
gboolean ignore_unknown)
{
g_return_if_fail (context != NULL);
context->ignore_unknown = ignore_unknown;
}
/**
* g_option_context_get_ignore_unknown_options:
* @context: a #GOptionContext
*
* Returns whether unknown options are ignored or not. See
* g_option_context_set_ignore_unknown_options().
*
* Returns: %TRUE if unknown options are ignored.
*
* Since: 2.6
**/
gboolean
g_option_context_get_ignore_unknown_options (GOptionContext *context)
{
g_return_val_if_fail (context != NULL, FALSE);
return context->ignore_unknown;
}
/**
* g_option_context_add_group:
* @context: a #GOptionContext
* @group: the group to add
*
* Adds a #GOptionGroup to the @context, so that parsing with @context
* will recognize the options in the group. Note that the group will
* be freed together with the context when g_option_context_free() is
* called, so you must not free the group yourself after adding it
* to a context.
*
* Since: 2.6
**/
void
g_option_context_add_group (GOptionContext *context,
GOptionGroup *group)
{
GList *list;
g_return_if_fail (context != NULL);
g_return_if_fail (group != NULL);
g_return_if_fail (group->name != NULL);
g_return_if_fail (group->description != NULL);
g_return_if_fail (group->help_description != NULL);
for (list = context->groups; list; list = list->next)
{
GOptionGroup *g = (GOptionGroup *)list->data;
if ((group->name == NULL && g->name == NULL) ||
(group->name && g->name && strcmp (group->name, g->name) == 0))
g_warning ("A group named \"%s\" is already part of this GOptionContext",
group->name);
}
context->groups = g_list_append (context->groups, group);
}
/**
* g_option_context_set_main_group:
* @context: a #GOptionContext
* @group: the group to set as main group
*
* Sets a #GOptionGroup as main group of the @context.
* This has the same effect as calling g_option_context_add_group(),
* the only difference is that the options in the main group are
* treated differently when generating output.
*
* Since: 2.6
**/
void
g_option_context_set_main_group (GOptionContext *context,
GOptionGroup *group)
{
g_return_if_fail (context != NULL);
g_return_if_fail (group != NULL);
if (context->main_group)
{
g_warning ("This GOptionContext already has a main group");
return;
}
context->main_group = group;
}
/**
* g_option_context_get_main_group:
* @context: a #GOptionContext
*
* Returns a pointer to the main group of @context.
*
* Return value: the main group of @context, or %NULL if @context doesn't
* have a main group. Note that group belongs to @context and should
* not be modified or freed.
*
* Since: 2.6
**/
GOptionGroup *
g_option_context_get_main_group (GOptionContext *context)
{
g_return_val_if_fail (context != NULL, NULL);
return context->main_group;
}
/**
* g_option_context_add_main_entries:
* @context: a #GOptionContext
* @entries: a %NULL-terminated array of #GOptionEntrys
* @translation_domain: (allow-none): a translation domain to use for translating
* the output for the options in @entries
* with gettext(), or %NULL
*
* A convenience function which creates a main group if it doesn't
* exist, adds the @entries to it and sets the translation domain.
*
* Since: 2.6
**/
void
g_option_context_add_main_entries (GOptionContext *context,
const GOptionEntry *entries,
const gchar *translation_domain)
{
g_return_if_fail (entries != NULL);
if (!context->main_group)
context->main_group = g_option_group_new (NULL, NULL, NULL, NULL, NULL);
g_option_group_add_entries (context->main_group, entries);
g_option_group_set_translation_domain (context->main_group, translation_domain);
}
static gint
calculate_max_length (GOptionGroup *group,
GHashTable *aliases)
{
GOptionEntry *entry;
gint i, len, max_length;
const gchar *long_name;
max_length = 0;
for (i = 0; i < group->n_entries; i++)
{
entry = &group->entries[i];
if (entry->flags & G_OPTION_FLAG_HIDDEN)
continue;
long_name = g_hash_table_lookup (aliases, &entry->long_name);
if (!long_name)
long_name = entry->long_name;
len = _g_utf8_strwidth (long_name);
if (entry->short_name)
len += 4;
if (!NO_ARG (entry) && entry->arg_description)
len += 1 + _g_utf8_strwidth (TRANSLATE (group, entry->arg_description));
max_length = MAX (max_length, len);
}
return max_length;
}
static void
print_entry (GOptionGroup *group,
gint max_length,
const GOptionEntry *entry,
GString *string,
GHashTable *aliases)
{
GString *str;
const gchar *long_name;
if (entry->flags & G_OPTION_FLAG_HIDDEN)
return;
if (entry->long_name[0] == 0)
return;
long_name = g_hash_table_lookup (aliases, &entry->long_name);
if (!long_name)
long_name = entry->long_name;
str = g_string_new (NULL);
if (entry->short_name)
g_string_append_printf (str, " -%c, --%s", entry->short_name, long_name);
else
g_string_append_printf (str, " --%s", long_name);
if (entry->arg_description)
g_string_append_printf (str, "=%s", TRANSLATE (group, entry->arg_description));
g_string_append_printf (string, "%s%*s %s\n", str->str,
(int) (max_length + 4 - _g_utf8_strwidth (str->str)), "",
entry->description ? TRANSLATE (group, entry->description) : "");
g_string_free (str, TRUE);
}
static gboolean
group_has_visible_entries (GOptionContext *context,
GOptionGroup *group,
gboolean main_entries)
{
GOptionFlags reject_filter = G_OPTION_FLAG_HIDDEN;
GOptionEntry *entry;
gint i, l;
gboolean main_group = group == context->main_group;
if (!main_entries)
reject_filter |= G_OPTION_FLAG_IN_MAIN;
for (i = 0, l = (group ? group->n_entries : 0); i < l; i++)
{
entry = &group->entries[i];
if (main_entries && !main_group && !(entry->flags & G_OPTION_FLAG_IN_MAIN))
continue;
if (entry->long_name[0] == 0) /* ignore rest entry */
continue;
if (!(entry->flags & reject_filter))
return TRUE;
}
return FALSE;
}
static gboolean
group_list_has_visible_entries (GOptionContext *context,
GList *group_list,
gboolean main_entries)
{
while (group_list)
{
if (group_has_visible_entries (context, group_list->data, main_entries))
return TRUE;
group_list = group_list->next;
}
return FALSE;
}
static gboolean
context_has_h_entry (GOptionContext *context)
{
gsize i;
GList *list;
if (context->main_group)
{
for (i = 0; i < context->main_group->n_entries; i++)
{
if (context->main_group->entries[i].short_name == 'h')
return TRUE;
}
}
for (list = context->groups; list != NULL; list = g_list_next (list))
{
GOptionGroup *group;
group = (GOptionGroup*)list->data;
for (i = 0; i < group->n_entries; i++)
{
if (group->entries[i].short_name == 'h')
return TRUE;
}
}
return FALSE;
}
/**
* g_option_context_get_help:
* @context: a #GOptionContext
* @main_help: if %TRUE, only include the main group
* @group: (allow-none): the #GOptionGroup to create help for, or %NULL
*
* Returns a formatted, translated help text for the given context.
* To obtain the text produced by , call
* g_option_context_get_help (context, TRUE, NULL).
* To obtain the text produced by , call
* g_option_context_get_help (context, FALSE, NULL).
* To obtain the help text for an option group, call
* g_option_context_get_help (context, FALSE, group).
*
* Returns: A newly allocated string containing the help text
*
* Since: 2.14
*/
gchar *
g_option_context_get_help (GOptionContext *context,
gboolean main_help,
GOptionGroup *group)
{
GList *list;
gint max_length = 0, len;
gint i;
GOptionEntry *entry;
GHashTable *shadow_map;
GHashTable *aliases;
gboolean seen[256];
const gchar *rest_description;
GString *string;
guchar token;
string = g_string_sized_new (1024);
rest_description = NULL;
if (context->main_group)
{
for (i = 0; i < context->main_group->n_entries; i++)
{
entry = &context->main_group->entries[i];
if (entry->long_name[0] == 0)
{
rest_description = TRANSLATE (context->main_group, entry->arg_description);
break;
}
}
}
g_string_append_printf (string, "%s\n %s %s",
_("Usage:"), g_get_prgname(), _("[OPTION...]"));
if (rest_description)
{
g_string_append (string, " ");
g_string_append (string, rest_description);
}
if (context->parameter_string)
{
g_string_append (string, " ");
g_string_append (string, TRANSLATE (context, context->parameter_string));
}
g_string_append (string, "\n\n");
if (context->summary)
{
g_string_append (string, TRANSLATE (context, context->summary));
g_string_append (string, "\n\n");
}
memset (seen, 0, sizeof (gboolean) * 256);
shadow_map = g_hash_table_new (g_str_hash, g_str_equal);
aliases = g_hash_table_new_full (NULL, NULL, NULL, g_free);
if (context->main_group)
{
for (i = 0; i < context->main_group->n_entries; i++)
{
entry = &context->main_group->entries[i];
g_hash_table_insert (shadow_map,
(gpointer)entry->long_name,
entry);
if (seen[(guchar)entry->short_name])
entry->short_name = 0;
else
seen[(guchar)entry->short_name] = TRUE;
}
}
list = context->groups;
while (list != NULL)
{
GOptionGroup *g = list->data;
for (i = 0; i < g->n_entries; i++)
{
entry = &g->entries[i];
if (g_hash_table_lookup (shadow_map, entry->long_name) &&
!(entry->flags & G_OPTION_FLAG_NOALIAS))
{
g_hash_table_insert (aliases, &entry->long_name,
g_strdup_printf ("%s-%s", g->name, entry->long_name));
}
else
g_hash_table_insert (shadow_map, (gpointer)entry->long_name, entry);
if (seen[(guchar)entry->short_name] &&
!(entry->flags & G_OPTION_FLAG_NOALIAS))
entry->short_name = 0;
else
seen[(guchar)entry->short_name] = TRUE;
}
list = list->next;
}
g_hash_table_destroy (shadow_map);
list = context->groups;
if (context->help_enabled)
{
max_length = _g_utf8_strwidth ("-?, --help");
if (list)
{
len = _g_utf8_strwidth ("--help-all");
max_length = MAX (max_length, len);
}
}
if (context->main_group)
{
len = calculate_max_length (context->main_group, aliases);
max_length = MAX (max_length, len);
}
while (list != NULL)
{
GOptionGroup *g = list->data;
if (context->help_enabled)
{
/* First, we check the --help- options */
len = _g_utf8_strwidth ("--help-") + _g_utf8_strwidth (g->name);
max_length = MAX (max_length, len);
}
/* Then we go through the entries */
len = calculate_max_length (g, aliases);
max_length = MAX (max_length, len);
list = list->next;
}
/* Add a bit of padding */
max_length += 4;
if (!group && context->help_enabled)
{
list = context->groups;
token = context_has_h_entry (context) ? '?' : 'h';
g_string_append_printf (string, "%s\n -%c, --%-*s %s\n",
_("Help Options:"), token, max_length - 4, "help",
_("Show help options"));
/* We only want --help-all when there are groups */
if (list)
g_string_append_printf (string, " --%-*s %s\n",
max_length, "help-all",
_("Show all help options"));
while (list)
{
GOptionGroup *g = list->data;
if (group_has_visible_entries (context, g, FALSE))
g_string_append_printf (string, " --help-%-*s %s\n",
max_length - 5, g->name,
TRANSLATE (g, g->help_description));
list = list->next;
}
g_string_append (string, "\n");
}
if (group)
{
/* Print a certain group */
if (group_has_visible_entries (context, group, FALSE))
{
g_string_append (string, TRANSLATE (group, group->description));
g_string_append (string, "\n");
for (i = 0; i < group->n_entries; i++)
print_entry (group, max_length, &group->entries[i], string, aliases);
g_string_append (string, "\n");
}
}
else if (!main_help)
{
/* Print all groups */
list = context->groups;
while (list)
{
GOptionGroup *g = list->data;
if (group_has_visible_entries (context, g, FALSE))
{
g_string_append (string, g->description);
g_string_append (string, "\n");
for (i = 0; i < g->n_entries; i++)
if (!(g->entries[i].flags & G_OPTION_FLAG_IN_MAIN))
print_entry (g, max_length, &g->entries[i], string, aliases);
g_string_append (string, "\n");
}
list = list->next;
}
}
/* Print application options if --help or --help-all has been specified */
if ((main_help || !group) &&
(group_has_visible_entries (context, context->main_group, TRUE) ||
group_list_has_visible_entries (context, context->groups, TRUE)))
{
list = context->groups;
g_string_append (string, _("Application Options:"));
g_string_append (string, "\n");
if (context->main_group)
for (i = 0; i < context->main_group->n_entries; i++)
print_entry (context->main_group, max_length,
&context->main_group->entries[i], string, aliases);
while (list != NULL)
{
GOptionGroup *g = list->data;
/* Print main entries from other groups */
for (i = 0; i < g->n_entries; i++)
if (g->entries[i].flags & G_OPTION_FLAG_IN_MAIN)
print_entry (g, max_length, &g->entries[i], string, aliases);
list = list->next;
}
g_string_append (string, "\n");
}
if (context->description)
{
g_string_append (string, TRANSLATE (context, context->description));
g_string_append (string, "\n");
}
g_hash_table_destroy (aliases);
return g_string_free (string, FALSE);
}
G_GNUC_NORETURN
static void
print_help (GOptionContext *context,
gboolean main_help,
GOptionGroup *group)
{
gchar *help;
help = g_option_context_get_help (context, main_help, group);
g_print ("%s", help);
g_free (help);
exit (0);
}
static gboolean
parse_int (const gchar *arg_name,
const gchar *arg,
gint *result,
GError **error)
{
gchar *end;
glong tmp;
errno = 0;
tmp = strtol (arg, &end, 0);
if (*arg == '\0' || *end != '\0')
{
g_set_error (error,
G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
_("Cannot parse integer value '%s' for %s"),
arg, arg_name);
return FALSE;
}
*result = tmp;
if (*result != tmp || errno == ERANGE)
{
g_set_error (error,
G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
_("Integer value '%s' for %s out of range"),
arg, arg_name);
return FALSE;
}
return TRUE;
}
static gboolean
parse_double (const gchar *arg_name,
const gchar *arg,
gdouble *result,
GError **error)
{
gchar *end;
gdouble tmp;
errno = 0;
tmp = g_strtod (arg, &end);
if (*arg == '\0' || *end != '\0')
{
g_set_error (error,
G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
_("Cannot parse double value '%s' for %s"),
arg, arg_name);
return FALSE;
}
if (errno == ERANGE)
{
g_set_error (error,
G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
_("Double value '%s' for %s out of range"),
arg, arg_name);
return FALSE;
}
*result = tmp;
return TRUE;
}
static gboolean
parse_int64 (const gchar *arg_name,
const gchar *arg,
gint64 *result,
GError **error)
{
gchar *end;
gint64 tmp;
errno = 0;
tmp = g_ascii_strtoll (arg, &end, 0);
if (*arg == '\0' || *end != '\0')
{
g_set_error (error,
G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
_("Cannot parse integer value '%s' for %s"),
arg, arg_name);
return FALSE;
}
if (errno == ERANGE)
{
g_set_error (error,
G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
_("Integer value '%s' for %s out of range"),
arg, arg_name);
return FALSE;
}
*result = tmp;
return TRUE;
}
static Change *
get_change (GOptionContext *context,
GOptionArg arg_type,
gpointer arg_data)
{
GList *list;
Change *change = NULL;
for (list = context->changes; list != NULL; list = list->next)
{
change = list->data;
if (change->arg_data == arg_data)
goto found;
}
change = g_new0 (Change, 1);
change->arg_type = arg_type;
change->arg_data = arg_data;
context->changes = g_list_prepend (context->changes, change);
found:
return change;
}
static void
add_pending_null (GOptionContext *context,
gchar **ptr,
gchar *value)
{
PendingNull *n;
n = g_new0 (PendingNull, 1);
n->ptr = ptr;
n->value = value;
context->pending_nulls = g_list_prepend (context->pending_nulls, n);
}
static gboolean
parse_arg (GOptionContext *context,
GOptionGroup *group,
GOptionEntry *entry,
const gchar *value,
const gchar *option_name,
GError **error)
{
Change *change;
g_assert (value || OPTIONAL_ARG (entry) || NO_ARG (entry));
switch (entry->arg)
{
case G_OPTION_ARG_NONE:
{
change = get_change (context, G_OPTION_ARG_NONE,
entry->arg_data);
*(gboolean *)entry->arg_data = !(entry->flags & G_OPTION_FLAG_REVERSE);
break;
}
case G_OPTION_ARG_STRING:
{
gchar *data;
data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
if (!data)
return FALSE;
change = get_change (context, G_OPTION_ARG_STRING,
entry->arg_data);
g_free (change->allocated.str);
change->prev.str = *(gchar **)entry->arg_data;
change->allocated.str = data;
*(gchar **)entry->arg_data = data;
break;
}
case G_OPTION_ARG_STRING_ARRAY:
{
gchar *data;
data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
if (!data)
return FALSE;
change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
entry->arg_data);
if (change->allocated.array.len == 0)
{
change->prev.array = *(gchar ***)entry->arg_data;
change->allocated.array.data = g_new (gchar *, 2);
}
else
change->allocated.array.data =
g_renew (gchar *, change->allocated.array.data,
change->allocated.array.len + 2);
change->allocated.array.data[change->allocated.array.len] = data;
change->allocated.array.data[change->allocated.array.len + 1] = NULL;
change->allocated.array.len ++;
*(gchar ***)entry->arg_data = change->allocated.array.data;
break;
}
case G_OPTION_ARG_FILENAME:
{
gchar *data;
#ifdef G_OS_WIN32
data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
if (!data)
return FALSE;
#else
data = g_strdup (value);
#endif
change = get_change (context, G_OPTION_ARG_FILENAME,
entry->arg_data);
g_free (change->allocated.str);
change->prev.str = *(gchar **)entry->arg_data;
change->allocated.str = data;
*(gchar **)entry->arg_data = data;
break;
}
case G_OPTION_ARG_FILENAME_ARRAY:
{
gchar *data;
#ifdef G_OS_WIN32
data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
if (!data)
return FALSE;
#else
data = g_strdup (value);
#endif
change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
entry->arg_data);
if (change->allocated.array.len == 0)
{
change->prev.array = *(gchar ***)entry->arg_data;
change->allocated.array.data = g_new (gchar *, 2);
}
else
change->allocated.array.data =
g_renew (gchar *, change->allocated.array.data,
change->allocated.array.len + 2);
change->allocated.array.data[change->allocated.array.len] = data;
change->allocated.array.data[change->allocated.array.len + 1] = NULL;
change->allocated.array.len ++;
*(gchar ***)entry->arg_data = change->allocated.array.data;
break;
}
case G_OPTION_ARG_INT:
{
gint data;
if (!parse_int (option_name, value,
&data,
error))
return FALSE;
change = get_change (context, G_OPTION_ARG_INT,
entry->arg_data);
change->prev.integer = *(gint *)entry->arg_data;
*(gint *)entry->arg_data = data;
break;
}
case G_OPTION_ARG_CALLBACK:
{
gchar *data;
gboolean retval;
if (!value && entry->flags & G_OPTION_FLAG_OPTIONAL_ARG)
data = NULL;
else if (entry->flags & G_OPTION_FLAG_NO_ARG)
data = NULL;
else if (entry->flags & G_OPTION_FLAG_FILENAME)
{
#ifdef G_OS_WIN32
data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
#else
data = g_strdup (value);
#endif
}
else
data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
if (!(entry->flags & (G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG)) &&
!data)
return FALSE;
retval = (* (GOptionArgFunc) entry->arg_data) (option_name, data, group->user_data, error);
if (!retval && error != NULL && *error == NULL)
g_set_error (error,
G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
_("Error parsing option %s"), option_name);
g_free (data);
return retval;
break;
}
case G_OPTION_ARG_DOUBLE:
{
gdouble data;
if (!parse_double (option_name, value,
&data,
error))
{
return FALSE;
}
change = get_change (context, G_OPTION_ARG_DOUBLE,
entry->arg_data);
change->prev.dbl = *(gdouble *)entry->arg_data;
*(gdouble *)entry->arg_data = data;
break;
}
case G_OPTION_ARG_INT64:
{
gint64 data;
if (!parse_int64 (option_name, value,
&data,
error))
{
return FALSE;
}
change = get_change (context, G_OPTION_ARG_INT64,
entry->arg_data);
change->prev.int64 = *(gint64 *)entry->arg_data;
*(gint64 *)entry->arg_data = data;
break;
}
default:
g_assert_not_reached ();
}
return TRUE;
}
static gboolean
parse_short_option (GOptionContext *context,
GOptionGroup *group,
gint idx,
gint *new_idx,
gchar arg,
gint *argc,
gchar ***argv,
GError **error,
gboolean *parsed)
{
gint j;
for (j = 0; j < group->n_entries; j++)
{
if (arg == group->entries[j].short_name)
{
gchar *option_name;
gchar *value = NULL;
option_name = g_strdup_printf ("-%c", group->entries[j].short_name);
if (NO_ARG (&group->entries[j]))
value = NULL;
else
{
if (*new_idx > idx)
{
g_set_error (error,
G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
_("Error parsing option %s"), option_name);
g_free (option_name);
return FALSE;
}
if (idx < *argc - 1)
{
if (!OPTIONAL_ARG (&group->entries[j]))
{
value = (*argv)[idx + 1];
add_pending_null (context, &((*argv)[idx + 1]), NULL);
*new_idx = idx + 1;
}
else
{
if ((*argv)[idx + 1][0] == '-')
value = NULL;
else
{
value = (*argv)[idx + 1];
add_pending_null (context, &((*argv)[idx + 1]), NULL);
*new_idx = idx + 1;
}
}
}
else if (idx >= *argc - 1 && OPTIONAL_ARG (&group->entries[j]))
value = NULL;
else
{
g_set_error (error,
G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
_("Missing argument for %s"), option_name);
g_free (option_name);
return FALSE;
}
}
if (!parse_arg (context, group, &group->entries[j],
value, option_name, error))
{
g_free (option_name);
return FALSE;
}
g_free (option_name);
*parsed = TRUE;
}
}
return TRUE;
}
static gboolean
parse_long_option (GOptionContext *context,
GOptionGroup *group,
gint *idx,
gchar *arg,
gboolean aliased,
gint *argc,
gchar ***argv,
GError **error,
gboolean *parsed)
{
gint j;
for (j = 0; j < group->n_entries; j++)
{
if (*idx >= *argc)
return TRUE;
if (aliased && (group->entries[j].flags & G_OPTION_FLAG_NOALIAS))
continue;
if (NO_ARG (&group->entries[j]) &&
strcmp (arg, group->entries[j].long_name) == 0)
{
gchar *option_name;
gboolean retval;
option_name = g_strconcat ("--", group->entries[j].long_name, NULL);
retval = parse_arg (context, group, &group->entries[j],
NULL, option_name, error);
g_free (option_name);
add_pending_null (context, &((*argv)[*idx]), NULL);
*parsed = TRUE;
return retval;
}
else
{
gint len = strlen (group->entries[j].long_name);
if (strncmp (arg, group->entries[j].long_name, len) == 0 &&
(arg[len] == '=' || arg[len] == 0))
{
gchar *value = NULL;
gchar *option_name;
add_pending_null (context, &((*argv)[*idx]), NULL);
option_name = g_strconcat ("--", group->entries[j].long_name, NULL);
if (arg[len] == '=')
value = arg + len + 1;
else if (*idx < *argc - 1)
{
if (!OPTIONAL_ARG (&group->entries[j]))
{
value = (*argv)[*idx + 1];
add_pending_null (context, &((*argv)[*idx + 1]), NULL);
(*idx)++;
}
else
{
if ((*argv)[*idx + 1][0] == '-')
{
gboolean retval;
retval = parse_arg (context, group, &group->entries[j],
NULL, option_name, error);
*parsed = TRUE;
g_free (option_name);
return retval;
}
else
{
value = (*argv)[*idx + 1];
add_pending_null (context, &((*argv)[*idx + 1]), NULL);
(*idx)++;
}
}
}
else if (*idx >= *argc - 1 && OPTIONAL_ARG (&group->entries[j]))
{
gboolean retval;
retval = parse_arg (context, group, &group->entries[j],
NULL, option_name, error);
*parsed = TRUE;
g_free (option_name);
return retval;
}
else
{
g_set_error (error,
G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
_("Missing argument for %s"), option_name);
g_free (option_name);
return FALSE;
}
if (!parse_arg (context, group, &group->entries[j],
value, option_name, error))
{
g_free (option_name);
return FALSE;
}
g_free (option_name);
*parsed = TRUE;
}
}
}
return TRUE;
}
static gboolean
parse_remaining_arg (GOptionContext *context,
GOptionGroup *group,
gint *idx,
gint *argc,
gchar ***argv,
GError **error,
gboolean *parsed)
{
gint j;
for (j = 0; j < group->n_entries; j++)
{
if (*idx >= *argc)
return TRUE;
if (group->entries[j].long_name[0])
continue;
g_return_val_if_fail (group->entries[j].arg == G_OPTION_ARG_CALLBACK ||
group->entries[j].arg == G_OPTION_ARG_STRING_ARRAY ||
group->entries[j].arg == G_OPTION_ARG_FILENAME_ARRAY, FALSE);
add_pending_null (context, &((*argv)[*idx]), NULL);
if (!parse_arg (context, group, &group->entries[j], (*argv)[*idx], "", error))
return FALSE;
*parsed = TRUE;
return TRUE;
}
return TRUE;
}
static void
free_changes_list (GOptionContext *context,
gboolean revert)
{
GList *list;
for (list = context->changes; list != NULL; list = list->next)
{
Change *change = list->data;
if (revert)
{
switch (change->arg_type)
{
case G_OPTION_ARG_NONE:
*(gboolean *)change->arg_data = change->prev.bool;
break;
case G_OPTION_ARG_INT:
*(gint *)change->arg_data = change->prev.integer;
break;
case G_OPTION_ARG_STRING:
case G_OPTION_ARG_FILENAME:
g_free (change->allocated.str);
*(gchar **)change->arg_data = change->prev.str;
break;
case G_OPTION_ARG_STRING_ARRAY:
case G_OPTION_ARG_FILENAME_ARRAY:
g_strfreev (change->allocated.array.data);
*(gchar ***)change->arg_data = change->prev.array;
break;
case G_OPTION_ARG_DOUBLE:
*(gdouble *)change->arg_data = change->prev.dbl;
break;
case G_OPTION_ARG_INT64:
*(gint64 *)change->arg_data = change->prev.int64;
break;
default:
g_assert_not_reached ();
}
}
g_free (change);
}
g_list_free (context->changes);
context->changes = NULL;
}
static void
free_pending_nulls (GOptionContext *context,
gboolean perform_nulls)
{
GList *list;
for (list = context->pending_nulls; list != NULL; list = list->next)
{
PendingNull *n = list->data;
if (perform_nulls)
{
if (n->value)
{
/* Copy back the short options */
*(n->ptr)[0] = '-';
strcpy (*n->ptr + 1, n->value);
}
else
*n->ptr = NULL;
}
g_free (n->value);
g_free (n);
}
g_list_free (context->pending_nulls);
context->pending_nulls = NULL;
}
/* Use a platform-specific mechanism to look up the first argument to
* the current process.
* Note if you implement this for other platforms, also add it to
* tests/option-argv0.c
*/
static char *
platform_get_argv0 (void)
{
#if defined __linux
char *cmdline;
char *base_arg0;
gsize len;
if (!g_file_get_contents ("/proc/self/cmdline",
&cmdline,
&len,
NULL))
return NULL;
/* Sanity check for a NUL terminator. */
if (!memchr (cmdline, 0, len))
return NULL;
/* We could just return cmdline, but I think it's better
* to hold on to a smaller malloc block; the arguments
* could be large.
*/
base_arg0 = g_path_get_basename (cmdline);
g_free (cmdline);
return base_arg0;
#elif defined __OpenBSD__
char **cmdline = NULL;
char *base_arg0;
gsize len = PATH_MAX;
int mib[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
cmdline = (char **) realloc (cmdline, len);
if (sysctl (mib, G_N_ELEMENTS (mib), cmdline, &len, NULL, 0) == -1)
{
g_free (cmdline);
return NULL;
}
/* We could just return cmdline, but I think it's better
* to hold on to a smaller malloc block; the arguments
* could be large.
*/
base_arg0 = g_path_get_basename (*cmdline);
g_free (cmdline);
return base_arg0;
#endif
return NULL;
}
/**
* g_option_context_parse:
* @context: a #GOptionContext
* @argc: (inout) (allow-none): a pointer to the number of command line arguments
* @argv: (inout) (array length=argc) (allow-none): a pointer to the array of command line arguments
* @error: a return location for errors
*
* Parses the command line arguments, recognizing options
* which have been added to @context. A side-effect of
* calling this function is that g_set_prgname() will be
* called.
*
* If the parsing is successful, any parsed arguments are
* removed from the array and @argc and @argv are updated
* accordingly. A '--' option is stripped from @argv
* unless there are unparsed options before and after it,
* or some of the options after it start with '-'. In case
* of an error, @argc and @argv are left unmodified.
*
* If automatic support is enabled
* (see g_option_context_set_help_enabled()), and the
* @argv array contains one of the recognized help options,
* this function will produce help output to stdout and
* call exit (0).
*
* Note that function depends on the
* current locale for
* automatic character set conversion of string and filename
* arguments.
*
* Return value: %TRUE if the parsing was successful,
* %FALSE if an error occurred
*
* Since: 2.6
**/
gboolean
g_option_context_parse (GOptionContext *context,
gint *argc,
gchar ***argv,
GError **error)
{
gint i, j, k;
GList *list;
/* Set program name */
if (!g_get_prgname())
{
gchar *prgname;
if (argc && argv && *argc)
prgname = g_path_get_basename ((*argv)[0]);
else
prgname = platform_get_argv0 ();
if (prgname)
g_set_prgname (prgname);
else
g_set_prgname ("");
g_free (prgname);
}
/* Call pre-parse hooks */
list = context->groups;
while (list)
{
GOptionGroup *group = list->data;
if (group->pre_parse_func)
{
if (!(* group->pre_parse_func) (context, group,
group->user_data, error))
goto fail;
}
list = list->next;
}
if (context->main_group && context->main_group->pre_parse_func)
{
if (!(* context->main_group->pre_parse_func) (context, context->main_group,
context->main_group->user_data, error))
goto fail;
}
if (argc && argv)
{
gboolean stop_parsing = FALSE;
gboolean has_unknown = FALSE;
gint separator_pos = 0;
for (i = 1; i < *argc; i++)
{
gchar *arg, *dash;
gboolean parsed = FALSE;
if ((*argv)[i][0] == '-' && (*argv)[i][1] != '\0' && !stop_parsing)
{
if ((*argv)[i][1] == '-')
{
/* -- option */
arg = (*argv)[i] + 2;
/* '--' terminates list of arguments */
if (*arg == 0)
{
separator_pos = i;
stop_parsing = TRUE;
continue;
}
/* Handle help options */
if (context->help_enabled)
{
if (strcmp (arg, "help") == 0)
print_help (context, TRUE, NULL);
else if (strcmp (arg, "help-all") == 0)
print_help (context, FALSE, NULL);
else if (strncmp (arg, "help-", 5) == 0)
{
list = context->groups;
while (list)
{
GOptionGroup *group = list->data;
if (strcmp (arg + 5, group->name) == 0)
print_help (context, FALSE, group);
list = list->next;
}
}
}
if (context->main_group &&
!parse_long_option (context, context->main_group, &i, arg,
FALSE, argc, argv, error, &parsed))
goto fail;
if (parsed)
continue;
/* Try the groups */
list = context->groups;
while (list)
{
GOptionGroup *group = list->data;
if (!parse_long_option (context, group, &i, arg,
FALSE, argc, argv, error, &parsed))
goto fail;
if (parsed)
break;
list = list->next;
}
if (parsed)
continue;
/* Now look for ---@name
* @description: a description for this group to be shown in
* . This string is translated using the translation
* domain or translation function of the group
* @help_description: a description for the @name option.
* This string is translated using the translation domain or translation function
* of the group
* @user_data: (allow-none): user data that will be passed to the pre- and post-parse hooks,
* the error hook and to callbacks of %G_OPTION_ARG_CALLBACK options, or %NULL
* @destroy: (allow-none): a function that will be called to free @user_data, or %NULL
*
* Creates a new #GOptionGroup.
*
* Return value: a newly created option group. It should be added
* to a #GOptionContext or freed with g_option_group_free().
*
* Since: 2.6
**/
GOptionGroup *
g_option_group_new (const gchar *name,
const gchar *description,
const gchar *help_description,
gpointer user_data,
GDestroyNotify destroy)
{
GOptionGroup *group;
group = g_new0 (GOptionGroup, 1);
group->name = g_strdup (name);
group->description = g_strdup (description);
group->help_description = g_strdup (help_description);
group->user_data = user_data;
group->destroy_notify = destroy;
return group;
}
/**
* g_option_group_free:
* @group: a #GOptionGroup
*
* Frees a #GOptionGroup. Note that you must not
* free groups which have been added to a #GOptionContext.
*
* Since: 2.6
**/
void
g_option_group_free (GOptionGroup *group)
{
g_return_if_fail (group != NULL);
g_free (group->name);
g_free (group->description);
g_free (group->help_description);
g_free (group->entries);
if (group->destroy_notify)
(* group->destroy_notify) (group->user_data);
if (group->translate_notify)
(* group->translate_notify) (group->translate_data);
g_free (group);
}
/**
* g_option_group_add_entries:
* @group: a #GOptionGroup
* @entries: a %NULL-terminated array of #GOptionEntrys
*
* Adds the options specified in @entries to @group.
*
* Since: 2.6
**/
void
g_option_group_add_entries (GOptionGroup *group,
const GOptionEntry *entries)
{
gint i, n_entries;
g_return_if_fail (entries != NULL);
for (n_entries = 0; entries[n_entries].long_name != NULL; n_entries++) ;
group->entries = g_renew (GOptionEntry, group->entries, group->n_entries + n_entries);
memcpy (group->entries + group->n_entries, entries, sizeof (GOptionEntry) * n_entries);
for (i = group->n_entries; i < group->n_entries + n_entries; i++)
{
gchar c = group->entries[i].short_name;
if (c == '-' || (c != 0 && !g_ascii_isprint (c)))
{
g_warning (G_STRLOC ": ignoring invalid short option '%c' (%d) in entry %s:%s",
c, c, group->name, group->entries[i].long_name);
group->entries[i].short_name = '\0';
}
if (group->entries[i].arg != G_OPTION_ARG_NONE &&
(group->entries[i].flags & G_OPTION_FLAG_REVERSE) != 0)
{
g_warning (G_STRLOC ": ignoring reverse flag on option of arg-type %d in entry %s:%s",
group->entries[i].arg, group->name, group->entries[i].long_name);
group->entries[i].flags &= ~G_OPTION_FLAG_REVERSE;
}
if (group->entries[i].arg != G_OPTION_ARG_CALLBACK &&
(group->entries[i].flags & (G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG|G_OPTION_FLAG_FILENAME)) != 0)
{
g_warning (G_STRLOC ": ignoring no-arg, optional-arg or filename flags (%d) on option of arg-type %d in entry %s:%s",
group->entries[i].flags, group->entries[i].arg, group->name, group->entries[i].long_name);
group->entries[i].flags &= ~(G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG|G_OPTION_FLAG_FILENAME);
}
}
group->n_entries += n_entries;
}
/**
* g_option_group_set_parse_hooks:
* @group: a #GOptionGroup
* @pre_parse_func: (allow-none): a function to call before parsing, or %NULL
* @post_parse_func: (allow-none): a function to call after parsing, or %NULL
*
* Associates two functions with @group which will be called
* from g_option_context_parse() before the first option is parsed
* and after the last option has been parsed, respectively.
*
* Note that the user data to be passed to @pre_parse_func and
* @post_parse_func can be specified when constructing the group
* with g_option_group_new().
*
* Since: 2.6
**/
void
g_option_group_set_parse_hooks (GOptionGroup *group,
GOptionParseFunc pre_parse_func,
GOptionParseFunc post_parse_func)
{
g_return_if_fail (group != NULL);
group->pre_parse_func = pre_parse_func;
group->post_parse_func = post_parse_func;
}
/**
* g_option_group_set_error_hook:
* @group: a #GOptionGroup
* @error_func: a function to call when an error occurs
*
* Associates a function with @group which will be called
* from g_option_context_parse() when an error occurs.
*
* Note that the user data to be passed to @error_func can be
* specified when constructing the group with g_option_group_new().
*
* Since: 2.6
**/
void
g_option_group_set_error_hook (GOptionGroup *group,
GOptionErrorFunc error_func)
{
g_return_if_fail (group != NULL);
group->error_func = error_func;
}
/**
* g_option_group_set_translate_func:
* @group: a #GOptionGroup
* @func: (allow-none): the #GTranslateFunc, or %NULL
* @data: (allow-none): user data to pass to @func, or %NULL
* @destroy_notify: (allow-none): a function which gets called to free @data, or %NULL
*
* Sets the function which is used to translate user-visible
* strings, for output. Different
* groups can use different #GTranslateFuncs. If @func
* is %NULL, strings are not translated.
*
* If you are using gettext(), you only need to set the translation
* domain, see g_option_group_set_translation_domain().
*
* Since: 2.6
**/
void
g_option_group_set_translate_func (GOptionGroup *group,
GTranslateFunc func,
gpointer data,
GDestroyNotify destroy_notify)
{
g_return_if_fail (group != NULL);
if (group->translate_notify)
group->translate_notify (group->translate_data);
group->translate_func = func;
group->translate_data = data;
group->translate_notify = destroy_notify;
}
static const gchar *
dgettext_swapped (const gchar *msgid,
const gchar *domainname)
{
return g_dgettext (domainname, msgid);
}
/**
* g_option_group_set_translation_domain:
* @group: a #GOptionGroup
* @domain: the domain to use
*
* A convenience function to use gettext() for translating
* user-visible strings.
*
* Since: 2.6
**/
void
g_option_group_set_translation_domain (GOptionGroup *group,
const gchar *domain)
{
g_return_if_fail (group != NULL);
g_option_group_set_translate_func (group,
(GTranslateFunc)dgettext_swapped,
g_strdup (domain),
g_free);
}
/**
* g_option_context_set_translate_func:
* @context: a #GOptionContext
* @func: (allow-none): the #GTranslateFunc, or %NULL
* @data: (allow-none): user data to pass to @func, or %NULL
* @destroy_notify: (allow-none): a function which gets called to free @data, or %NULL
*
* Sets the function which is used to translate the contexts
* user-visible strings, for output.
* If @func is %NULL, strings are not translated.
*
* Note that option groups have their own translation functions,
* this function only affects the @parameter_string (see g_option_context_new()),
* the summary (see g_option_context_set_summary()) and the description
* (see g_option_context_set_description()).
*
* If you are using gettext(), you only need to set the translation
* domain, see g_option_context_set_translation_domain().
*
* Since: 2.12
**/
void
g_option_context_set_translate_func (GOptionContext *context,
GTranslateFunc func,
gpointer data,
GDestroyNotify destroy_notify)
{
g_return_if_fail (context != NULL);
if (context->translate_notify)
context->translate_notify (context->translate_data);
context->translate_func = func;
context->translate_data = data;
context->translate_notify = destroy_notify;
}
/**
* g_option_context_set_translation_domain:
* @context: a #GOptionContext
* @domain: the domain to use
*
* A convenience function to use gettext() for translating
* user-visible strings.
*
* Since: 2.12
**/
void
g_option_context_set_translation_domain (GOptionContext *context,
const gchar *domain)
{
g_return_if_fail (context != NULL);
g_option_context_set_translate_func (context,
(GTranslateFunc)dgettext_swapped,
g_strdup (domain),
g_free);
}
/**
* g_option_context_set_summary:
* @context: a #GOptionContext
* @summary: (allow-none): a string to be shown in output
* before the list of options, or %NULL
*
* Adds a string to be displayed in output
* before the list of options. This is typically a summary of the
* program functionality.
*
* Note that the summary is translated (see
* g_option_context_set_translate_func() and
* g_option_context_set_translation_domain()).
*
* Since: 2.12
*/
void
g_option_context_set_summary (GOptionContext *context,
const gchar *summary)
{
g_return_if_fail (context != NULL);
g_free (context->summary);
context->summary = g_strdup (summary);
}
/**
* g_option_context_get_summary:
* @context: a #GOptionContext
*
* Returns the summary. See g_option_context_set_summary().
*
* Returns: the summary
*
* Since: 2.12
*/
const gchar *
g_option_context_get_summary (GOptionContext *context)
{
g_return_val_if_fail (context != NULL, NULL);
return context->summary;
}
/**
* g_option_context_set_description:
* @context: a #GOptionContext
* @description: (allow-none): a string to be shown in output
* after the list of options, or %NULL
*
* Adds a string to be displayed in output
* after the list of options. This text often includes a bug reporting
* address.
*
* Note that the summary is translated (see
* g_option_context_set_translate_func()).
*
* Since: 2.12
*/
void
g_option_context_set_description (GOptionContext *context,
const gchar *description)
{
g_return_if_fail (context != NULL);
g_free (context->description);
context->description = g_strdup (description);
}
/**
* g_option_context_get_description:
* @context: a #GOptionContext
*
* Returns the description. See g_option_context_set_description().
*
* Returns: the description
*
* Since: 2.12
*/
const gchar *
g_option_context_get_description (GOptionContext *context)
{
g_return_val_if_fail (context != NULL, NULL);
return context->description;
}
pkg-config-0.29.1/glib/glib/glib-private.c 0000664 0001750 0001750 00000002652 12651243552 015147 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 2011 Red Hat, Inc.
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Colin Walters
*/
#include "config.h"
#include "glib-private.h"
/**
* glib__private__:
* @arg: Do not use this argument
*
* Do not call this function; it is used to share private
* API between glib, gobject, and gio.
*/
GLibPrivateVTable *
glib__private__ (void)
{
static GLibPrivateVTable table = {
g_wakeup_new,
g_wakeup_free,
g_wakeup_get_pollfd,
g_wakeup_signal,
g_wakeup_acknowledge,
g_get_worker_context,
g_check_setuid,
g_main_context_new_with_next_id,
g_dir_open_with_errno,
g_dir_new_from_dirp
};
return &table;
}
pkg-config-0.29.1/glib/glib/gbacktrace.c 0000664 0001750 0001750 00000021656 12651243552 014655 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
/*
* MT safe ; except for g_on_error_stack_trace, but who wants thread safety
* then
*/
#include "config.h"
#include "glibconfig.h"
#include
#include
#include
#include
#ifdef HAVE_SYS_TIME_H
#include
#endif
#ifdef HAVE_SYS_TIMES_H
#include
#endif
#include
#ifdef HAVE_SYS_WAIT_H
#include
#endif
#include
#ifdef HAVE_UNISTD_H
#include
#endif
#ifdef HAVE_SYS_SELECT_H
#include
#endif /* HAVE_SYS_SELECT_H */
#include /* for bzero on BSD systems */
#ifdef G_OS_WIN32
# define STRICT /* Strict typing, please */
# define _WIN32_WINDOWS 0x0401 /* to get IsDebuggerPresent */
# include
# undef STRICT
#endif
#include "gbacktrace.h"
#include "gtypes.h"
#include "gmain.h"
#include "gprintfint.h"
#include "gutils.h"
#ifndef NO_FD_SET
# define SELECT_MASK fd_set
#else
# if defined(_IBMR2)
# define SELECT_MASK void
# else
# define SELECT_MASK int
# endif
#endif
#ifndef G_OS_WIN32
static void stack_trace (char **args);
#endif
/* People want to hit this from their debugger... */
GLIB_AVAILABLE_IN_ALL volatile gboolean glib_on_error_halt;
volatile gboolean glib_on_error_halt = TRUE;
/**
* g_on_error_query:
* @prg_name: the program name, needed by gdb
* for the [S]tack trace option. If @prg_name is %NULL, g_get_prgname()
* is called to get the program name (which will work correctly if
* gdk_init() or gtk_init() has been called)
*
* Prompts the user with
* [E]xit, [H]alt, show [S]tack trace or [P]roceed.
* This function is intended to be used for debugging use only.
* The following example shows how it can be used together with
* the g_log() functions.
*
* |[
* #include <glib.h>
*
* static void
* log_handler (const gchar *log_domain,
* GLogLevelFlags log_level,
* const gchar *message,
* gpointer user_data)
* {
* g_log_default_handler (log_domain, log_level, message, user_data);
*
* g_on_error_query (MY_PROGRAM_NAME);
* }
*
* int
* main (int argc, char *argv[])
* {
* g_log_set_handler (MY_LOG_DOMAIN,
* G_LOG_LEVEL_WARNING |
* G_LOG_LEVEL_ERROR |
* G_LOG_LEVEL_CRITICAL,
* log_handler,
* NULL);
* /* ... */
* ]|
*
* If [E]xit is selected, the application terminates with a call
* to _exit(0).
*
* If [S]tack trace is selected, g_on_error_stack_trace() is called.
* This invokes gdb, which attaches to the current
* process and shows a stack trace. The prompt is then shown again.
*
* If [P]roceed is selected, the function returns.
*
* This function may cause different actions on non-UNIX platforms.
*/
void
g_on_error_query (const gchar *prg_name)
{
#ifndef G_OS_WIN32
static const gchar * const query1 = "[E]xit, [H]alt";
static const gchar * const query2 = ", show [S]tack trace";
static const gchar * const query3 = " or [P]roceed";
gchar buf[16];
if (!prg_name)
prg_name = g_get_prgname ();
retry:
if (prg_name)
_g_fprintf (stdout,
"%s (pid:%u): %s%s%s: ",
prg_name,
(guint) getpid (),
query1,
query2,
query3);
else
_g_fprintf (stdout,
"(process:%u): %s%s: ",
(guint) getpid (),
query1,
query3);
fflush (stdout);
if (isatty(0) && isatty(1))
fgets (buf, 8, stdin);
else
strcpy (buf, "E\n");
if ((buf[0] == 'E' || buf[0] == 'e')
&& buf[1] == '\n')
_exit (0);
else if ((buf[0] == 'P' || buf[0] == 'p')
&& buf[1] == '\n')
return;
else if (prg_name
&& (buf[0] == 'S' || buf[0] == 's')
&& buf[1] == '\n')
{
g_on_error_stack_trace (prg_name);
goto retry;
}
else if ((buf[0] == 'H' || buf[0] == 'h')
&& buf[1] == '\n')
{
while (glib_on_error_halt)
;
glib_on_error_halt = TRUE;
return;
}
else
goto retry;
#else
if (!prg_name)
prg_name = g_get_prgname ();
MessageBox (NULL, "g_on_error_query called, program terminating",
(prg_name && *prg_name) ? prg_name : NULL,
MB_OK|MB_ICONERROR);
_exit(0);
#endif
}
/**
* g_on_error_stack_trace:
* @prg_name: the program name, needed by gdb
* for the [S]tack trace option.
*
* Invokes gdb, which attaches to the current
* process and shows a stack trace. Called by g_on_error_query()
* when the [S]tack trace option is selected. You can get the current
* process's "program name" with g_get_prgname(), assuming that you
* have called gtk_init() or gdk_init().
*
* This function may cause different actions on non-UNIX platforms.
*/
void
g_on_error_stack_trace (const gchar *prg_name)
{
#if defined(G_OS_UNIX) || defined(G_OS_BEOS)
pid_t pid;
gchar buf[16];
gchar *args[4] = { "gdb", NULL, NULL, NULL };
int status;
if (!prg_name)
return;
_g_sprintf (buf, "%u", (guint) getpid ());
args[1] = (gchar*) prg_name;
args[2] = buf;
pid = fork ();
if (pid == 0)
{
stack_trace (args);
_exit (0);
}
else if (pid == (pid_t) -1)
{
perror ("unable to fork gdb");
return;
}
waitpid (pid, &status, 0);
#else
if (IsDebuggerPresent ())
G_BREAKPOINT ();
else
abort ();
#endif
}
#ifndef G_OS_WIN32
static gboolean stack_trace_done = FALSE;
static void
stack_trace_sigchld (int signum)
{
stack_trace_done = TRUE;
}
static void
stack_trace (char **args)
{
pid_t pid;
int in_fd[2];
int out_fd[2];
SELECT_MASK fdset;
SELECT_MASK readset;
struct timeval tv;
int sel, idx, state;
char buffer[256];
char c;
stack_trace_done = FALSE;
signal (SIGCHLD, stack_trace_sigchld);
if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
{
perror ("unable to open pipe");
_exit (0);
}
pid = fork ();
if (pid == 0)
{
close (0); dup (in_fd[0]); /* set the stdin to the in pipe */
close (1); dup (out_fd[1]); /* set the stdout to the out pipe */
close (2); dup (out_fd[1]); /* set the stderr to the out pipe */
execvp (args[0], args); /* exec gdb */
perror ("exec failed");
_exit (0);
}
else if (pid == (pid_t) -1)
{
perror ("unable to fork");
_exit (0);
}
FD_ZERO (&fdset);
FD_SET (out_fd[0], &fdset);
write (in_fd[1], "backtrace\n", 10);
write (in_fd[1], "p x = 0\n", 8);
write (in_fd[1], "quit\n", 5);
idx = 0;
state = 0;
while (1)
{
readset = fdset;
tv.tv_sec = 1;
tv.tv_usec = 0;
sel = select (FD_SETSIZE, &readset, NULL, NULL, &tv);
if (sel == -1)
break;
if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
{
if (read (out_fd[0], &c, 1))
{
switch (state)
{
case 0:
if (c == '#')
{
state = 1;
idx = 0;
buffer[idx++] = c;
}
break;
case 1:
buffer[idx++] = c;
if ((c == '\n') || (c == '\r'))
{
buffer[idx] = 0;
_g_fprintf (stdout, "%s", buffer);
state = 0;
idx = 0;
}
break;
default:
break;
}
}
}
else if (stack_trace_done)
break;
}
close (in_fd[0]);
close (in_fd[1]);
close (out_fd[0]);
close (out_fd[1]);
_exit (0);
}
#endif /* !G_OS_WIN32 */
pkg-config-0.29.1/glib/glib/glib-unix.h 0000664 0001750 0001750 00000010517 12651243552 014464 0000000 0000000 /* glib-unix.h - Unix specific integration
* Copyright (C) 2011 Red Hat, 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; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __G_UNIX_H__
#define __G_UNIX_H__
/* We need to include the UNIX headers needed to use the APIs below,
* but we also take this opportunity to include a wide selection of
* other UNIX headers. If one of the headers below is broken on some
* system, work around it here (or better, fix the system or tell
* people to use a better one).
*/
#include
#include
#include
#include
#include
#include
#ifndef G_OS_UNIX
#error "This header may only be used on UNIX"
#endif
G_BEGIN_DECLS
/**
* G_UNIX_ERROR:
*
* Error domain for API in the "g_unix_" namespace. Note that there is
* no exported enumeration mapping %errno. Instead, all functions
* ensure that %errno is relevant. The code for all #G_UNIX_ERROR is
* always 0, and the error message is always
* generated via g_strerror().
*
* It is expected that most code will not look at %errno from these
* APIs. Important cases where one would want to differentiate between
* errors are already covered by existing cross-platform GLib API,
* such as e.g. #GFile wrapping ENOENT. However, it is
* provided for completeness, at least.
*/
#define G_UNIX_ERROR (g_unix_error_quark())
GLIB_AVAILABLE_IN_2_30
GQuark g_unix_error_quark (void);
GLIB_AVAILABLE_IN_2_30
gboolean g_unix_open_pipe (gint *fds,
gint flags,
GError **error);
GLIB_AVAILABLE_IN_2_30
gboolean g_unix_set_fd_nonblocking (gint fd,
gboolean nonblock,
GError **error);
GLIB_AVAILABLE_IN_2_30
GSource *g_unix_signal_source_new (gint signum);
GLIB_AVAILABLE_IN_2_30
guint g_unix_signal_add_full (gint priority,
gint signum,
GSourceFunc handler,
gpointer user_data,
GDestroyNotify notify);
GLIB_AVAILABLE_IN_2_30
guint g_unix_signal_add (gint signum,
GSourceFunc handler,
gpointer user_data);
/**
* GUnixFDSourceFunc:
* @fd: the fd that triggered the event
* @condition: the IO conditions reported on @fd
* @user_data: user data passed to g_unix_fd_add()
*
* The type of functions to be called when a UNIX fd watch source
* triggers.
*
* Returns: %FALSE if the source should be removed
**/
typedef gboolean (*GUnixFDSourceFunc) (gint fd,
GIOCondition condition,
gpointer user_data);
GLIB_AVAILABLE_IN_2_36
GSource *g_unix_fd_source_new (gint fd,
GIOCondition condition);
GLIB_AVAILABLE_IN_2_36
guint g_unix_fd_add_full (gint priority,
gint fd,
GIOCondition condition,
GUnixFDSourceFunc function,
gpointer user_data,
GDestroyNotify notify);
GLIB_AVAILABLE_IN_2_36
guint g_unix_fd_add (gint fd,
GIOCondition condition,
GUnixFDSourceFunc function,
gpointer user_data);
G_END_DECLS
#endif /* __G_UNIX_H__ */
pkg-config-0.29.1/glib/glib/gurifuncs.h 0000664 0001750 0001750 00000005341 12651243552 014572 0000000 0000000 /* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson
*/
#ifndef __G_URI_FUNCS_H__
#define __G_URI_FUNCS_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
G_BEGIN_DECLS
/**
* G_URI_RESERVED_CHARS_GENERIC_DELIMITERS:
*
* Generic delimiters characters as defined in RFC 3986. Includes ":/?#[]@".
**/
#define G_URI_RESERVED_CHARS_GENERIC_DELIMITERS ":/?#[]@"
/**
* G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS:
*
* Subcomponent delimiter characters as defined in RFC 3986. Includes "!$&'()*+,;=".
**/
#define G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS "!$&'()*+,;="
/**
* G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT:
*
* Allowed characters in path elements. Includes "!$&'()*+,;=:@".
**/
#define G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS ":@"
/**
* G_URI_RESERVED_CHARS_ALLOWED_IN_PATH:
*
* Allowed characters in a path. Includes "!$&'()*+,;=:@/".
**/
#define G_URI_RESERVED_CHARS_ALLOWED_IN_PATH G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT "/"
/**
* G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO:
*
* Allowed characters in userinfo as defined in RFC 3986. Includes "!$&'()*+,;=:".
**/
#define G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS ":"
GLIB_AVAILABLE_IN_ALL
char * g_uri_unescape_string (const char *escaped_string,
const char *illegal_characters);
GLIB_AVAILABLE_IN_ALL
char * g_uri_unescape_segment (const char *escaped_string,
const char *escaped_string_end,
const char *illegal_characters);
GLIB_AVAILABLE_IN_ALL
char * g_uri_parse_scheme (const char *uri);
GLIB_AVAILABLE_IN_ALL
char * g_uri_escape_string (const char *unescaped,
const char *reserved_chars_allowed,
gboolean allow_utf8);
G_END_DECLS
#endif /* __G_URI_FUNCS_H__ */
pkg-config-0.29.1/glib/glib/docs.c 0000664 0001750 0001750 00000165421 12651243552 013516 0000000 0000000 /*
* Copyright © 2011 Red Hat, Inc
*
* This 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 of the licence, 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Matthias Clasen
*/
/* This file collects documentation for macros, typedefs and
* the like, which have no good home in any of the 'real' source
* files.
*/
/* Basic types {{{1 */
/**
* SECTION:types
* @title: Basic Types
* @short_description: standard GLib types, defined for ease-of-use
* and portability
*
* GLib defines a number of commonly used types, which can be divided
* into 4 groups:
* - New types which are not part of standard C (but are defined in
* various C standard library header files) - #gboolean, #gsize,
* #gssize, #goffset, #gintptr, #guintptr.
* - Integer types which are guaranteed to be the same size across
* all platforms - #gint8, #guint8, #gint16, #guint16, #gint32,
* #guint32, #gint64, #guint64.
* - Types which are easier to use than their standard C counterparts -
* #gpointer, #gconstpointer, #guchar, #guint, #gushort, #gulong.
* - Types which correspond exactly to standard C types, but are
* included for completeness - #gchar, #gint, #gshort, #glong,
* #gfloat, #gdouble.
*
* GLib also defines macros for the limits of some of the standard
* integer and floating point types, as well as macros for suitable
* printf() formats for these types.
*/
/**
* gboolean:
*
* A standard boolean type.
* Variables of this type should only contain the value
* %TRUE or %FALSE.
*/
/**
* gpointer:
*
* An untyped pointer.
* #gpointer looks better and is easier to use
* than void*.
*/
/**
* gconstpointer:
*
* An untyped pointer to constant data.
* The data pointed to should not be changed.
*
* This is typically used in function prototypes to indicate
* that the data pointed to will not be altered by the function.
*/
/**
* gchar:
*
* Corresponds to the standard C char type.
*/
/**
* guchar:
*
* Corresponds to the standard C unsigned char type.
*/
/**
* gint:
*
* Corresponds to the standard C int type.
* Values of this type can range from #G_MININT to #G_MAXINT.
*/
/**
* G_MININT:
*
* The minimum value which can be held in a #gint.
*/
/**
* G_MAXINT:
*
* The maximum value which can be held in a #gint.
*/
/**
* guint:
*
* Corresponds to the standard C unsigned int type.
* Values of this type can range from 0 to #G_MAXUINT.
*/
/**
* G_MAXUINT:
*
* The maximum value which can be held in a #guint.
*/
/**
* gshort:
*
* Corresponds to the standard C short type.
* Values of this type can range from #G_MINSHORT to #G_MAXSHORT.
*/
/**
* G_MINSHORT:
*
* The minimum value which can be held in a #gshort.
*/
/**
* G_MAXSHORT:
*
* The maximum value which can be held in a #gshort.
*/
/**
* gushort:
*
* Corresponds to the standard C unsigned short type.
* Values of this type can range from 0 to #G_MAXUSHORT.
*/
/**
* G_MAXUSHORT:
*
* The maximum value which can be held in a #gushort.
*/
/**
* glong:
*
* Corresponds to the standard C long type.
* Values of this type can range from #G_MINLONG to #G_MAXLONG.
*/
/**
* G_MINLONG:
*
* The minimum value which can be held in a #glong.
*/
/**
* G_MAXLONG:
*
* The maximum value which can be held in a #glong.
*/
/**
* gulong:
*
* Corresponds to the standard C unsigned long type.
* Values of this type can range from 0 to #G_MAXULONG.
*/
/**
* G_MAXULONG:
*
* The maximum value which can be held in a #gulong.
*/
/**
* gint8:
*
* A signed integer guaranteed to be 8 bits on all platforms.
* Values of this type can range from #G_MININT8 (= -128) to
* #G_MAXINT8 (= 127).
*/
/**
* G_MININT8:
*
* The minimum value which can be held in a #gint8.
*
* Since: 2.4
*/
/**
* G_MAXINT8:
*
* The maximum value which can be held in a #gint8.
*
* Since: 2.4
*/
/**
* guint8:
*
* An unsigned integer guaranteed to be 8 bits on all platforms.
* Values of this type can range from 0 to #G_MAXUINT8 (= 255).
*/
/**
* G_MAXUINT8:
*
* The maximum value which can be held in a #guint8.
*
* Since: 2.4
*/
/**
* gint16:
*
* A signed integer guaranteed to be 16 bits on all platforms.
* Values of this type can range from #G_MININT16 (= -32,768) to
* #G_MAXINT16 (= 32,767).
*
* To print or scan values of this type, use
* %G_GINT16_MODIFIER and/or %G_GINT16_FORMAT.
*/
/**
* G_MININT16:
*
* The minimum value which can be held in a #gint16.
*
* Since: 2.4
*/
/**
* G_MAXINT16:
*
* The maximum value which can be held in a #gint16.
*
* Since: 2.4
*/
/**
* G_GINT16_MODIFIER:
*
* The platform dependent length modifier for conversion specifiers
* for scanning and printing values of type #gint16 or #guint16. It
* is a string literal, but doesn't include the percent-sign, such
* that you can add precision and length modifiers between percent-sign
* and conversion specifier and append a conversion specifier.
*
* The following example prints "0x7b";
* |[
* gint16 value = 123;
* g_print ("%#" G_GINT16_MODIFIER "x", value);
* ]|
*
* Since: 2.4
*/
/**
* G_GINT16_FORMAT:
*
* This is the platform dependent conversion specifier for scanning and
* printing values of type #gint16. It is a string literal, but doesn't
* include the percent-sign, such that you can add precision and length
* modifiers between percent-sign and conversion specifier.
*
* |[
* gint16 in;
* gint32 out;
* sscanf ("42", "%" G_GINT16_FORMAT, &in)
* out = in * 1000;
* g_print ("%" G_GINT32_FORMAT, out);
* ]|
*/
/**
* guint16:
*
* An unsigned integer guaranteed to be 16 bits on all platforms.
* Values of this type can range from 0 to #G_MAXUINT16 (= 65,535).
*
* To print or scan values of this type, use
* %G_GINT16_MODIFIER and/or %G_GUINT16_FORMAT.
*/
/**
* G_MAXUINT16:
*
* The maximum value which can be held in a #guint16.
*
* Since: 2.4
*/
/**
* G_GUINT16_FORMAT:
*
* This is the platform dependent conversion specifier for scanning
* and printing values of type #guint16. See also #G_GINT16_FORMAT
*/
/**
* gint32:
*
* A signed integer guaranteed to be 32 bits on all platforms.
* Values of this type can range from #G_MININT32 (= -2,147,483,648)
* to #G_MAXINT32 (= 2,147,483,647).
*
* To print or scan values of this type, use
* %G_GINT32_MODIFIER and/or %G_GINT32_FORMAT.
*/
/**
* G_MININT32:
*
* The minimum value which can be held in a #gint32.
*
* Since: 2.4
*/
/**
* G_MAXINT32:
*
* The maximum value which can be held in a #gint32.
*
* Since: 2.4
*/
/**
* G_GINT32_MODIFIER:
*
* The platform dependent length modifier for conversion specifiers
* for scanning and printing values of type #gint32 or #guint32. It
* is a string literal. See also #G_GINT16_MODIFIER.
*
* Since: 2.4
*/
/**
* G_GINT32_FORMAT:
*
* This is the platform dependent conversion specifier for scanning
* and printing values of type #gint32. See also #G_GINT16_FORMAT.
*/
/**
* guint32:
*
* An unsigned integer guaranteed to be 32 bits on all platforms.
* Values of this type can range from 0 to #G_MAXUINT32 (= 4,294,967,295).
*
* To print or scan values of this type, use
* %G_GINT32_MODIFIER and/or %G_GUINT32_FORMAT.
*/
/**
* G_MAXUINT32:
*
* The maximum value which can be held in a #guint32.
*
* Since: 2.4
*/
/**
* G_GUINT32_FORMAT:
*
* This is the platform dependent conversion specifier for scanning
* and printing values of type #guint32. See also #G_GINT16_FORMAT.
*/
/**
* gint64:
*
* A signed integer guaranteed to be 64 bits on all platforms.
* Values of this type can range from #G_MININT64
* (= -9,223,372,036,854,775,808) to #G_MAXINT64
* (= 9,223,372,036,854,775,807).
*
* To print or scan values of this type, use
* %G_GINT64_MODIFIER and/or %G_GINT64_FORMAT.
*/
/**
* G_MININT64:
*
* The minimum value which can be held in a #gint64.
*/
/**
* G_MAXINT64:
*
* The maximum value which can be held in a #gint64.
*/
/**
* G_GINT64_MODIFIER:
*
* The platform dependent length modifier for conversion specifiers
* for scanning and printing values of type #gint64 or #guint64.
* It is a string literal.
*
*
* Some platforms do not support printing 64 bit integers, even
* though the types are supported. On such platforms #G_GINT64_MODIFIER
* is not defined.
*
*
* Since: 2.4
*/
/**
* G_GINT64_FORMAT:
*
* This is the platform dependent conversion specifier for scanning
* and printing values of type #gint64. See also #G_GINT16_FORMAT.
*
*
* Some platforms do not support scanning and printing 64 bit integers,
* even though the types are supported. On such platforms #G_GINT64_FORMAT
* is not defined. Note that scanf() may not support 64 bit integers, even
* if #G_GINT64_FORMAT is defined. Due to its weak error handling, scanf()
* is not recommended for parsing anyway; consider using g_ascii_strtoull()
* instead.
*
*/
/**
* guint64:
*
* An unsigned integer guaranteed to be 64 bits on all platforms.
* Values of this type can range from 0 to #G_MAXUINT64
* (= 18,446,744,073,709,551,615).
*
* To print or scan values of this type, use
* %G_GINT64_MODIFIER and/or %G_GUINT64_FORMAT.
*/
/**
* G_MAXUINT64:
*
* The maximum value which can be held in a #guint64.
*/
/**
* G_GUINT64_FORMAT:
*
* This is the platform dependent conversion specifier for scanning
* and printing values of type #guint64. See also #G_GINT16_FORMAT.
*
*
* Some platforms do not support scanning and printing 64 bit integers,
* even though the types are supported. On such platforms #G_GUINT64_FORMAT
* is not defined. Note that scanf() may not support 64 bit integers, even
* if #G_GINT64_FORMAT is defined. Due to its weak error handling, scanf()
* is not recommended for parsing anyway; consider using g_ascii_strtoull()
* instead.
*
*/
/**
* G_GINT64_CONSTANT:
* @val: a literal integer value, e.g. 0x1d636b02300a7aa7
*
* This macro is used to insert 64-bit integer literals
* into the source code.
*/
/**
* G_GUINT64_CONSTANT:
* @val: a literal integer value, e.g. 0x1d636b02300a7aa7U
*
* This macro is used to insert 64-bit unsigned integer
* literals into the source code.
*
* Since: 2.10
*/
/**
* gfloat:
*
* Corresponds to the standard C float type.
* Values of this type can range from -#G_MAXFLOAT to #G_MAXFLOAT.
*/
/**
* G_MINFLOAT:
*
* The minimum positive value which can be held in a #gfloat.
*
* If you are interested in the smallest value which can be held
* in a #gfloat, use -G_MAXFLOAT.
*/
/**
* G_MAXFLOAT:
*
* The maximum value which can be held in a #gfloat.
*/
/**
* gdouble:
*
* Corresponds to the standard C double type.
* Values of this type can range from -#G_MAXDOUBLE to #G_MAXDOUBLE.
*/
/**
* G_MINDOUBLE:
*
* The minimum positive value which can be held in a #gdouble.
*
* If you are interested in the smallest value which can be held
* in a #gdouble, use -G_MAXDOUBLE.
*/
/**
* G_MAXDOUBLE:
*
* The maximum value which can be held in a #gdouble.
*/
/**
* gsize:
*
* An unsigned integer type of the result of the sizeof operator,
* corresponding to the size_t type defined in C99.
* This type is wide enough to hold the numeric value of a pointer,
* so it is usually 32bit wide on a 32bit platform and 64bit wide
* on a 64bit platform. Values of this type can range from 0 to
* #G_MAXSIZE.
*
* To print or scan values of this type, use
* %G_GSIZE_MODIFIER and/or %G_GSIZE_FORMAT.
*/
/**
* G_MAXSIZE:
*
* The maximum value which can be held in a #gsize.
*
* Since: 2.4
*/
/**
* G_GSIZE_MODIFIER:
*
* The platform dependent length modifier for conversion specifiers
* for scanning and printing values of type #gsize or #gssize. It
* is a string literal.
*
* Since: 2.6
*/
/**
* G_GSIZE_FORMAT:
*
* This is the platform dependent conversion specifier for scanning
* and printing values of type #gsize. See also #G_GINT16_FORMAT.
*
* Since: 2.6
*/
/**
* gssize:
*
* A signed variant of #gsize, corresponding to the
* ssize_t defined on most platforms.
* Values of this type can range from #G_MINSSIZE
* to #G_MAXSSIZE.
*
* To print or scan values of this type, use
* %G_GSIZE_MODIFIER and/or %G_GSSIZE_FORMAT.
*/
/**
* G_MINSSIZE:
*
* The minimum value which can be held in a #gssize.
*
* Since: 2.14
*/
/**
* G_MAXSSIZE:
*
* The maximum value which can be held in a #gssize.
*
* Since: 2.14
*/
/**
* G_GSSIZE_FORMAT:
*
* This is the platform dependent conversion specifier for scanning
* and printing values of type #gssize. See also #G_GINT16_FORMAT.
*
* Since: 2.6
*/
/**
* goffset:
*
* A signed integer type that is used for file offsets,
* corresponding to the C99 type off64_t.
* Values of this type can range from #G_MINOFFSET to
* #G_MAXOFFSET.
*
* To print or scan values of this type, use
* %G_GOFFSET_MODIFIER and/or %G_GOFFSET_FORMAT.
*
* Since: 2.14
*/
/**
* G_MINOFFSET:
*
* The minimum value which can be held in a #goffset.
*/
/**
* G_MAXOFFSET:
*
* The maximum value which can be held in a #goffset.
*/
/**
* G_GOFFSET_MODIFIER:
*
* The platform dependent length modifier for conversion specifiers
* for scanning and printing values of type #goffset. It is a string
* literal. See also #G_GINT64_MODIFIER.
*
* Since: 2.20
*/
/**
* G_GOFFSET_FORMAT:
*
* This is the platform dependent conversion specifier for scanning
* and printing values of type #goffset. See also #G_GINT64_FORMAT.
*
* Since: 2.20
*/
/**
* G_GOFFSET_CONSTANT:
* @val: a literal integer value, e.g. 0x1d636b02300a7aa7
*
* This macro is used to insert #goffset 64-bit integer literals
* into the source code.
*
* See also #G_GINT64_CONSTANT.
*
* Since: 2.20
*/
/**
* gintptr:
*
* Corresponds to the C99 type intptr_t,
* a signed integer type that can hold any pointer.
*
* To print or scan values of this type, use
* %G_GINTPTR_MODIFIER and/or %G_GINTPTR_FORMAT.
*
* Since: 2.18
*/
/**
* G_GINTPTR_MODIFIER:
*
* The platform dependent length modifier for conversion specifiers
* for scanning and printing values of type #gintptr or #guintptr.
* It is a string literal.
*
* Since: 2.22
*/
/**
* G_GINTPTR_FORMAT:
*
* This is the platform dependent conversion specifier for scanning
* and printing values of type #gintptr.
*
* Since: 2.22
*/
/**
* guintptr:
*
* Corresponds to the C99 type uintptr_t,
* an unsigned integer type that can hold any pointer.
*
* To print or scan values of this type, use
* %G_GINTPTR_MODIFIER and/or %G_GUINTPTR_FORMAT.
*
* Since: 2.18
*/
/**
* G_GUINTPTR_FORMAT:
*
* This is the platform dependent conversion specifier
* for scanning and printing values of type #guintptr.
*
* Since: 2.22
*/
/* Type conversion {{{1 */
/**
* SECTION:type_conversion
* @title: Type Conversion Macros
* @short_description: portably storing integers in pointer variables
*
* Many times GLib, GTK+, and other libraries allow you to pass "user
* data" to a callback, in the form of a void pointer. From time to time
* you want to pass an integer instead of a pointer. You could allocate
* an integer, with something like:
* |[
* int *ip = g_new (int, 1);
* *ip = 42;
* ]|
* But this is inconvenient, and it's annoying to have to free the
* memory at some later time.
*
* Pointers are always at least 32 bits in size (on all platforms GLib
* intends to support). Thus you can store at least 32-bit integer values
* in a pointer value. Naively, you might try this, but it's incorrect:
* |[
* gpointer p;
* int i;
* p = (void*) 42;
* i = (int) p;
* ]|
* Again, that example was not correct, don't copy it.
* The problem is that on some systems you need to do this:
* |[
* gpointer p;
* int i;
* p = (void*) (long) 42;
* i = (int) (long) p;
* ]|
* The GLib macros GPOINTER_TO_INT(), GINT_TO_POINTER(), etc. take care
* to do the right thing on the every platform.
*
* You may not store pointers in integers. This is not
* portable in any way, shape or form. These macros only
* allow storing integers in pointers, and only preserve 32 bits of the
* integer; values outside the range of a 32-bit integer will be mangled.
*
*/
/**
* GINT_TO_POINTER:
* @i: integer to stuff into a pointer
*
* Stuffs an integer into a pointer type.
*
* Remember, you may not store pointers in integers. This is not portable
* in any way, shape or form. These macros only allow
* storing integers in pointers, and only preserve 32 bits of the
* integer; values outside the range of a 32-bit integer will be mangled.
*/
/**
* GPOINTER_TO_INT:
* @p: pointer containing an integer
*
* Extracts an integer from a pointer. The integer must have
* been stored in the pointer with GINT_TO_POINTER().
*
* Remember, you may not store pointers in integers. This is not portable
* in any way, shape or form. These macros only allow
* storing integers in pointers, and only preserve 32 bits of the
* integer; values outside the range of a 32-bit integer will be mangled.
*/
/**
* GUINT_TO_POINTER:
* @u: unsigned integer to stuff into the pointer
*
* Stuffs an unsigned integer into a pointer type.
*/
/**
* GPOINTER_TO_UINT:
* @p: pointer to extract an unsigned integer from
*
* Extracts an unsigned integer from a pointer. The integer must have
* been stored in the pointer with GUINT_TO_POINTER().
*/
/**
* GSIZE_TO_POINTER:
* @s: #gsize to stuff into the pointer
*
* Stuffs a #gsize into a pointer type.
*/
/**
* GPOINTER_TO_SIZE:
* @p: pointer to extract a #gsize from
*
* Extracts a #gsize from a pointer. The #gsize must have
* been stored in the pointer with GSIZE_TO_POINTER().
*/
/* Byte order {{{1 */
/**
* SECTION:byte_order
* @title: Byte Order Macros
* @short_description: a portable way to convert between different byte orders
*
* These macros provide a portable way to determine the host byte order
* and to convert values between different byte orders.
*
* The byte order is the order in which bytes are stored to create larger
* data types such as the #gint and #glong values.
* The host byte order is the byte order used on the current machine.
*
* Some processors store the most significant bytes (i.e. the bytes that
* hold the largest part of the value) first. These are known as big-endian
* processors. Other processors (notably the x86 family) store the most
* significant byte last. These are known as little-endian processors.
*
* Finally, to complicate matters, some other processors store the bytes in
* a rather curious order known as PDP-endian. For a 4-byte word, the 3rd
* most significant byte is stored first, then the 4th, then the 1st and
* finally the 2nd.
*
* Obviously there is a problem when these different processors communicate
* with each other, for example over networks or by using binary file formats.
* This is where these macros come in. They are typically used to convert
* values into a byte order which has been agreed on for use when
* communicating between different processors. The Internet uses what is
* known as 'network byte order' as the standard byte order (which is in
* fact the big-endian byte order).
*
* Note that the byte order conversion macros may evaluate their arguments
* multiple times, thus you should not use them with arguments which have
* side-effects.
*/
/**
* G_BYTE_ORDER:
*
* The host byte order.
* This can be either #G_LITTLE_ENDIAN or #G_BIG_ENDIAN (support for
* #G_PDP_ENDIAN may be added in future.)
*/
/**
* G_LITTLE_ENDIAN:
*
* Specifies one of the possible types of byte order.
* See #G_BYTE_ORDER.
*/
/**
* G_BIG_ENDIAN:
*
* Specifies one of the possible types of byte order.
* See #G_BYTE_ORDER.
*/
/**
* G_PDP_ENDIAN:
*
* Specifies one of the possible types of byte order
* (currently unused). See #G_BYTE_ORDER.
*/
/**
* g_htonl:
* @val: a 32-bit integer value in host byte order
*
* Converts a 32-bit integer value from host to network byte order.
*
* Returns: @val converted to network byte order
*/
/**
* g_htons:
* @val: a 16-bit integer value in host byte order
*
* Converts a 16-bit integer value from host to network byte order.
*
* Returns: @val converted to network byte order
*/
/**
* g_ntohl:
* @val: a 32-bit integer value in network byte order
*
* Converts a 32-bit integer value from network to host byte order.
*
* Returns: @val converted to host byte order.
*/
/**
* g_ntohs:
* @val: a 16-bit integer value in network byte order
*
* Converts a 16-bit integer value from network to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GINT_FROM_BE:
* @val: a #gint value in big-endian byte order
*
* Converts a #gint value from big-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GINT_FROM_LE:
* @val: a #gint value in little-endian byte order
*
* Converts a #gint value from little-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GINT_TO_BE:
* @val: a #gint value in host byte order
*
* Converts a #gint value from host byte order to big-endian.
*
* Returns: @val converted to big-endian byte order
*/
/**
* GINT_TO_LE:
* @val: a #gint value in host byte order
*
* Converts a #gint value from host byte order to little-endian.
*
* Returns: @val converted to little-endian byte order
*/
/**
* GUINT_FROM_BE:
* @val: a #guint value in big-endian byte order
*
* Converts a #guint value from big-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GUINT_FROM_LE:
* @val: a #guint value in little-endian byte order
*
* Converts a #guint value from little-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GUINT_TO_BE:
* @val: a #guint value in host byte order
*
* Converts a #guint value from host byte order to big-endian.
*
* Returns: @val converted to big-endian byte order
*/
/**
* GUINT_TO_LE:
* @val: a #guint value in host byte order
*
* Converts a #guint value from host byte order to little-endian.
*
* Returns: @val converted to little-endian byte order.
*/
/**
* GLONG_FROM_BE:
* @val: a #glong value in big-endian byte order
*
* Converts a #glong value from big-endian to the host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GLONG_FROM_LE:
* @val: a #glong value in little-endian byte order
*
* Converts a #glong value from little-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GLONG_TO_BE:
* @val: a #glong value in host byte order
*
* Converts a #glong value from host byte order to big-endian.
*
* Returns: @val converted to big-endian byte order
*/
/**
* GLONG_TO_LE:
* @val: a #glong value in host byte order
*
* Converts a #glong value from host byte order to little-endian.
*
* Returns: @val converted to little-endian
*/
/**
* GULONG_FROM_BE:
* @val: a #gulong value in big-endian byte order
*
* Converts a #gulong value from big-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GULONG_FROM_LE:
* @val: a #gulong value in little-endian byte order
*
* Converts a #gulong value from little-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GULONG_TO_BE:
* @val: a #gulong value in host byte order
*
* Converts a #gulong value from host byte order to big-endian.
*
* Returns: @val converted to big-endian
*/
/**
* GULONG_TO_LE:
* @val: a #gulong value in host byte order
*
* Converts a #gulong value from host byte order to little-endian.
*
* Returns: @val converted to little-endian
*/
/**
* GSIZE_FROM_BE:
* @val: a #gsize value in big-endian byte order
*
* Converts a #gsize value from big-endian to the host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GSIZE_FROM_LE:
* @val: a #gsize value in little-endian byte order
*
* Converts a #gsize value from little-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GSIZE_TO_BE:
* @val: a #gsize value in host byte order
*
* Converts a #gsize value from host byte order to big-endian.
*
* Returns: @val converted to big-endian byte order
*/
/**
* GSIZE_TO_LE:
* @val: a #gsize value in host byte order
*
* Converts a #gsize value from host byte order to little-endian.
*
* Returns: @val converted to little-endian
*/
/**
* GSSIZE_FROM_BE:
* @val: a #gssize value in big-endian byte order
*
* Converts a #gssize value from big-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GSSIZE_FROM_LE:
* @val: a #gssize value in little-endian byte order
*
* Converts a #gssize value from little-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GSSIZE_TO_BE:
* @val: a #gssize value in host byte order
*
* Converts a #gssize value from host byte order to big-endian.
*
* Returns: @val converted to big-endian
*/
/**
* GSSIZE_TO_LE:
* @val: a #gssize value in host byte order
*
* Converts a #gssize value from host byte order to little-endian.
*
* Returns: @val converted to little-endian
*/
/**
* GINT16_FROM_BE:
* @val: a #gint16 value in big-endian byte order
*
* Converts a #gint16 value from big-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GINT16_FROM_LE:
* @val: a #gint16 value in little-endian byte order
*
* Converts a #gint16 value from little-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GINT16_TO_BE:
* @val: a #gint16 value in host byte order
*
* Converts a #gint16 value from host byte order to big-endian.
*
* Returns: @val converted to big-endian
*/
/**
* GINT16_TO_LE:
* @val: a #gint16 value in host byte order
*
* Converts a #gint16 value from host byte order to little-endian.
*
* Returns: @val converted to little-endian
*/
/**
* GUINT16_FROM_BE:
* @val: a #guint16 value in big-endian byte order
*
* Converts a #guint16 value from big-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GUINT16_FROM_LE:
* @val: a #guint16 value in little-endian byte order
*
* Converts a #guint16 value from little-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GUINT16_TO_BE:
* @val: a #guint16 value in host byte order
*
* Converts a #guint16 value from host byte order to big-endian.
*
* Returns: @val converted to big-endian
*/
/**
* GUINT16_TO_LE:
* @val: a #guint16 value in host byte order
*
* Converts a #guint16 value from host byte order to little-endian.
*
* Returns: @val converted to little-endian
*/
/**
* GINT32_FROM_BE:
* @val: a #gint32 value in big-endian byte order
*
* Converts a #gint32 value from big-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GINT32_FROM_LE:
* @val: a #gint32 value in little-endian byte order
*
* Converts a #gint32 value from little-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GINT32_TO_BE:
* @val: a #gint32 value in host byte order
*
* Converts a #gint32 value from host byte order to big-endian.
*
* Returns: @val converted to big-endian
*/
/**
* GINT32_TO_LE:
* @val: a #gint32 value in host byte order
*
* Converts a #gint32 value from host byte order to little-endian.
*
* Returns: @val converted to little-endian
*/
/**
* GUINT32_FROM_BE:
* @val: a #guint32 value in big-endian byte order
*
* Converts a #guint32 value from big-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GUINT32_FROM_LE:
* @val: a #guint32 value in little-endian byte order
*
* Converts a #guint32 value from little-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GUINT32_TO_BE:
* @val: a #guint32 value in host byte order
*
* Converts a #guint32 value from host byte order to big-endian.
*
* Returns: @val converted to big-endian
*/
/**
* GUINT32_TO_LE:
* @val: a #guint32 value in host byte order
*
* Converts a #guint32 value from host byte order to little-endian.
*
* Returns: @val converted to little-endian
*/
/**
* GINT64_FROM_BE:
* @val: a #gint64 value in big-endian byte order
*
* Converts a #gint64 value from big-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GINT64_FROM_LE:
* @val: a #gint64 value in little-endian byte order
*
* Converts a #gint64 value from little-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GINT64_TO_BE:
* @val: a #gint64 value in host byte order
*
* Converts a #gint64 value from host byte order to big-endian.
*
* Returns: @val converted to big-endian
*/
/**
* GINT64_TO_LE:
* @val: a #gint64 value in host byte order
*
* Converts a #gint64 value from host byte order to little-endian.
*
* Returns: @val converted to little-endian
*/
/**
* GUINT64_FROM_BE:
* @val: a #guint64 value in big-endian byte order
*
* Converts a #guint64 value from big-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GUINT64_FROM_LE:
* @val: a #guint64 value in little-endian byte order
*
* Converts a #guint64 value from little-endian to host byte order.
*
* Returns: @val converted to host byte order
*/
/**
* GUINT64_TO_BE:
* @val: a #guint64 value in host byte order
*
* Converts a #guint64 value from host byte order to big-endian.
*
* Returns: @val converted to big-endian
*/
/**
* GUINT64_TO_LE:
* @val: a #guint64 value in host byte order
*
* Converts a #guint64 value from host byte order to little-endian.
*
* Returns: @val converted to little-endian
*/
/**
* GUINT16_SWAP_BE_PDP:
* @val: a #guint16 value in big-endian or pdp-endian byte order
*
* Converts a #guint16 value between big-endian and pdp-endian byte order.
* The conversion is symmetric so it can be used both ways.
*
* Returns: @val converted to the opposite byte order
*/
/**
* GUINT16_SWAP_LE_BE:
* @val: a #guint16 value in little-endian or big-endian byte order
*
* Converts a #guint16 value between little-endian and big-endian byte order.
* The conversion is symmetric so it can be used both ways.
*
* Returns: @val converted to the opposite byte order
*/
/**
* GUINT16_SWAP_LE_PDP:
* @val: a #guint16 value in little-endian or pdp-endian byte order
*
* Converts a #guint16 value between little-endian and pdp-endian byte order.
* The conversion is symmetric so it can be used both ways.
*
* Returns: @val converted to the opposite byte order
*/
/**
* GUINT32_SWAP_BE_PDP:
* @val: a #guint32 value in big-endian or pdp-endian byte order
*
* Converts a #guint32 value between big-endian and pdp-endian byte order.
* The conversion is symmetric so it can be used both ways.
*
* Returns: @val converted to the opposite byte order
*/
/**
* GUINT32_SWAP_LE_BE:
* @val: a #guint32 value in little-endian or big-endian byte order
*
* Converts a #guint32 value between little-endian and big-endian byte order.
* The conversion is symmetric so it can be used both ways.
*
* Returns: @val converted to the opposite byte order
*/
/**
* GUINT32_SWAP_LE_PDP:
* @val: a #guint32 value in little-endian or pdp-endian byte order
*
* Converts a #guint32 value between little-endian and pdp-endian byte order.
* The conversion is symmetric so it can be used both ways.
*
* Returns: @val converted to the opposite byte order
*/
/**
* GUINT64_SWAP_LE_BE:
* @val: a #guint64 value in little-endian or big-endian byte order
*
* Converts a #guint64 value between little-endian and big-endian byte order.
* The conversion is symmetric so it can be used both ways.
*
* Returns: @val converted to the opposite byte order
*/
/* Numerical Definitions {{{1 */
/**
* SECTION:numerical
* @title: Numerical Definitions
* @short_description: mathematical constants, and floating point decomposition
*
* GLib offers mathematical constants such as #G_PI for the value of pi;
* many platforms have these in the C library, but some don't, the GLib
* versions always exist.
*
* The #GFloatIEEE754 and #GDoubleIEEE754 unions are used to access the
* sign, mantissa and exponent of IEEE floats and doubles. These unions are
* defined as appropriate for a given platform. IEEE floats and doubles are
* supported (used for storage) by at least Intel, PPC and Sparc. See
* IEEE 754-2008
* for more information about IEEE number formats.
*/
/**
* G_IEEE754_FLOAT_BIAS:
*
* The bias by which exponents in single-precision floats are offset.
*/
/**
* G_IEEE754_DOUBLE_BIAS:
*
* The bias by which exponents in double-precision floats are offset.
*/
/**
* GFloatIEEE754:
* @v_float: the double value
*
* The #GFloatIEEE754 and #GDoubleIEEE754 unions are used to access the sign,
* mantissa and exponent of IEEE floats and doubles. These unions are defined
* as appropriate for a given platform. IEEE floats and doubles are supported
* (used for storage) by at least Intel, PPC and Sparc.
*/
/**
* GDoubleIEEE754:
* @v_double: the double value
*
* The #GFloatIEEE754 and #GDoubleIEEE754 unions are used to access the sign,
* mantissa and exponent of IEEE floats and doubles. These unions are defined
* as appropriate for a given platform. IEEE floats and doubles are supported
* (used for storage) by at least Intel, PPC and Sparc.
*/
/**
* G_E:
*
* The base of natural logarithms.
*/
/**
* G_LN2:
*
* The natural logarithm of 2.
*/
/**
* G_LN10:
*
* The natural logarithm of 10.
*/
/**
* G_PI:
*
* The value of pi (ratio of circle's circumference to its diameter).
*/
/**
* G_PI_2:
*
* Pi divided by 2.
*/
/**
* G_PI_4:
*
* Pi divided by 4.
*/
/**
* G_SQRT2:
*
* The square root of two.
*/
/**
* G_LOG_2_BASE_10:
*
* Multiplying the base 2 exponent by this number yields the base 10 exponent.
*/
/* Macros {{{1 */
/**
* SECTION:macros
* @title: Standard Macros
* @short_description: commonly-used macros
*
* These macros provide a few commonly-used features.
*/
/**
* G_OS_WIN32:
*
* This macro is defined only on Windows. So you can bracket
* Windows-specific code in "#ifdef G_OS_WIN32".
*/
/**
* G_OS_BEOS:
*
* This macro is defined only on BeOS. So you can bracket
* BeOS-specific code in "#ifdef G_OS_BEOS".
*/
/**
* G_OS_UNIX:
*
* This macro is defined only on UNIX. So you can bracket
* UNIX-specific code in "#ifdef G_OS_UNIX".
*/
/**
* G_DIR_SEPARATOR:
*
* The directory separator character.
* This is '/' on UNIX machines and '\' under Windows.
*/
/**
* G_DIR_SEPARATOR_S:
*
* The directory separator as a string.
* This is "/" on UNIX machines and "\" under Windows.
*/
/**
* G_IS_DIR_SEPARATOR:
* @c: a character
*
* Checks whether a character is a directory
* separator. It returns %TRUE for '/' on UNIX
* machines and for '\' or '/' under Windows.
*
* Since: 2.6
*/
/**
* G_SEARCHPATH_SEPARATOR:
*
* The search path separator character.
* This is ':' on UNIX machines and ';' under Windows.
*/
/**
* G_SEARCHPATH_SEPARATOR_S:
*
* The search path separator as a string.
* This is ":" on UNIX machines and ";" under Windows.
*/
/**
* TRUE:
*
* Defines the %TRUE value for the #gboolean type.
*/
/**
* FALSE:
*
* Defines the %FALSE value for the #gboolean type.
*/
/**
* NULL:
*
* Defines the standard %NULL pointer.
*/
/**
* MIN:
* @a: a numeric value
* @b: a numeric value
*
* Calculates the minimum of @a and @b.
*
* Returns: the minimum of @a and @b.
*/
/**
* MAX:
* @a: a numeric value
* @b: a numeric value
*
* Calculates the maximum of @a and @b.
*
* Returns: the maximum of @a and @b.
*/
/**
* ABS:
* @a: a numeric value
*
* Calculates the absolute value of @a.
* The absolute value is simply the number with any negative sign taken away.
*
* For example,
* - ABS(-10) is 10.
* - ABS(10) is also 10.
*
* Returns: the absolute value of @a.
*/
/**
* CLAMP:
* @x: the value to clamp
* @low: the minimum value allowed
* @high: the maximum value allowed
*
* Ensures that @x is between the limits set by @low and @high. If @low is
* greater than @high the result is undefined.
*
* For example,
* - CLAMP(5, 10, 15) is 10.
* - CLAMP(15, 5, 10) is 10.
* - CLAMP(20, 15, 25) is 20.
*
* Returns: the value of @x clamped to the range between @low and @high
*/
/**
* G_STRUCT_MEMBER:
* @member_type: the type of the struct field
* @struct_p: a pointer to a struct
* @struct_offset: the offset of the field from the start of the struct,
* in bytes
*
* Returns a member of a structure at a given offset, using the given type.
*
* Returns: the struct member
*/
/**
* G_STRUCT_MEMBER_P:
* @struct_p: a pointer to a struct
* @struct_offset: the offset from the start of the struct, in bytes
*
* Returns an untyped pointer to a given offset of a struct.
*
* Returns: an untyped pointer to @struct_p plus @struct_offset bytes
*/
/**
* G_STRUCT_OFFSET:
* @struct_type: a structure type, e.g. GtkWidget
* @member: a field in the structure, e.g. window
*
* Returns the offset, in bytes, of a member of a struct.
*
* Returns: the offset of @member from the start of @struct_type
*/
/**
* G_CONST_RETURN:
*
* If G_DISABLE_CONST_RETURNS is defined, this macro expands
* to nothing. By default, the macro expands to const.
* The macro should be used in place of const for
* functions that return a value that should not be modified. The
* purpose of this macro is to allow us to turn on const
* for returned constant strings by default, while allowing programmers
* who find that annoying to turn it off. This macro should only be used
* for return values and for out parameters, it doesn't
* make sense for in parameters.
*
* Deprecated: 2.30: API providers should replace all existing uses with
* const and API consumers should adjust their code
* accordingly
*/
/**
* G_N_ELEMENTS:
* @arr: the array
*
* Determines the number of elements in an array. The array must be
* declared so the compiler knows its size at compile-time; this
* macro will not work on an array allocated on the heap, only static
* arrays or arrays on the stack.
*/
/* Miscellaneous Macros {{{1 */
/**
* SECTION:macros_misc
* @title: Miscellaneous Macros
* @short_description: specialized macros which are not used often
*
* These macros provide more specialized features which are not
* needed so often by application programmers.
*/
/**
* G_INLINE_FUNC:
*
* This macro is used to export function prototypes so they can be linked
* with an external version when no inlining is performed. The file which
* implements the functions should define G_IMPLEMENTS_INLINES
* before including the headers which contain %G_INLINE_FUNC declarations.
* Since inlining is very compiler-dependent using these macros correctly
* is very difficult. Their use is strongly discouraged.
*
* This macro is often mistaken for a replacement for the inline keyword;
* inline is already declared in a portable manner in the GLib headers
* and can be used normally.
*/
/**
* G_STMT_START:
*
* Used within multi-statement macros so that they can be used in places
* where only one statement is expected by the compiler.
*/
/**
* G_STMT_END:
*
* Used within multi-statement macros so that they can be used in places
* where only one statement is expected by the compiler.
*/
/**
* G_BEGIN_DECLS:
*
* Used (along with #G_END_DECLS) to bracket header files. If the
* compiler in use is a C++ compiler, adds extern "C"
* around the header.
*/
/**
* G_END_DECLS:
*
* Used (along with #G_BEGIN_DECLS) to bracket header files. If the
* compiler in use is a C++ compiler, adds extern "C"
* around the header.
*/
/**
* G_VA_COPY:
* @ap1: the va_list variable to place a copy of @ap2 in
* @ap2: a va_list
*
* Portable way to copy va_list variables.
*
* In order to use this function, you must include
* string.h yourself, because this macro may
* use memmove() and GLib does not include string.h
* for you.
*/
/**
* G_STRINGIFY:
* @macro_or_string: a macro or a string
*
* Accepts a macro or a string and converts it into a string after
* preprocessor argument expansion. For example, the following code:
*
* |[
* #define AGE 27
* const gchar *greeting = G_STRINGIFY (AGE) " today!";
* ]|
*
* is transformed by the preprocessor into (code equivalent to):
*
* |[
* const gchar *greeting = "27 today!";
* ]|
*/
/**
* G_PASTE:
* @identifier1: an identifier
* @identifier2: an identifier
*
* Yields a new preprocessor pasted identifier
* identifier1identifier2
from its expanded
* arguments @identifier1 and @identifier2. For example,
* the following code:
* |[
* #define GET(traveller,method) G_PASTE(traveller_get_, method) (traveller)
* const gchar *name = GET (traveller, name);
* const gchar *quest = GET (traveller, quest);
* GdkColor *favourite = GET (traveller, favourite_colour);
* ]|
*
* is transformed by the preprocessor into:
* |[
* const gchar *name = traveller_get_name (traveller);
* const gchar *quest = traveller_get_quest (traveller);
* GdkColor *favourite = traveller_get_favourite_colour (traveller);
* ]|
*
* Since: 2.20
*/
/**
* G_STATIC_ASSERT:
* @expr: a constant expression
*
* The G_STATIC_ASSERT macro lets the programmer check
* a condition at compile time, the condition needs to
* be compile time computable. The macro can be used in
* any place where a typedef is valid.
*
*
* A typedef is generally allowed in
* exactly the same places that a variable declaration is
* allowed. For this reason, you should not use
* G_STATIC_ASSERT in the middle of
* blocks of code.
*
*
* The macro should only be used once per source code line.
*
* Since: 2.20
*/
/**
* G_STATIC_ASSERT_EXPR:
* @expr: a constant expression
*
* The G_STATIC_ASSERT_EXPR macro lets the programmer check
* a condition at compile time. The condition needs to be
* compile time computable.
*
* Unlike G_STATIC_ASSERT, this macro
* evaluates to an expression and, as such, can be used in
* the middle of other expressions. Its value should be
* ignored. This can be accomplished by placing it as
* the first argument of a comma expression.
*
* |[
* #define ADD_ONE_TO_INT(x) \
* (G_STATIC_ASSERT_EXPR(sizeof (x) == sizeof (int)), ((x) + 1))
* ]|
*
* Since: 2.30
*/
/**
* G_GNUC_EXTENSION:
*
* Expands to __extension__ when gcc
* is used as the compiler. This simply tells gcc not
* to warn about the following non-standard code when compiling with the
* option.
*/
/**
* G_GNUC_CONST:
*
* Expands to the GNU C const function attribute if
* the compiler is gcc. Declaring a function as const
* enables better optimization of calls to the function. A const function
* doesn't examine any values except its parameters, and has no effects
* except its return value.
*
* Place the attribute after the declaration, just before the semicolon.
*
* See the GNU C documentation for more details.
*
*
* A function that has pointer arguments and examines the data pointed to
* must not be declared const. Likewise, a function
* that calls a non-const function usually must not be const. It doesn't
* make sense for a const function to return void.
*
*/
/**
* G_GNUC_PURE:
*
* Expands to the GNU C pure function attribute if the
* compiler is gcc. Declaring a function as pure enables
* better optimization of calls to the function. A pure function has no
* effects except its return value and the return value depends only on
* the parameters and/or global variables.
*
* Place the attribute after the declaration, just before the semicolon.
*
* See the GNU C documentation for more details.
*/
/**
* G_GNUC_MALLOC:
*
* Expands to the GNU C malloc function attribute if the
* compiler is gcc. Declaring a function as malloc enables
* better optimization of the function. A function can have the malloc
* attribute if it returns a pointer which is guaranteed to not alias with
* any other pointer when the function returns (in practice, this means newly
* allocated memory).
*
* Place the attribute after the declaration, just before the semicolon.
*
* See the GNU C documentation for more details.
*
* Since: 2.6
*/
/**
* G_GNUC_ALLOC_SIZE:
* @x: the index of the argument specifying the allocation size
*
* Expands to the GNU C alloc_size function attribute
* if the compiler is a new enough gcc. This attribute
* tells the compiler that the function returns a pointer to memory of a
* size that is specified by the @xth function parameter.
*
* Place the attribute after the function declaration, just before the
* semicolon.
*
* See the GNU C documentation for more details.
*
* Since: 2.18
*/
/**
* G_GNUC_ALLOC_SIZE2:
* @x: the index of the argument specifying one factor of the allocation size
* @y: the index of the argument specifying the second factor of the allocation size
*
* Expands to the GNU C alloc_size function attribute
* if the compiler is a new enough gcc. This attribute
* tells the compiler that the function returns a pointer to memory of a
* size that is specified by the product of two function parameters.
*
* Place the attribute after the function declaration, just before the
* semicolon.
*
* See the GNU C documentation for more details.
*
* Since: 2.18
*/
/**
* G_GNUC_DEPRECATED:
*
* Expands to the GNU C deprecated attribute if the
* compiler is gcc. It can be used to mark typedefs,
* variables and functions as deprecated. When called with the
* option, the compiler will
* generate warnings when deprecated interfaces are used.
*
* Place the attribute after the declaration, just before the semicolon.
*
* See the GNU C documentation for more details.
*
* Since: 2.2
*/
/**
* G_GNUC_DEPRECATED_FOR:
* @f: the intended replacement for the deprecated symbol,
* such as the name of a function
*
* Like %G_GNUC_DEPRECATED, but names the intended replacement for the
* deprecated symbol if the version of gcc in use is
* new enough to support custom deprecation messages.
*
* Place the attribute after the declaration, just before the semicolon.
*
* See the GNU C documentation for more details.
*
* Note that if @f is a macro, it will be expanded in the warning message.
* You can enclose it in quotes to prevent this. (The quotes will show up
* in the warning, but it's better than showing the macro expansion.)
*
* Since: 2.26
*/
/**
* G_GNUC_BEGIN_IGNORE_DEPRECATIONS:
*
* Tells gcc (if it is a new enough version) to
* temporarily stop emitting warnings when functions marked with
* %G_GNUC_DEPRECATED or %G_GNUC_DEPRECATED_FOR are called. This is
* useful for when you have one deprecated function calling another
* one, or when you still have regression tests for deprecated
* functions.
*
* Use %G_GNUC_END_IGNORE_DEPRECATIONS to begin warning again. (If you
* are not compiling with -Wdeprecated-declarations
* then neither macro has any effect.)
*
* This macro can be used either inside or outside of a function body,
* but must appear on a line by itself.
*
* Since: 2.32
*/
/**
* G_GNUC_END_IGNORE_DEPRECATIONS:
*
* Undoes the effect of %G_GNUC_BEGIN_IGNORE_DEPRECATIONS, telling
* gcc to begin outputting warnings again
* (assuming those warnings had been enabled to begin with).
*
* This macro can be used either inside or outside of a function body,
* but must appear on a line by itself.
*
* Since: 2.32
*/
/**
* G_DEPRECATED:
*
* This macro is similar to %G_GNUC_DEPRECATED, and can be used to mark
* functions declarations as deprecated. Unlike %G_GNUC_DEPRECATED, it is
* meant to be portable across different compilers and must be placed
* before the function declaration.
*
* Since: 2.32
*/
/**
* G_DEPRECATED_FOR:
* @f: the name of the function that this function was deprecated for
*
* This macro is similar to %G_GNUC_DEPRECATED_FOR, and can be used to mark
* functions declarations as deprecated. Unlike %G_GNUC_DEPRECATED_FOR, it is
* meant to be portable across different compilers and must be placed
* before the function declaration.
*
* Since: 2.32
*/
/**
* G_UNAVAILABLE:
* @maj: the major version that introduced the symbol
* @min: the minor version that introduced the symbol
*
* This macro can be used to mark a function declaration as unavailable.
* It must be placed before the function declaration. Use of a function
* that has been annotated with this macros will produce a compiler warning.
*
* Since: 2.32
*/
/**
* GLIB_DISABLE_DEPRECATION_WARNINGS:
*
* A macro that should be defined before including the glib.h header.
* If it is defined, no compiler warnings will be produced for uses
* of deprecated GLib APIs.
*/
/**
* G_GNUC_NORETURN:
*
* Expands to the GNU C noreturn function attribute
* if the compiler is gcc. It is used for declaring
* functions which never return. It enables optimization of the function,
* and avoids possible compiler warnings.
*
* Place the attribute after the declaration, just before the semicolon.
*
* See the GNU C documentation for more details.
*/
/**
* G_GNUC_UNUSED:
*
* Expands to the GNU C unused function attribute if
* the compiler is gcc. It is used for declaring
* functions and arguments which may never be used. It avoids possible compiler
* warnings.
*
* For functions, place the attribute after the declaration, just before the
* semicolon. For arguments, place the attribute at the beginning of the
* argument declaration.
*
* |[
* void my_unused_function (G_GNUC_UNUSED gint unused_argument,
* gint other_argument) G_GNUC_UNUSED;
* ]|
*
* See the GNU C documentation for more details.
*/
/**
* G_GNUC_PRINTF:
* @format_idx: the index of the argument corresponding to the
* format string (The arguments are numbered from 1)
* @arg_idx: the index of the first of the format arguments
*
* Expands to the GNU C format function attribute
* if the compiler is gcc. This is used for declaring
* functions which take a variable number of arguments, with the same
* syntax as printf(). It allows the compiler to type-check the arguments
* passed to the function.
*
* Place the attribute after the function declaration, just before the
* semicolon.
*
* See the GNU C documentation for more details.
*
* |[
* gint g_snprintf (gchar *string,
* gulong n,
* gchar const *format,
* ...) G_GNUC_PRINTF (3, 4);
* ]|
*/
/**
* G_GNUC_SCANF:
* @format_idx: the index of the argument corresponding to
* the format string (The arguments are numbered from 1)
* @arg_idx: the index of the first of the format arguments
*
* Expands to the GNU C format function attribute
* if the compiler is gcc. This is used for declaring
* functions which take a variable number of arguments, with the same
* syntax as scanf(). It allows the compiler to type-check the arguments
* passed to the function. See the GNU C documentation for details.
*/
/**
* G_GNUC_FORMAT:
* @arg_idx: the index of the argument
*
* Expands to the GNU C format_arg function attribute
* if the compiler is gcc. This function attribute
* specifies that a function takes a format string for a printf(),
* scanf(), strftime() or strfmon() style function and modifies it,
* so that the result can be passed to a printf(), scanf(), strftime()
* or strfmon() style function (with the remaining arguments to the
* format function the same as they would have been for the unmodified
* string).
*
* Place the attribute after the function declaration, just before the
* semicolon.
*
* See the GNU C documentation for more details.
*
* |[
* gchar *g_dgettext (gchar *domain_name, gchar *msgid) G_GNUC_FORMAT (2);
* ]|
*/
/**
* G_GNUC_NULL_TERMINATED:
*
* Expands to the GNU C sentinel function attribute
* if the compiler is gcc, or "" if it isn't. This
* function attribute only applies to variadic functions and instructs
* the compiler to check that the argument list is terminated with an
* explicit %NULL.
*
* Place the attribute after the declaration, just before the semicolon.
*
* See the GNU C documentation for more details.
*
* Since: 2.8
*/
/**
* G_GNUC_WARN_UNUSED_RESULT:
*
* Expands to the GNU C warn_unused_result function
* attribute if the compiler is gcc, or "" if it isn't.
* This function attribute makes the compiler emit a warning if the result
* of a function call is ignored.
*
* Place the attribute after the declaration, just before the semicolon.
*
* See the GNU C documentation for more details.
*
* Since: 2.10
*/
/**
* G_GNUC_FUNCTION:
*
* Expands to "" on all modern compilers, and to
* __FUNCTION__ on gcc version 2.x.
* Don't use it.
*
* Deprecated: 2.16: Use #G_STRFUNC instead
*/
/**
* G_GNUC_PRETTY_FUNCTION:
*
* Expands to "" on all modern compilers, and to
* __PRETTY_FUNCTION__ on gcc
* version 2.x. Don't use it.
*
* Deprecated: 2.16: Use #G_STRFUNC instead
*/
/**
* G_GNUC_NO_INSTRUMENT:
*
* Expands to the GNU C no_instrument_function function
* attribute if the compiler is gcc. Functions with this
* attribute will not be instrumented for profiling, when the compiler is
* called with the option.
*
* Place the attribute after the declaration, just before the semicolon.
*
* See the GNU C documentation for more details.
*/
/**
* G_GNUC_INTERNAL:
*
* This attribute can be used for marking library functions as being used
* internally to the library only, which may allow the compiler to handle
* function calls more efficiently. Note that static functions do not need
* to be marked as internal in this way. See the GNU C documentation for
* details.
*
* When using a compiler that supports the GNU C hidden visibility attribute,
* this macro expands to __attribute__((visibility("hidden"))).
* When using the Sun Studio compiler, it expands to __hidden.
*
* Note that for portability, the attribute should be placed before the
* function declaration. While GCC allows the macro after the declaration,
* Sun Studio does not.
*
* |[
* G_GNUC_INTERNAL
* void _g_log_fallback_handler (const gchar *log_domain,
* GLogLevelFlags log_level,
* const gchar *message,
* gpointer unused_data);
* ]|
*
* Since: 2.6
*/
/**
* G_GNUC_MAY_ALIAS:
*
* Expands to the GNU C may_alias type attribute
* if the compiler is gcc. Types with this attribute
* will not be subjected to type-based alias analysis, but are assumed
* to alias with any other type, just like char.
* See the GNU C documentation for details.
*
* Since: 2.14
*/
/**
* G_LIKELY:
* @expr: the expression
*
* Hints the compiler that the expression is likely to evaluate to
* a true value. The compiler may use this information for optimizations.
*
* |[
* if (G_LIKELY (random () != 1))
* g_print ("not one");
* ]|
*
* Returns: the value of @expr
*
* Since: 2.2
*/
/**
* G_UNLIKELY:
* @expr: the expression
*
* Hints the compiler that the expression is unlikely to evaluate to
* a true value. The compiler may use this information for optimizations.
*
* |[
* if (G_UNLIKELY (random () == 1))
* g_print ("a random one");
* ]|
*
* Returns: the value of @expr
*
* Since: 2.2
*/
/**
* G_STRLOC:
*
* Expands to a string identifying the current code position.
*/
/**
* G_STRFUNC:
*
* Expands to a string identifying the current function.
*
* Since: 2.4
*/
/* Windows Compatibility Functions {{{1 */
/**
* SECTION:windows
* @title: Windows Compatibility Functions
* @short_description: UNIX emulation on Windows
*
* These functions provide some level of UNIX emulation on the
* Windows platform. If your application really needs the POSIX
* APIs, we suggest you try the Cygwin project.
*/
/**
* MAXPATHLEN:
*
* Provided for UNIX emulation on Windows; equivalent to UNIX
* macro %MAXPATHLEN, which is the maximum length of a filename
* (including full path).
*/
/**
* G_WIN32_DLLMAIN_FOR_DLL_NAME:
* @static: empty or "static"
* @dll_name: the name of the (pointer to the) char array where
* the DLL name will be stored. If this is used, you must also
* include windows.h. If you need a more
* complex DLL entry point function, you cannot use this
*
* On Windows, this macro defines a DllMain() function that stores
* the actual DLL name that the code being compiled will be included in.
*
* On non-Windows platforms, expands to nothing.
*/
/**
* G_WIN32_HAVE_WIDECHAR_API:
*
* On Windows, this macro defines an expression which evaluates to
* %TRUE if the code is running on a version of Windows where the wide
* character versions of the Win32 API functions, and the wide character
* versions of the C library functions work. (They are always present in
* the DLLs, but don't work on Windows 9x and Me.)
*
* On non-Windows platforms, it is not defined.
*
* Since: 2.6
*/
/**
* G_WIN32_IS_NT_BASED:
*
* On Windows, this macro defines an expression which evaluates to
* %TRUE if the code is running on an NT-based Windows operating system.
*
* On non-Windows platforms, it is not defined.
*
* Since: 2.6
*/
/* Epilogue {{{1 */
/* vim: set foldmethod=marker: */
pkg-config-0.29.1/glib/glib/gconstructor.h 0000664 0001750 0001750 00000005473 12275467762 015344 0000000 0000000 /*
If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and
destructors, in a sane way, including e.g. on library unload. If not you're on
your own.
Some compilers need #pragma to handle this, which does not work with macros,
so the way you need to use this is (for constructors):
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(my_constructor)
#endif
G_DEFINE_CONSTRUCTOR(my_constructor)
static void my_constructor(void) {
...
}
*/
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
#define G_HAS_CONSTRUCTORS 1
#define G_DEFINE_CONSTRUCTOR(_func) static void __attribute__((constructor)) _func (void);
#define G_DEFINE_DESTRUCTOR(_func) static void __attribute__((destructor)) _func (void);
#elif defined (_MSC_VER) && (_MSC_VER >= 1500)
/* Visual studio 2008 and later has _Pragma */
#define G_HAS_CONSTRUCTORS 1
#define G_DEFINE_CONSTRUCTOR(_func) \
static void _func(void); \
static int _func ## _wrapper(void) { _func(); return 0; } \
__pragma(section(".CRT$XCU",read)) \
__declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _wrapper;
#define G_DEFINE_DESTRUCTOR(_func) \
static void _func(void); \
static int _func ## _constructor(void) { atexit (_func); return 0; } \
__pragma(section(".CRT$XCU",read)) \
__declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor;
#elif defined (_MSC_VER)
#define G_HAS_CONSTRUCTORS 1
/* Pre Visual studio 2008 must use #pragma section */
#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
section(".CRT$XCU",read)
#define G_DEFINE_CONSTRUCTOR(_func) \
static void _func(void); \
static int _func ## _wrapper(void) { _func(); return 0; } \
__declspec(allocate(".CRT$XCU")) static int (*p)(void) = _func ## _wrapper;
#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
section(".CRT$XCU",read)
#define G_DEFINE_DESTRUCTOR(_func) \
static void _func(void); \
static int _func ## _constructor(void) { atexit (_func); return 0; } \
__declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor;
#elif defined(__SUNPRO_C)
/* This is not tested, but i believe it should work, based on:
* http://opensource.apple.com/source/OpenSSL098/OpenSSL098-35/src/fips/fips_premain.c
*/
#define G_HAS_CONSTRUCTORS 1
#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
init(_func)
#define G_DEFINE_CONSTRUCTOR(_func) \
static void _func(void);
#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
fini(_func)
#define G_DEFINE_DESTRUCTOR(_func) \
static void _func(void);
#else
/* constructors not supported for this compiler */
#endif
pkg-config-0.29.1/glib/glib/gstringchunk.c 0000664 0001750 0001750 00000021061 12275467762 015300 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
/*
* MT safe
*/
#include "config.h"
#include
#include "gstringchunk.h"
#include "ghash.h"
#include "gslist.h"
#include "gmessages.h"
#include "gutils.h"
/**
* SECTION:string_chunks
* @title: String Chunks
* @short_description: efficient storage of groups of strings
*
* String chunks are used to store groups of strings. Memory is
* allocated in blocks, and as strings are added to the #GStringChunk
* they are copied into the next free position in a block. When a block
* is full a new block is allocated.
*
* When storing a large number of strings, string chunks are more
* efficient than using g_strdup() since fewer calls to malloc() are
* needed, and less memory is wasted in memory allocation overheads.
*
* By adding strings with g_string_chunk_insert_const() it is also
* possible to remove duplicates.
*
* To create a new #GStringChunk use g_string_chunk_new().
*
* To add strings to a #GStringChunk use g_string_chunk_insert().
*
* To add strings to a #GStringChunk, but without duplicating strings
* which are already in the #GStringChunk, use
* g_string_chunk_insert_const().
*
* To free the entire #GStringChunk use g_string_chunk_free(). It is
* not possible to free individual strings.
*/
/**
* GStringChunk:
*
* An opaque data structure representing String Chunks.
* It should only be accessed by using the following functions.
*/
struct _GStringChunk
{
GHashTable *const_table;
GSList *storage_list;
gsize storage_next;
gsize this_size;
gsize default_size;
};
#define MY_MAXSIZE ((gsize)-1)
static inline gsize
nearest_power (gsize base,
gsize num)
{
if (num > MY_MAXSIZE / 2)
{
return MY_MAXSIZE;
}
else
{
gsize n = base;
while (n < num)
n <<= 1;
return n;
}
}
/**
* g_string_chunk_new:
* @size: the default size of the blocks of memory which are
* allocated to store the strings. If a particular string
* is larger than this default size, a larger block of
* memory will be allocated for it.
*
* Creates a new #GStringChunk.
*
* Returns: a new #GStringChunk
*/
GStringChunk *
g_string_chunk_new (gsize size)
{
GStringChunk *new_chunk = g_new (GStringChunk, 1);
gsize actual_size = 1;
actual_size = nearest_power (1, size);
new_chunk->const_table = NULL;
new_chunk->storage_list = NULL;
new_chunk->storage_next = actual_size;
new_chunk->default_size = actual_size;
new_chunk->this_size = actual_size;
return new_chunk;
}
/**
* g_string_chunk_free:
* @chunk: a #GStringChunk
*
* Frees all memory allocated by the #GStringChunk.
* After calling g_string_chunk_free() it is not safe to
* access any of the strings which were contained within it.
*/
void
g_string_chunk_free (GStringChunk *chunk)
{
GSList *tmp_list;
g_return_if_fail (chunk != NULL);
if (chunk->storage_list)
{
for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next)
g_free (tmp_list->data);
g_slist_free (chunk->storage_list);
}
if (chunk->const_table)
g_hash_table_destroy (chunk->const_table);
g_free (chunk);
}
/**
* g_string_chunk_clear:
* @chunk: a #GStringChunk
*
* Frees all strings contained within the #GStringChunk.
* After calling g_string_chunk_clear() it is not safe to
* access any of the strings which were contained within it.
*
* Since: 2.14
*/
void
g_string_chunk_clear (GStringChunk *chunk)
{
GSList *tmp_list;
g_return_if_fail (chunk != NULL);
if (chunk->storage_list)
{
for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next)
g_free (tmp_list->data);
g_slist_free (chunk->storage_list);
chunk->storage_list = NULL;
chunk->storage_next = chunk->default_size;
chunk->this_size = chunk->default_size;
}
if (chunk->const_table)
g_hash_table_remove_all (chunk->const_table);
}
/**
* g_string_chunk_insert:
* @chunk: a #GStringChunk
* @string: the string to add
*
* Adds a copy of @string to the #GStringChunk.
* It returns a pointer to the new copy of the string
* in the #GStringChunk. The characters in the string
* can be changed, if necessary, though you should not
* change anything after the end of the string.
*
* Unlike g_string_chunk_insert_const(), this function
* does not check for duplicates. Also strings added
* with g_string_chunk_insert() will not be searched
* by g_string_chunk_insert_const() when looking for
* duplicates.
*
* Returns: a pointer to the copy of @string within
* the #GStringChunk
*/
gchar*
g_string_chunk_insert (GStringChunk *chunk,
const gchar *string)
{
g_return_val_if_fail (chunk != NULL, NULL);
return g_string_chunk_insert_len (chunk, string, -1);
}
/**
* g_string_chunk_insert_const:
* @chunk: a #GStringChunk
* @string: the string to add
*
* Adds a copy of @string to the #GStringChunk, unless the same
* string has already been added to the #GStringChunk with
* g_string_chunk_insert_const().
*
* This function is useful if you need to copy a large number
* of strings but do not want to waste space storing duplicates.
* But you must remember that there may be several pointers to
* the same string, and so any changes made to the strings
* should be done very carefully.
*
* Note that g_string_chunk_insert_const() will not return a
* pointer to a string added with g_string_chunk_insert(), even
* if they do match.
*
* Returns: a pointer to the new or existing copy of @string
* within the #GStringChunk
*/
gchar*
g_string_chunk_insert_const (GStringChunk *chunk,
const gchar *string)
{
char* lookup;
g_return_val_if_fail (chunk != NULL, NULL);
if (!chunk->const_table)
chunk->const_table = g_hash_table_new (g_str_hash, g_str_equal);
lookup = (char*) g_hash_table_lookup (chunk->const_table, (gchar *)string);
if (!lookup)
{
lookup = g_string_chunk_insert (chunk, string);
g_hash_table_insert (chunk->const_table, lookup, lookup);
}
return lookup;
}
/**
* g_string_chunk_insert_len:
* @chunk: a #GStringChunk
* @string: bytes to insert
* @len: number of bytes of @string to insert, or -1 to insert a
* nul-terminated string
*
* Adds a copy of the first @len bytes of @string to the #GStringChunk.
* The copy is nul-terminated.
*
* Since this function does not stop at nul bytes, it is the caller's
* responsibility to ensure that @string has at least @len addressable
* bytes.
*
* The characters in the returned string can be changed, if necessary,
* though you should not change anything after the end of the string.
*
* Return value: a pointer to the copy of @string within the #GStringChunk
*
* Since: 2.4
*/
gchar*
g_string_chunk_insert_len (GStringChunk *chunk,
const gchar *string,
gssize len)
{
gssize size;
gchar* pos;
g_return_val_if_fail (chunk != NULL, NULL);
if (len < 0)
size = strlen (string);
else
size = len;
if ((chunk->storage_next + size + 1) > chunk->this_size)
{
gsize new_size = nearest_power (chunk->default_size, size + 1);
chunk->storage_list = g_slist_prepend (chunk->storage_list,
g_new (gchar, new_size));
chunk->this_size = new_size;
chunk->storage_next = 0;
}
pos = ((gchar *) chunk->storage_list->data) + chunk->storage_next;
*(pos + size) = '\0';
memcpy (pos, string, size);
chunk->storage_next += size + 1;
return pos;
}
pkg-config-0.29.1/glib/glib/ghostutils.c 0000664 0001750 0001750 00000047401 12275467762 015005 0000000 0000000 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* GLIB - Library of useful routines for C programming
* Copyright (C) 2008 Red Hat, Inc.
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include
#include "ghostutils.h"
#include "garray.h"
#include "gmem.h"
#include "gstring.h"
#include "gstrfuncs.h"
#include "glibintl.h"
/**
* SECTION:ghostutils
* @short_description: Internet hostname utilities
*
* Functions for manipulating internet hostnames; in particular, for
* converting between Unicode and ASCII-encoded forms of
* Internationalized Domain Names (IDNs).
*
* The Internationalized Domain
* Names for Applications (IDNA) standards allow for the use
* of Unicode domain names in applications, while providing
* backward-compatibility with the old ASCII-only DNS, by defining an
* ASCII-Compatible Encoding of any given Unicode name, which can be
* used with non-IDN-aware applications and protocols. (For example,
* "Παν語.org" maps to "xn--4wa8awb4637h.org".)
**/
#define IDNA_ACE_PREFIX "xn--"
#define IDNA_ACE_PREFIX_LEN 4
/* Punycode constants, from RFC 3492. */
#define PUNYCODE_BASE 36
#define PUNYCODE_TMIN 1
#define PUNYCODE_TMAX 26
#define PUNYCODE_SKEW 38
#define PUNYCODE_DAMP 700
#define PUNYCODE_INITIAL_BIAS 72
#define PUNYCODE_INITIAL_N 0x80
#define PUNYCODE_IS_BASIC(cp) ((guint)(cp) < 0x80)
/* Encode/decode a single base-36 digit */
static inline gchar
encode_digit (guint dig)
{
if (dig < 26)
return dig + 'a';
else
return dig - 26 + '0';
}
static inline guint
decode_digit (gchar dig)
{
if (dig >= 'A' && dig <= 'Z')
return dig - 'A';
else if (dig >= 'a' && dig <= 'z')
return dig - 'a';
else if (dig >= '0' && dig <= '9')
return dig - '0' + 26;
else
return G_MAXUINT;
}
/* Punycode bias adaptation algorithm, RFC 3492 section 6.1 */
static guint
adapt (guint delta,
guint numpoints,
gboolean firsttime)
{
guint k;
delta = firsttime ? delta / PUNYCODE_DAMP : delta / 2;
delta += delta / numpoints;
k = 0;
while (delta > ((PUNYCODE_BASE - PUNYCODE_TMIN) * PUNYCODE_TMAX) / 2)
{
delta /= PUNYCODE_BASE - PUNYCODE_TMIN;
k += PUNYCODE_BASE;
}
return k + ((PUNYCODE_BASE - PUNYCODE_TMIN + 1) * delta /
(delta + PUNYCODE_SKEW));
}
/* Punycode encoder, RFC 3492 section 6.3. The algorithm is
* sufficiently bizarre that it's not really worth trying to explain
* here.
*/
static gboolean
punycode_encode (const gchar *input_utf8,
gsize input_utf8_length,
GString *output)
{
guint delta, handled_chars, num_basic_chars, bias, j, q, k, t, digit;
gunichar n, m, *input;
glong input_length;
gboolean success = FALSE;
/* Convert from UTF-8 to Unicode code points */
input = g_utf8_to_ucs4 (input_utf8, input_utf8_length, NULL,
&input_length, NULL);
if (!input)
return FALSE;
/* Copy basic chars */
for (j = num_basic_chars = 0; j < input_length; j++)
{
if (PUNYCODE_IS_BASIC (input[j]))
{
g_string_append_c (output, g_ascii_tolower (input[j]));
num_basic_chars++;
}
}
if (num_basic_chars)
g_string_append_c (output, '-');
handled_chars = num_basic_chars;
/* Encode non-basic chars */
delta = 0;
bias = PUNYCODE_INITIAL_BIAS;
n = PUNYCODE_INITIAL_N;
while (handled_chars < input_length)
{
/* let m = the minimum {non-basic} code point >= n in the input */
for (m = G_MAXUINT, j = 0; j < input_length; j++)
{
if (input[j] >= n && input[j] < m)
m = input[j];
}
if (m - n > (G_MAXUINT - delta) / (handled_chars + 1))
goto fail;
delta += (m - n) * (handled_chars + 1);
n = m;
for (j = 0; j < input_length; j++)
{
if (input[j] < n)
{
if (++delta == 0)
goto fail;
}
else if (input[j] == n)
{
q = delta;
for (k = PUNYCODE_BASE; ; k += PUNYCODE_BASE)
{
if (k <= bias)
t = PUNYCODE_TMIN;
else if (k >= bias + PUNYCODE_TMAX)
t = PUNYCODE_TMAX;
else
t = k - bias;
if (q < t)
break;
digit = t + (q - t) % (PUNYCODE_BASE - t);
g_string_append_c (output, encode_digit (digit));
q = (q - t) / (PUNYCODE_BASE - t);
}
g_string_append_c (output, encode_digit (q));
bias = adapt (delta, handled_chars + 1, handled_chars == num_basic_chars);
delta = 0;
handled_chars++;
}
}
delta++;
n++;
}
success = TRUE;
fail:
g_free (input);
return success;
}
/* From RFC 3454, Table B.1 */
#define idna_is_junk(ch) ((ch) == 0x00AD || (ch) == 0x1806 || (ch) == 0x200B || (ch) == 0x2060 || (ch) == 0xFEFF || (ch) == 0x034F || (ch) == 0x180B || (ch) == 0x180C || (ch) == 0x180D || (ch) == 0x200C || (ch) == 0x200D || ((ch) >= 0xFE00 && (ch) <= 0xFE0F))
/* Scan @str for "junk" and return a cleaned-up string if any junk
* is found. Else return %NULL.
*/
static gchar *
remove_junk (const gchar *str,
gint len)
{
GString *cleaned = NULL;
const gchar *p;
gunichar ch;
for (p = str; len == -1 ? *p : p < str + len; p = g_utf8_next_char (p))
{
ch = g_utf8_get_char (p);
if (idna_is_junk (ch))
{
if (!cleaned)
{
cleaned = g_string_new (NULL);
g_string_append_len (cleaned, str, p - str);
}
}
else if (cleaned)
g_string_append_unichar (cleaned, ch);
}
if (cleaned)
return g_string_free (cleaned, FALSE);
else
return NULL;
}
static inline gboolean
contains_uppercase_letters (const gchar *str,
gint len)
{
const gchar *p;
for (p = str; len == -1 ? *p : p < str + len; p = g_utf8_next_char (p))
{
if (g_unichar_isupper (g_utf8_get_char (p)))
return TRUE;
}
return FALSE;
}
static inline gboolean
contains_non_ascii (const gchar *str,
gint len)
{
const gchar *p;
for (p = str; len == -1 ? *p : p < str + len; p++)
{
if ((guchar)*p > 0x80)
return TRUE;
}
return FALSE;
}
/* RFC 3454, Appendix C. ish. */
static inline gboolean
idna_is_prohibited (gunichar ch)
{
switch (g_unichar_type (ch))
{
case G_UNICODE_CONTROL:
case G_UNICODE_FORMAT:
case G_UNICODE_UNASSIGNED:
case G_UNICODE_PRIVATE_USE:
case G_UNICODE_SURROGATE:
case G_UNICODE_LINE_SEPARATOR:
case G_UNICODE_PARAGRAPH_SEPARATOR:
case G_UNICODE_SPACE_SEPARATOR:
return TRUE;
case G_UNICODE_OTHER_SYMBOL:
if (ch == 0xFFFC || ch == 0xFFFD ||
(ch >= 0x2FF0 && ch <= 0x2FFB))
return TRUE;
return FALSE;
case G_UNICODE_NON_SPACING_MARK:
if (ch == 0x0340 || ch == 0x0341)
return TRUE;
return FALSE;
default:
return FALSE;
}
}
/* RFC 3491 IDN cleanup algorithm. */
static gchar *
nameprep (const gchar *hostname,
gint len,
gboolean *is_unicode)
{
gchar *name, *tmp = NULL, *p;
/* It would be nice if we could do this without repeatedly
* allocating strings and converting back and forth between
* gunichars and UTF-8... The code does at least avoid doing most of
* the sub-operations when they would just be equivalent to a
* g_strdup().
*/
/* Remove presentation-only characters */
name = remove_junk (hostname, len);
if (name)
{
tmp = name;
len = -1;
}
else
name = (gchar *)hostname;
/* Convert to lowercase */
if (contains_uppercase_letters (name, len))
{
name = g_utf8_strdown (name, len);
g_free (tmp);
tmp = name;
len = -1;
}
/* If there are no UTF8 characters, we're done. */
if (!contains_non_ascii (name, len))
{
*is_unicode = FALSE;
if (name == (gchar *)hostname)
return len == -1 ? g_strdup (hostname) : g_strndup (hostname, len);
else
return name;
}
*is_unicode = TRUE;
/* Normalize */
name = g_utf8_normalize (name, len, G_NORMALIZE_NFKC);
g_free (tmp);
tmp = name;
if (!name)
return NULL;
/* KC normalization may have created more capital letters (eg,
* angstrom -> capital A with ring). So we have to lowercasify a
* second time. (This is more-or-less how the nameprep algorithm
* does it. If tolower(nfkc(tolower(X))) is guaranteed to be the
* same as tolower(nfkc(X)), then we could skip the first tolower,
* but I'm not sure it is.)
*/
if (contains_uppercase_letters (name, -1))
{
name = g_utf8_strdown (name, -1);
g_free (tmp);
tmp = name;
}
/* Check for prohibited characters */
for (p = name; *p; p = g_utf8_next_char (p))
{
if (idna_is_prohibited (g_utf8_get_char (p)))
{
name = NULL;
g_free (tmp);
goto done;
}
}
/* FIXME: We're supposed to verify certain constraints on bidi
* characters, but glib does not appear to have that information.
*/
done:
return name;
}
/* RFC 3490, section 3.1 says '.', 0x3002, 0xFF0E, and 0xFF61 count as
* label-separating dots. @str must be '\0'-terminated.
*/
#define idna_is_dot(str) ( \
((guchar)(str)[0] == '.') || \
((guchar)(str)[0] == 0xE3 && (guchar)(str)[1] == 0x80 && (guchar)(str)[2] == 0x82) || \
((guchar)(str)[0] == 0xEF && (guchar)(str)[1] == 0xBC && (guchar)(str)[2] == 0x8E) || \
((guchar)(str)[0] == 0xEF && (guchar)(str)[1] == 0xBD && (guchar)(str)[2] == 0xA1) )
static const gchar *
idna_end_of_label (const gchar *str)
{
for (; *str; str = g_utf8_next_char (str))
{
if (idna_is_dot (str))
return str;
}
return str;
}
/**
* g_hostname_to_ascii:
* @hostname: a valid UTF-8 or ASCII hostname
*
* Converts @hostname to its canonical ASCII form; an ASCII-only
* string containing no uppercase letters and not ending with a
* trailing dot.
*
* Return value: an ASCII hostname, which must be freed, or %NULL if
* @hostname is in some way invalid.
*
* Since: 2.22
**/
gchar *
g_hostname_to_ascii (const gchar *hostname)
{
gchar *name, *label, *p;
GString *out;
gssize llen, oldlen;
gboolean unicode;
label = name = nameprep (hostname, -1, &unicode);
if (!name || !unicode)
return name;
out = g_string_new (NULL);
do
{
unicode = FALSE;
for (p = label; *p && !idna_is_dot (p); p++)
{
if ((guchar)*p > 0x80)
unicode = TRUE;
}
oldlen = out->len;
llen = p - label;
if (unicode)
{
if (!strncmp (label, IDNA_ACE_PREFIX, IDNA_ACE_PREFIX_LEN))
goto fail;
g_string_append (out, IDNA_ACE_PREFIX);
if (!punycode_encode (label, llen, out))
goto fail;
}
else
g_string_append_len (out, label, llen);
if (out->len - oldlen > 63)
goto fail;
label += llen;
if (*label)
label = g_utf8_next_char (label);
if (*label)
g_string_append_c (out, '.');
}
while (*label);
g_free (name);
return g_string_free (out, FALSE);
fail:
g_free (name);
g_string_free (out, TRUE);
return NULL;
}
/**
* g_hostname_is_non_ascii:
* @hostname: a hostname
*
* Tests if @hostname contains Unicode characters. If this returns
* %TRUE, you need to encode the hostname with g_hostname_to_ascii()
* before using it in non-IDN-aware contexts.
*
* Note that a hostname might contain a mix of encoded and unencoded
* segments, and so it is possible for g_hostname_is_non_ascii() and
* g_hostname_is_ascii_encoded() to both return %TRUE for a name.
*
* Return value: %TRUE if @hostname contains any non-ASCII characters
*
* Since: 2.22
**/
gboolean
g_hostname_is_non_ascii (const gchar *hostname)
{
return contains_non_ascii (hostname, -1);
}
/* Punycode decoder, RFC 3492 section 6.2. As with punycode_encode(),
* read the RFC if you want to understand what this is actually doing.
*/
static gboolean
punycode_decode (const gchar *input,
gsize input_length,
GString *output)
{
GArray *output_chars;
gunichar n;
guint i, bias;
guint oldi, w, k, digit, t;
const gchar *split;
n = PUNYCODE_INITIAL_N;
i = 0;
bias = PUNYCODE_INITIAL_BIAS;
split = input + input_length - 1;
while (split > input && *split != '-')
split--;
if (split > input)
{
output_chars = g_array_sized_new (FALSE, FALSE, sizeof (gunichar),
split - input);
input_length -= (split - input) + 1;
while (input < split)
{
gunichar ch = (gunichar)*input++;
if (!PUNYCODE_IS_BASIC (ch))
goto fail;
g_array_append_val (output_chars, ch);
}
input++;
}
else
output_chars = g_array_new (FALSE, FALSE, sizeof (gunichar));
while (input_length)
{
oldi = i;
w = 1;
for (k = PUNYCODE_BASE; ; k += PUNYCODE_BASE)
{
if (!input_length--)
goto fail;
digit = decode_digit (*input++);
if (digit >= PUNYCODE_BASE)
goto fail;
if (digit > (G_MAXUINT - i) / w)
goto fail;
i += digit * w;
if (k <= bias)
t = PUNYCODE_TMIN;
else if (k >= bias + PUNYCODE_TMAX)
t = PUNYCODE_TMAX;
else
t = k - bias;
if (digit < t)
break;
if (w > G_MAXUINT / (PUNYCODE_BASE - t))
goto fail;
w *= (PUNYCODE_BASE - t);
}
bias = adapt (i - oldi, output_chars->len + 1, oldi == 0);
if (i / (output_chars->len + 1) > G_MAXUINT - n)
goto fail;
n += i / (output_chars->len + 1);
i %= (output_chars->len + 1);
g_array_insert_val (output_chars, i++, n);
}
for (i = 0; i < output_chars->len; i++)
g_string_append_unichar (output, g_array_index (output_chars, gunichar, i));
g_array_free (output_chars, TRUE);
return TRUE;
fail:
g_array_free (output_chars, TRUE);
return FALSE;
}
/**
* g_hostname_to_unicode:
* @hostname: a valid UTF-8 or ASCII hostname
*
* Converts @hostname to its canonical presentation form; a UTF-8
* string in Unicode normalization form C, containing no uppercase
* letters, no forbidden characters, and no ASCII-encoded segments,
* and not ending with a trailing dot.
*
* Of course if @hostname is not an internationalized hostname, then
* the canonical presentation form will be entirely ASCII.
*
* Return value: a UTF-8 hostname, which must be freed, or %NULL if
* @hostname is in some way invalid.
*
* Since: 2.22
**/
gchar *
g_hostname_to_unicode (const gchar *hostname)
{
GString *out;
gssize llen;
out = g_string_new (NULL);
do
{
llen = idna_end_of_label (hostname) - hostname;
if (!g_ascii_strncasecmp (hostname, IDNA_ACE_PREFIX, IDNA_ACE_PREFIX_LEN))
{
hostname += IDNA_ACE_PREFIX_LEN;
llen -= IDNA_ACE_PREFIX_LEN;
if (!punycode_decode (hostname, llen, out))
{
g_string_free (out, TRUE);
return NULL;
}
}
else
{
gboolean unicode;
gchar *canonicalized = nameprep (hostname, llen, &unicode);
if (!canonicalized)
{
g_string_free (out, TRUE);
return NULL;
}
g_string_append (out, canonicalized);
g_free (canonicalized);
}
hostname += llen;
if (*hostname)
hostname = g_utf8_next_char (hostname);
if (*hostname)
g_string_append_c (out, '.');
}
while (*hostname);
return g_string_free (out, FALSE);
}
/**
* g_hostname_is_ascii_encoded:
* @hostname: a hostname
*
* Tests if @hostname contains segments with an ASCII-compatible
* encoding of an Internationalized Domain Name. If this returns
* %TRUE, you should decode the hostname with g_hostname_to_unicode()
* before displaying it to the user.
*
* Note that a hostname might contain a mix of encoded and unencoded
* segments, and so it is possible for g_hostname_is_non_ascii() and
* g_hostname_is_ascii_encoded() to both return %TRUE for a name.
*
* Return value: %TRUE if @hostname contains any ASCII-encoded
* segments.
*
* Since: 2.22
**/
gboolean
g_hostname_is_ascii_encoded (const gchar *hostname)
{
while (1)
{
if (!g_ascii_strncasecmp (hostname, IDNA_ACE_PREFIX, IDNA_ACE_PREFIX_LEN))
return TRUE;
hostname = idna_end_of_label (hostname);
if (*hostname)
hostname = g_utf8_next_char (hostname);
if (!*hostname)
return FALSE;
}
}
/**
* g_hostname_is_ip_address:
* @hostname: a hostname (or IP address in string form)
*
* Tests if @hostname is the string form of an IPv4 or IPv6 address.
* (Eg, "192.168.0.1".)
*
* Return value: %TRUE if @hostname is an IP address
*
* Since: 2.22
**/
gboolean
g_hostname_is_ip_address (const gchar *hostname)
{
gchar *p, *end;
gint nsegments, octet;
/* On Linux we could implement this using inet_pton, but the Windows
* equivalent of that requires linking against winsock, so we just
* figure this out ourselves. Tested by tests/hostutils.c.
*/
p = (char *)hostname;
if (strchr (p, ':'))
{
gboolean skipped;
/* If it contains a ':', it's an IPv6 address (assuming it's an
* IP address at all). This consists of eight ':'-separated
* segments, each containing a 1-4 digit hex number, except that
* optionally: (a) the last two segments can be replaced by an
* IPv4 address, and (b) a single span of 1 to 8 "0000" segments
* can be replaced with just "::".
*/
nsegments = 0;
skipped = FALSE;
while (*p && nsegments < 8)
{
/* Each segment after the first must be preceded by a ':'.
* (We also handle half of the "string starts with ::" case
* here.)
*/
if (p != (char *)hostname || (p[0] == ':' && p[1] == ':'))
{
if (*p != ':')
return FALSE;
p++;
}
/* If there's another ':', it means we're skipping some segments */
if (*p == ':' && !skipped)
{
skipped = TRUE;
nsegments++;
/* Handle the "string ends with ::" case */
if (!p[1])
p++;
continue;
}
/* Read the segment, make sure it's valid. */
for (end = p; g_ascii_isxdigit (*end); end++)
;
if (end == p || end > p + 4)
return FALSE;
if (*end == '.')
{
if ((nsegments == 6 && !skipped) || (nsegments <= 6 && skipped))
goto parse_ipv4;
else
return FALSE;
}
nsegments++;
p = end;
}
return !*p && (nsegments == 8 || skipped);
}
parse_ipv4:
/* Parse IPv4: N.N.N.N, where each N <= 255 and doesn't have leading 0s. */
for (nsegments = 0; nsegments < 4; nsegments++)
{
if (nsegments != 0)
{
if (*p != '.')
return FALSE;
p++;
}
/* Check the segment; a little tricker than the IPv6 case since
* we can't allow extra leading 0s, and we can't assume that all
* strings of valid length are within range.
*/
octet = 0;
if (*p == '0')
end = p + 1;
else
{
for (end = p; g_ascii_isdigit (*end); end++)
octet = 10 * octet + (*end - '0');
}
if (end == p || end > p + 3 || octet > 255)
return FALSE;
p = end;
}
/* If there's nothing left to parse, then it's ok. */
return !*p;
}
pkg-config-0.29.1/glib/glib/valgrind.h 0000664 0001750 0001750 00001050502 12651243552 014373 0000000 0000000 /* -*- c -*-
----------------------------------------------------------------
Notice that the following BSD-style license applies to this one
file (valgrind.h) only. The rest of Valgrind is licensed under the
terms of the GNU General Public License, version 2, unless
otherwise indicated. See the COPYING file in the source
distribution for details.
----------------------------------------------------------------
This file is part of Valgrind, a dynamic binary instrumentation
framework.
Copyright (C) 2000-2012 Julian Seward. 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. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. 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 BY THE AUTHOR ``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.
----------------------------------------------------------------
Notice that the above BSD-style license applies to this one file
(valgrind.h) only. The entire rest of Valgrind is licensed under
the terms of the GNU General Public License, version 2. See the
COPYING file in the source distribution for details.
----------------------------------------------------------------
*/
/* This file is for inclusion into client (your!) code.
You can use these macros to manipulate and query Valgrind's
execution inside your own programs.
The resulting executables will still run without Valgrind, just a
little bit more slowly than they otherwise would, but otherwise
unchanged. When not running on valgrind, each client request
consumes very few (eg. 7) instructions, so the resulting performance
loss is negligible unless you plan to execute client requests
millions of times per second. Nevertheless, if that is still a
problem, you can compile with the NVALGRIND symbol defined (gcc
-DNVALGRIND) so that client requests are not even compiled in. */
#ifndef __VALGRIND_H
#define __VALGRIND_H
/* ------------------------------------------------------------------ */
/* VERSION NUMBER OF VALGRIND */
/* ------------------------------------------------------------------ */
/* Specify Valgrind's version number, so that user code can
conditionally compile based on our version number. Note that these
were introduced at version 3.6 and so do not exist in version 3.5
or earlier. The recommended way to use them to check for "version
X.Y or later" is (eg)
#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \
&& (__VALGRIND_MAJOR__ > 3 \
|| (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
*/
#define __VALGRIND_MAJOR__ 3
#define __VALGRIND_MINOR__ 8
#include
/* Nb: this file might be included in a file compiled with -ansi. So
we can't use C++ style "//" comments nor the "asm" keyword (instead
use "__asm__"). */
/* Derive some tags indicating what the target platform is. Note
that in this file we're using the compiler's CPP symbols for
identifying architectures, which are different to the ones we use
within the rest of Valgrind. Note, __powerpc__ is active for both
32 and 64-bit PPC, whereas __powerpc64__ is only active for the
latter (on Linux, that is).
Misc note: how to find out what's predefined in gcc by default:
gcc -Wp,-dM somefile.c
*/
#undef PLAT_x86_darwin
#undef PLAT_amd64_darwin
#undef PLAT_x86_win32
#undef PLAT_x86_linux
#undef PLAT_amd64_linux
#undef PLAT_ppc32_linux
#undef PLAT_ppc64_linux
#undef PLAT_arm_linux
#undef PLAT_s390x_linux
#undef PLAT_mips32_linux
#if defined(__APPLE__) && defined(__i386__)
# define PLAT_x86_darwin 1
#elif defined(__APPLE__) && defined(__x86_64__)
# define PLAT_amd64_darwin 1
#elif defined(__MINGW32__) || defined(__CYGWIN32__) \
|| (defined(_WIN32) && defined(_M_IX86))
# define PLAT_x86_win32 1
#elif defined(__linux__) && defined(__i386__)
# define PLAT_x86_linux 1
#elif defined(__linux__) && defined(__x86_64__)
# define PLAT_amd64_linux 1
#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
# define PLAT_ppc32_linux 1
#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
# define PLAT_ppc64_linux 1
#elif defined(__linux__) && defined(__arm__)
# define PLAT_arm_linux 1
#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
# define PLAT_s390x_linux 1
#elif defined(__linux__) && defined(__mips__)
# define PLAT_mips32_linux 1
#else
/* If we're not compiling for our target platform, don't generate
any inline asms. */
# if !defined(NVALGRIND)
# define NVALGRIND 1
# endif
#endif
/* ------------------------------------------------------------------ */
/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
/* in here of use to end-users -- skip to the next section. */
/* ------------------------------------------------------------------ */
/*
* VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
* request. Accepts both pointers and integers as arguments.
*
* VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
* client request that does not return a value.
* VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
* client request and whose value equals the client request result. Accepts
* both pointers and integers as arguments. Note that such calls are not
* necessarily pure functions -- they may have side effects.
*/
#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \
_zzq_request, _zzq_arg1, _zzq_arg2, \
_zzq_arg3, _zzq_arg4, _zzq_arg5) \
do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \
(_zzq_request), (_zzq_arg1), (_zzq_arg2), \
(_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \
_zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
(_zzq_request), (_zzq_arg1), (_zzq_arg2), \
(_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
#if defined(NVALGRIND)
/* Define NVALGRIND to completely remove the Valgrind magic sequence
from the compiled code (analogous to NDEBUG's effects on
assert()) */
#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
_zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
(_zzq_default)
#else /* ! NVALGRIND */
/* The following defines the magic code sequences which the JITter
spots and handles magically. Don't look too closely at them as
they will rot your brain.
The assembly code sequences for all architectures is in this one
file. This is because this file must be stand-alone, and we don't
want to have multiple files.
For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
value gets put in the return slot, so that everything works when
this is executed not under Valgrind. Args are passed in a memory
block, and so there's no intrinsic limit to the number that could
be passed, but it's currently five.
The macro args are:
_zzq_rlval result lvalue
_zzq_default default value (result returned when running on real CPU)
_zzq_request request code
_zzq_arg1..5 request params
The other two macros are used to support function wrapping, and are
a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
guest's NRADDR pseudo-register and whatever other information is
needed to safely run the call original from the wrapper: on
ppc64-linux, the R2 value at the divert point is also needed. This
information is abstracted into a user-visible type, OrigFn.
VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
guest, but guarantees that the branch instruction will not be
redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
complete inline asm, since it needs to be combined with more magic
inline asm stuff to be useful.
*/
/* ------------------------- x86-{linux,darwin} ---------------- */
#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
|| (defined(PLAT_x86_win32) && defined(__GNUC__))
typedef
struct {
unsigned int nraddr; /* where's the code? */
}
OrigFn;
#define __SPECIAL_INSTRUCTION_PREAMBLE \
"roll $3, %%edi ; roll $13, %%edi\n\t" \
"roll $29, %%edi ; roll $19, %%edi\n\t"
#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
_zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
__extension__ \
({volatile unsigned int _zzq_args[6]; \
volatile unsigned int _zzq_result; \
_zzq_args[0] = (unsigned int)(_zzq_request); \
_zzq_args[1] = (unsigned int)(_zzq_arg1); \
_zzq_args[2] = (unsigned int)(_zzq_arg2); \
_zzq_args[3] = (unsigned int)(_zzq_arg3); \
_zzq_args[4] = (unsigned int)(_zzq_arg4); \
_zzq_args[5] = (unsigned int)(_zzq_arg5); \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* %EDX = client_request ( %EAX ) */ \
"xchgl %%ebx,%%ebx" \
: "=d" (_zzq_result) \
: "a" (&_zzq_args[0]), "0" (_zzq_default) \
: "cc", "memory" \
); \
_zzq_result; \
})
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
volatile unsigned int __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* %EAX = guest_NRADDR */ \
"xchgl %%ecx,%%ecx" \
: "=a" (__addr) \
: \
: "cc", "memory" \
); \
_zzq_orig->nraddr = __addr; \
}
#define VALGRIND_CALL_NOREDIR_EAX \
__SPECIAL_INSTRUCTION_PREAMBLE \
/* call-noredir *%EAX */ \
"xchgl %%edx,%%edx\n\t"
#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */
/* ------------------------- x86-Win32 ------------------------- */
#if defined(PLAT_x86_win32) && !defined(__GNUC__)
typedef
struct {
unsigned int nraddr; /* where's the code? */
}
OrigFn;
#if defined(_MSC_VER)
#define __SPECIAL_INSTRUCTION_PREAMBLE \
__asm rol edi, 3 __asm rol edi, 13 \
__asm rol edi, 29 __asm rol edi, 19
#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
_zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \
(uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \
(uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \
(uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
static __inline uintptr_t
valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
uintptr_t _zzq_arg5)
{
volatile uintptr_t _zzq_args[6];
volatile unsigned int _zzq_result;
_zzq_args[0] = (uintptr_t)(_zzq_request);
_zzq_args[1] = (uintptr_t)(_zzq_arg1);
_zzq_args[2] = (uintptr_t)(_zzq_arg2);
_zzq_args[3] = (uintptr_t)(_zzq_arg3);
_zzq_args[4] = (uintptr_t)(_zzq_arg4);
_zzq_args[5] = (uintptr_t)(_zzq_arg5);
__asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
__SPECIAL_INSTRUCTION_PREAMBLE
/* %EDX = client_request ( %EAX ) */
__asm xchg ebx,ebx
__asm mov _zzq_result, edx
}
return _zzq_result;
}
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
volatile unsigned int __addr; \
__asm { __SPECIAL_INSTRUCTION_PREAMBLE \
/* %EAX = guest_NRADDR */ \
__asm xchg ecx,ecx \
__asm mov __addr, eax \
} \
_zzq_orig->nraddr = __addr; \
}
#define VALGRIND_CALL_NOREDIR_EAX ERROR
#else
#error Unsupported compiler.
#endif
#endif /* PLAT_x86_win32 */
/* ------------------------ amd64-{linux,darwin} --------------- */
#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
typedef
struct {
unsigned long long int nraddr; /* where's the code? */
}
OrigFn;
#define __SPECIAL_INSTRUCTION_PREAMBLE \
"rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
"rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
_zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
__extension__ \
({ volatile unsigned long long int _zzq_args[6]; \
volatile unsigned long long int _zzq_result; \
_zzq_args[0] = (unsigned long long int)(_zzq_request); \
_zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
_zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
_zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
_zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
_zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* %RDX = client_request ( %RAX ) */ \
"xchgq %%rbx,%%rbx" \
: "=d" (_zzq_result) \
: "a" (&_zzq_args[0]), "0" (_zzq_default) \
: "cc", "memory" \
); \
_zzq_result; \
})
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
volatile unsigned long long int __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* %RAX = guest_NRADDR */ \
"xchgq %%rcx,%%rcx" \
: "=a" (__addr) \
: \
: "cc", "memory" \
); \
_zzq_orig->nraddr = __addr; \
}
#define VALGRIND_CALL_NOREDIR_RAX \
__SPECIAL_INSTRUCTION_PREAMBLE \
/* call-noredir *%RAX */ \
"xchgq %%rdx,%%rdx\n\t"
#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
/* ------------------------ ppc32-linux ------------------------ */
#if defined(PLAT_ppc32_linux)
typedef
struct {
unsigned int nraddr; /* where's the code? */
}
OrigFn;
#define __SPECIAL_INSTRUCTION_PREAMBLE \
"rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
"rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
_zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
\
__extension__ \
({ unsigned int _zzq_args[6]; \
unsigned int _zzq_result; \
unsigned int* _zzq_ptr; \
_zzq_args[0] = (unsigned int)(_zzq_request); \
_zzq_args[1] = (unsigned int)(_zzq_arg1); \
_zzq_args[2] = (unsigned int)(_zzq_arg2); \
_zzq_args[3] = (unsigned int)(_zzq_arg3); \
_zzq_args[4] = (unsigned int)(_zzq_arg4); \
_zzq_args[5] = (unsigned int)(_zzq_arg5); \
_zzq_ptr = _zzq_args; \
__asm__ volatile("mr 3,%1\n\t" /*default*/ \
"mr 4,%2\n\t" /*ptr*/ \
__SPECIAL_INSTRUCTION_PREAMBLE \
/* %R3 = client_request ( %R4 ) */ \
"or 1,1,1\n\t" \
"mr %0,3" /*result*/ \
: "=b" (_zzq_result) \
: "b" (_zzq_default), "b" (_zzq_ptr) \
: "cc", "memory", "r3", "r4"); \
_zzq_result; \
})
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
unsigned int __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* %R3 = guest_NRADDR */ \
"or 2,2,2\n\t" \
"mr %0,3" \
: "=b" (__addr) \
: \
: "cc", "memory", "r3" \
); \
_zzq_orig->nraddr = __addr; \
}
#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
__SPECIAL_INSTRUCTION_PREAMBLE \
/* branch-and-link-to-noredir *%R11 */ \
"or 3,3,3\n\t"
#endif /* PLAT_ppc32_linux */
/* ------------------------ ppc64-linux ------------------------ */
#if defined(PLAT_ppc64_linux)
typedef
struct {
unsigned long long int nraddr; /* where's the code? */
unsigned long long int r2; /* what tocptr do we need? */
}
OrigFn;
#define __SPECIAL_INSTRUCTION_PREAMBLE \
"rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
"rotldi 0,0,61 ; rotldi 0,0,51\n\t"
#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
_zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
\
__extension__ \
({ unsigned long long int _zzq_args[6]; \
unsigned long long int _zzq_result; \
unsigned long long int* _zzq_ptr; \
_zzq_args[0] = (unsigned long long int)(_zzq_request); \
_zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
_zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
_zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
_zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
_zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
_zzq_ptr = _zzq_args; \
__asm__ volatile("mr 3,%1\n\t" /*default*/ \
"mr 4,%2\n\t" /*ptr*/ \
__SPECIAL_INSTRUCTION_PREAMBLE \
/* %R3 = client_request ( %R4 ) */ \
"or 1,1,1\n\t" \
"mr %0,3" /*result*/ \
: "=b" (_zzq_result) \
: "b" (_zzq_default), "b" (_zzq_ptr) \
: "cc", "memory", "r3", "r4"); \
_zzq_result; \
})
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
unsigned long long int __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* %R3 = guest_NRADDR */ \
"or 2,2,2\n\t" \
"mr %0,3" \
: "=b" (__addr) \
: \
: "cc", "memory", "r3" \
); \
_zzq_orig->nraddr = __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* %R3 = guest_NRADDR_GPR2 */ \
"or 4,4,4\n\t" \
"mr %0,3" \
: "=b" (__addr) \
: \
: "cc", "memory", "r3" \
); \
_zzq_orig->r2 = __addr; \
}
#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
__SPECIAL_INSTRUCTION_PREAMBLE \
/* branch-and-link-to-noredir *%R11 */ \
"or 3,3,3\n\t"
#endif /* PLAT_ppc64_linux */
/* ------------------------- arm-linux ------------------------- */
#if defined(PLAT_arm_linux)
typedef
struct {
unsigned int nraddr; /* where's the code? */
}
OrigFn;
#define __SPECIAL_INSTRUCTION_PREAMBLE \
"mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
"mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
_zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
\
__extension__ \
({volatile unsigned int _zzq_args[6]; \
volatile unsigned int _zzq_result; \
_zzq_args[0] = (unsigned int)(_zzq_request); \
_zzq_args[1] = (unsigned int)(_zzq_arg1); \
_zzq_args[2] = (unsigned int)(_zzq_arg2); \
_zzq_args[3] = (unsigned int)(_zzq_arg3); \
_zzq_args[4] = (unsigned int)(_zzq_arg4); \
_zzq_args[5] = (unsigned int)(_zzq_arg5); \
__asm__ volatile("mov r3, %1\n\t" /*default*/ \
"mov r4, %2\n\t" /*ptr*/ \
__SPECIAL_INSTRUCTION_PREAMBLE \
/* R3 = client_request ( R4 ) */ \
"orr r10, r10, r10\n\t" \
"mov %0, r3" /*result*/ \
: "=r" (_zzq_result) \
: "r" (_zzq_default), "r" (&_zzq_args[0]) \
: "cc","memory", "r3", "r4"); \
_zzq_result; \
})
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
unsigned int __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* R3 = guest_NRADDR */ \
"orr r11, r11, r11\n\t" \
"mov %0, r3" \
: "=r" (__addr) \
: \
: "cc", "memory", "r3" \
); \
_zzq_orig->nraddr = __addr; \
}
#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
__SPECIAL_INSTRUCTION_PREAMBLE \
/* branch-and-link-to-noredir *%R4 */ \
"orr r12, r12, r12\n\t"
#endif /* PLAT_arm_linux */
/* ------------------------ s390x-linux ------------------------ */
#if defined(PLAT_s390x_linux)
typedef
struct {
unsigned long long int nraddr; /* where's the code? */
}
OrigFn;
/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
* code. This detection is implemented in platform specific toIR.c
* (e.g. VEX/priv/guest_s390_decoder.c).
*/
#define __SPECIAL_INSTRUCTION_PREAMBLE \
"lr 15,15\n\t" \
"lr 1,1\n\t" \
"lr 2,2\n\t" \
"lr 3,3\n\t"
#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
#define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
_zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
__extension__ \
({volatile unsigned long long int _zzq_args[6]; \
volatile unsigned long long int _zzq_result; \
_zzq_args[0] = (unsigned long long int)(_zzq_request); \
_zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
_zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
_zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
_zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
_zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
__asm__ volatile(/* r2 = args */ \
"lgr 2,%1\n\t" \
/* r3 = default */ \
"lgr 3,%2\n\t" \
__SPECIAL_INSTRUCTION_PREAMBLE \
__CLIENT_REQUEST_CODE \
/* results = r3 */ \
"lgr %0, 3\n\t" \
: "=d" (_zzq_result) \
: "a" (&_zzq_args[0]), "0" (_zzq_default) \
: "cc", "2", "3", "memory" \
); \
_zzq_result; \
})
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
volatile unsigned long long int __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
__GET_NR_CONTEXT_CODE \
"lgr %0, 3\n\t" \
: "=a" (__addr) \
: \
: "cc", "3", "memory" \
); \
_zzq_orig->nraddr = __addr; \
}
#define VALGRIND_CALL_NOREDIR_R1 \
__SPECIAL_INSTRUCTION_PREAMBLE \
__CALL_NO_REDIR_CODE
#endif /* PLAT_s390x_linux */
/* ------------------------- mips32-linux ---------------- */
#if defined(PLAT_mips32_linux)
typedef
struct {
unsigned int nraddr; /* where's the code? */
}
OrigFn;
/* .word 0x342
* .word 0x742
* .word 0xC2
* .word 0x4C2*/
#define __SPECIAL_INSTRUCTION_PREAMBLE \
"srl $0, $0, 13\n\t" \
"srl $0, $0, 29\n\t" \
"srl $0, $0, 3\n\t" \
"srl $0, $0, 19\n\t"
#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
_zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
__extension__ \
({ volatile unsigned int _zzq_args[6]; \
volatile unsigned int _zzq_result; \
_zzq_args[0] = (unsigned int)(_zzq_request); \
_zzq_args[1] = (unsigned int)(_zzq_arg1); \
_zzq_args[2] = (unsigned int)(_zzq_arg2); \
_zzq_args[3] = (unsigned int)(_zzq_arg3); \
_zzq_args[4] = (unsigned int)(_zzq_arg4); \
_zzq_args[5] = (unsigned int)(_zzq_arg5); \
__asm__ volatile("move $11, %1\n\t" /*default*/ \
"move $12, %2\n\t" /*ptr*/ \
__SPECIAL_INSTRUCTION_PREAMBLE \
/* T3 = client_request ( T4 ) */ \
"or $13, $13, $13\n\t" \
"move %0, $11\n\t" /*result*/ \
: "=r" (_zzq_result) \
: "r" (_zzq_default), "r" (&_zzq_args[0]) \
: "cc","memory", "t3", "t4"); \
_zzq_result; \
})
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
volatile unsigned int __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* %t9 = guest_NRADDR */ \
"or $14, $14, $14\n\t" \
"move %0, $11" /*result*/ \
: "=r" (__addr) \
: \
: "cc", "memory" , "t3" \
); \
_zzq_orig->nraddr = __addr; \
}
#define VALGRIND_CALL_NOREDIR_T9 \
__SPECIAL_INSTRUCTION_PREAMBLE \
/* call-noredir *%t9 */ \
"or $15, $15, $15\n\t"
#endif /* PLAT_mips32_linux */
/* Insert assembly code for other platforms here... */
#endif /* NVALGRIND */
/* ------------------------------------------------------------------ */
/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
/* ugly. It's the least-worst tradeoff I can think of. */
/* ------------------------------------------------------------------ */
/* This section defines magic (a.k.a appalling-hack) macros for doing
guaranteed-no-redirection macros, so as to get from function
wrappers to the functions they are wrapping. The whole point is to
construct standard call sequences, but to do the call itself with a
special no-redirect call pseudo-instruction that the JIT
understands and handles specially. This section is long and
repetitious, and I can't see a way to make it shorter.
The naming scheme is as follows:
CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
'W' stands for "word" and 'v' for "void". Hence there are
different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
and for each, the possibility of returning a word-typed result, or
no result.
*/
/* Use these to write the name of your wrapper. NOTE: duplicates
VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts
the default behaviour equivalance class tag "0000" into the name.
See pub_tool_redir.h for details -- normally you don't need to
think about this, though. */
/* Use an extra level of macroisation so as to ensure the soname/fnname
args are fully macro-expanded before pasting them together. */
#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
/* Use this macro from within a wrapper function to collect the
context (address and possibly other info) of the original function.
Once you have that you can then use it in one of the CALL_FN_
macros. The type of the argument _lval is OrigFn. */
#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
/* Also provide end-user facilities for function replacement, rather
than wrapping. A replacement function differs from a wrapper in
that it has no way to get hold of the original function being
called, and hence no way to call onwards to it. In a replacement
function, VALGRIND_GET_ORIG_FN always returns zero. */
#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \
VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \
VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
/* Derivatives of the main macros below, for calling functions
returning void. */
#define CALL_FN_v_v(fnptr) \
do { volatile unsigned long _junk; \
CALL_FN_W_v(_junk,fnptr); } while (0)
#define CALL_FN_v_W(fnptr, arg1) \
do { volatile unsigned long _junk; \
CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
#define CALL_FN_v_WW(fnptr, arg1,arg2) \
do { volatile unsigned long _junk; \
CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
do { volatile unsigned long _junk; \
CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
do { volatile unsigned long _junk; \
CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
do { volatile unsigned long _junk; \
CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
do { volatile unsigned long _junk; \
CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
do { volatile unsigned long _junk; \
CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
/* ------------------------- x86-{linux,darwin} ---------------- */
#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
/* These regs are trashed by the hidden call. No need to mention eax
as gcc can already see that, plus causes gcc to bomb. */
#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
/* Macros to save and align the stack before making a function
call and restore it afterwards as gcc may not keep the stack
pointer aligned if it doesn't realise calls are being made
to other functions. */
#define VALGRIND_ALIGN_STACK \
"movl %%esp,%%edi\n\t" \
"andl $0xfffffff0,%%esp\n\t"
#define VALGRIND_RESTORE_STACK \
"movl %%edi,%%esp\n\t"
/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
long) == 4. */
#define CALL_FN_W_v(lval, orig) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[1]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_W(lval, orig, arg1) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[2]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"subl $12, %%esp\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"subl $8, %%esp\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[4]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"subl $4, %%esp\n\t" \
"pushl 12(%%eax)\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[5]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"pushl 16(%%eax)\n\t" \
"pushl 12(%%eax)\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[6]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"subl $12, %%esp\n\t" \
"pushl 20(%%eax)\n\t" \
"pushl 16(%%eax)\n\t" \
"pushl 12(%%eax)\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[7]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"subl $8, %%esp\n\t" \
"pushl 24(%%eax)\n\t" \
"pushl 20(%%eax)\n\t" \
"pushl 16(%%eax)\n\t" \
"pushl 12(%%eax)\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[8]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"subl $4, %%esp\n\t" \
"pushl 28(%%eax)\n\t" \
"pushl 24(%%eax)\n\t" \
"pushl 20(%%eax)\n\t" \
"pushl 16(%%eax)\n\t" \
"pushl 12(%%eax)\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[9]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"pushl 32(%%eax)\n\t" \
"pushl 28(%%eax)\n\t" \
"pushl 24(%%eax)\n\t" \
"pushl 20(%%eax)\n\t" \
"pushl 16(%%eax)\n\t" \
"pushl 12(%%eax)\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[10]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"subl $12, %%esp\n\t" \
"pushl 36(%%eax)\n\t" \
"pushl 32(%%eax)\n\t" \
"pushl 28(%%eax)\n\t" \
"pushl 24(%%eax)\n\t" \
"pushl 20(%%eax)\n\t" \
"pushl 16(%%eax)\n\t" \
"pushl 12(%%eax)\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9,arg10) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[11]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"subl $8, %%esp\n\t" \
"pushl 40(%%eax)\n\t" \
"pushl 36(%%eax)\n\t" \
"pushl 32(%%eax)\n\t" \
"pushl 28(%%eax)\n\t" \
"pushl 24(%%eax)\n\t" \
"pushl 20(%%eax)\n\t" \
"pushl 16(%%eax)\n\t" \
"pushl 12(%%eax)\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
arg6,arg7,arg8,arg9,arg10, \
arg11) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[12]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
_argvec[11] = (unsigned long)(arg11); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"subl $4, %%esp\n\t" \
"pushl 44(%%eax)\n\t" \
"pushl 40(%%eax)\n\t" \
"pushl 36(%%eax)\n\t" \
"pushl 32(%%eax)\n\t" \
"pushl 28(%%eax)\n\t" \
"pushl 24(%%eax)\n\t" \
"pushl 20(%%eax)\n\t" \
"pushl 16(%%eax)\n\t" \
"pushl 12(%%eax)\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
arg6,arg7,arg8,arg9,arg10, \
arg11,arg12) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[13]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
_argvec[11] = (unsigned long)(arg11); \
_argvec[12] = (unsigned long)(arg12); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"pushl 48(%%eax)\n\t" \
"pushl 44(%%eax)\n\t" \
"pushl 40(%%eax)\n\t" \
"pushl 36(%%eax)\n\t" \
"pushl 32(%%eax)\n\t" \
"pushl 28(%%eax)\n\t" \
"pushl 24(%%eax)\n\t" \
"pushl 20(%%eax)\n\t" \
"pushl 16(%%eax)\n\t" \
"pushl 12(%%eax)\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#endif /* PLAT_x86_linux || PLAT_x86_darwin */
/* ------------------------ amd64-{linux,darwin} --------------- */
#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
/* These regs are trashed by the hidden call. */
#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
"rdi", "r8", "r9", "r10", "r11"
/* This is all pretty complex. It's so as to make stack unwinding
work reliably. See bug 243270. The basic problem is the sub and
add of 128 of %rsp in all of the following macros. If gcc believes
the CFA is in %rsp, then unwinding may fail, because what's at the
CFA is not what gcc "expected" when it constructs the CFIs for the
places where the macros are instantiated.
But we can't just add a CFI annotation to increase the CFA offset
by 128, to match the sub of 128 from %rsp, because we don't know
whether gcc has chosen %rsp as the CFA at that point, or whether it
has chosen some other register (eg, %rbp). In the latter case,
adding a CFI annotation to change the CFA offset is simply wrong.
So the solution is to get hold of the CFA using
__builtin_dwarf_cfa(), put it in a known register, and add a
CFI annotation to say what the register is. We choose %rbp for
this (perhaps perversely), because:
(1) %rbp is already subject to unwinding. If a new register was
chosen then the unwinder would have to unwind it in all stack
traces, which is expensive, and
(2) %rbp is already subject to precise exception updates in the
JIT. If a new register was chosen, we'd have to have precise
exceptions for it too, which reduces performance of the
generated code.
However .. one extra complication. We can't just whack the result
of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
list of trashed registers at the end of the inline assembly
fragments; gcc won't allow %rbp to appear in that list. Hence
instead we need to stash %rbp in %r15 for the duration of the asm,
and say that %r15 is trashed instead. gcc seems happy to go with
that.
Oh .. and this all needs to be conditionalised so that it is
unchanged from before this commit, when compiled with older gccs
that don't support __builtin_dwarf_cfa. Furthermore, since
this header file is freestanding, it has to be independent of
config.h, and so the following conditionalisation cannot depend on
configure time checks.
Although it's not clear from
'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
this expression excludes Darwin.
.cfi directives in Darwin assembly appear to be completely
different and I haven't investigated how they work.
For even more entertainment value, note we have to use the
completely undocumented __builtin_dwarf_cfa(), which appears to
really compute the CFA, whereas __builtin_frame_address(0) claims
to but actually doesn't. See
https://bugs.kde.org/show_bug.cgi?id=243270#c47
*/
#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
# define __FRAME_POINTER \
,"r"(__builtin_dwarf_cfa())
# define VALGRIND_CFI_PROLOGUE \
"movq %%rbp, %%r15\n\t" \
"movq %2, %%rbp\n\t" \
".cfi_remember_state\n\t" \
".cfi_def_cfa rbp, 0\n\t"
# define VALGRIND_CFI_EPILOGUE \
"movq %%r15, %%rbp\n\t" \
".cfi_restore_state\n\t"
#else
# define __FRAME_POINTER
# define VALGRIND_CFI_PROLOGUE
# define VALGRIND_CFI_EPILOGUE
#endif
/* Macros to save and align the stack before making a function
call and restore it afterwards as gcc may not keep the stack
pointer aligned if it doesn't realise calls are being made
to other functions. */
#define VALGRIND_ALIGN_STACK \
"movq %%rsp,%%r14\n\t" \
"andq $0xfffffffffffffff0,%%rsp\n\t"
#define VALGRIND_RESTORE_STACK \
"movq %%r14,%%rsp\n\t"
/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
long) == 8. */
/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
macros. In order not to trash the stack redzone, we need to drop
%rsp by 128 before the hidden call, and restore afterwards. The
nastyness is that it is only by luck that the stack still appears
to be unwindable during the hidden call - since then the behaviour
of any routine using this macro does not match what the CFI data
says. Sigh.
Why is this important? Imagine that a wrapper has a stack
allocated local, and passes to the hidden call, a pointer to it.
Because gcc does not know about the hidden call, it may allocate
that local in the redzone. Unfortunately the hidden call may then
trash it before it comes to use it. So we must step clear of the
redzone, for the duration of the hidden call, to make it safe.
Probably the same problem afflicts the other redzone-style ABIs too
(ppc64-linux); but for those, the stack is
self describing (none of this CFI nonsense) so at least messing
with the stack pointer doesn't give a danger of non-unwindable
stack. */
#define CALL_FN_W_v(lval, orig) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[1]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
VALGRIND_ALIGN_STACK \
"subq $128,%%rsp\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
VALGRIND_RESTORE_STACK \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_W(lval, orig, arg1) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[2]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
VALGRIND_ALIGN_STACK \
"subq $128,%%rsp\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
VALGRIND_RESTORE_STACK \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
VALGRIND_ALIGN_STACK \
"subq $128,%%rsp\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
VALGRIND_RESTORE_STACK \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[4]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
VALGRIND_ALIGN_STACK \
"subq $128,%%rsp\n\t" \
"movq 24(%%rax), %%rdx\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
VALGRIND_RESTORE_STACK \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[5]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
VALGRIND_ALIGN_STACK \
"subq $128,%%rsp\n\t" \
"movq 32(%%rax), %%rcx\n\t" \
"movq 24(%%rax), %%rdx\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
VALGRIND_RESTORE_STACK \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[6]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
VALGRIND_ALIGN_STACK \
"subq $128,%%rsp\n\t" \
"movq 40(%%rax), %%r8\n\t" \
"movq 32(%%rax), %%rcx\n\t" \
"movq 24(%%rax), %%rdx\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
VALGRIND_RESTORE_STACK \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[7]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
VALGRIND_ALIGN_STACK \
"subq $128,%%rsp\n\t" \
"movq 48(%%rax), %%r9\n\t" \
"movq 40(%%rax), %%r8\n\t" \
"movq 32(%%rax), %%rcx\n\t" \
"movq 24(%%rax), %%rdx\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
VALGRIND_RESTORE_STACK \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[8]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
VALGRIND_ALIGN_STACK \
"subq $136,%%rsp\n\t" \
"pushq 56(%%rax)\n\t" \
"movq 48(%%rax), %%r9\n\t" \
"movq 40(%%rax), %%r8\n\t" \
"movq 32(%%rax), %%rcx\n\t" \
"movq 24(%%rax), %%rdx\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
VALGRIND_RESTORE_STACK \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[9]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
VALGRIND_ALIGN_STACK \
"subq $128,%%rsp\n\t" \
"pushq 64(%%rax)\n\t" \
"pushq 56(%%rax)\n\t" \
"movq 48(%%rax), %%r9\n\t" \
"movq 40(%%rax), %%r8\n\t" \
"movq 32(%%rax), %%rcx\n\t" \
"movq 24(%%rax), %%rdx\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
VALGRIND_RESTORE_STACK \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[10]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
VALGRIND_ALIGN_STACK \
"subq $136,%%rsp\n\t" \
"pushq 72(%%rax)\n\t" \
"pushq 64(%%rax)\n\t" \
"pushq 56(%%rax)\n\t" \
"movq 48(%%rax), %%r9\n\t" \
"movq 40(%%rax), %%r8\n\t" \
"movq 32(%%rax), %%rcx\n\t" \
"movq 24(%%rax), %%rdx\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
VALGRIND_RESTORE_STACK \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9,arg10) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[11]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
VALGRIND_ALIGN_STACK \
"subq $128,%%rsp\n\t" \
"pushq 80(%%rax)\n\t" \
"pushq 72(%%rax)\n\t" \
"pushq 64(%%rax)\n\t" \
"pushq 56(%%rax)\n\t" \
"movq 48(%%rax), %%r9\n\t" \
"movq 40(%%rax), %%r8\n\t" \
"movq 32(%%rax), %%rcx\n\t" \
"movq 24(%%rax), %%rdx\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
VALGRIND_RESTORE_STACK \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9,arg10,arg11) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[12]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
_argvec[11] = (unsigned long)(arg11); \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
VALGRIND_ALIGN_STACK \
"subq $136,%%rsp\n\t" \
"pushq 88(%%rax)\n\t" \
"pushq 80(%%rax)\n\t" \
"pushq 72(%%rax)\n\t" \
"pushq 64(%%rax)\n\t" \
"pushq 56(%%rax)\n\t" \
"movq 48(%%rax), %%r9\n\t" \
"movq 40(%%rax), %%r8\n\t" \
"movq 32(%%rax), %%rcx\n\t" \
"movq 24(%%rax), %%rdx\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
VALGRIND_RESTORE_STACK \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9,arg10,arg11,arg12) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[13]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
_argvec[11] = (unsigned long)(arg11); \
_argvec[12] = (unsigned long)(arg12); \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
VALGRIND_ALIGN_STACK \
"subq $128,%%rsp\n\t" \
"pushq 96(%%rax)\n\t" \
"pushq 88(%%rax)\n\t" \
"pushq 80(%%rax)\n\t" \
"pushq 72(%%rax)\n\t" \
"pushq 64(%%rax)\n\t" \
"pushq 56(%%rax)\n\t" \
"movq 48(%%rax), %%r9\n\t" \
"movq 40(%%rax), %%r8\n\t" \
"movq 32(%%rax), %%rcx\n\t" \
"movq 24(%%rax), %%rdx\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
VALGRIND_RESTORE_STACK \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
/* ------------------------ ppc32-linux ------------------------ */
#if defined(PLAT_ppc32_linux)
/* This is useful for finding out about the on-stack stuff:
extern int f9 ( int,int,int,int,int,int,int,int,int );
extern int f10 ( int,int,int,int,int,int,int,int,int,int );
extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
int g9 ( void ) {
return f9(11,22,33,44,55,66,77,88,99);
}
int g10 ( void ) {
return f10(11,22,33,44,55,66,77,88,99,110);
}
int g11 ( void ) {
return f11(11,22,33,44,55,66,77,88,99,110,121);
}
int g12 ( void ) {
return f12(11,22,33,44,55,66,77,88,99,110,121,132);
}
*/
/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
/* These regs are trashed by the hidden call. */
#define __CALLER_SAVED_REGS \
"lr", "ctr", "xer", \
"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
"r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
"r11", "r12", "r13"
/* Macros to save and align the stack before making a function
call and restore it afterwards as gcc may not keep the stack
pointer aligned if it doesn't realise calls are being made
to other functions. */
#define VALGRIND_ALIGN_STACK \
"mr 28,1\n\t" \
"rlwinm 1,1,0,0,27\n\t"
#define VALGRIND_RESTORE_STACK \
"mr 1,28\n\t"
/* These CALL_FN_ macros assume that on ppc32-linux,
sizeof(unsigned long) == 4. */
#define CALL_FN_W_v(lval, orig) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[1]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_W(lval, orig, arg1) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[2]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[4]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
"lwz 5,12(11)\n\t" \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[5]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
"lwz 5,12(11)\n\t" \
"lwz 6,16(11)\n\t" /* arg4->r6 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[6]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
"lwz 5,12(11)\n\t" \
"lwz 6,16(11)\n\t" /* arg4->r6 */ \
"lwz 7,20(11)\n\t" \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[7]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
"lwz 5,12(11)\n\t" \
"lwz 6,16(11)\n\t" /* arg4->r6 */ \
"lwz 7,20(11)\n\t" \
"lwz 8,24(11)\n\t" \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[8]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
_argvec[7] = (unsigned long)arg7; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
"lwz 5,12(11)\n\t" \
"lwz 6,16(11)\n\t" /* arg4->r6 */ \
"lwz 7,20(11)\n\t" \
"lwz 8,24(11)\n\t" \
"lwz 9,28(11)\n\t" \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[9]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
_argvec[7] = (unsigned long)arg7; \
_argvec[8] = (unsigned long)arg8; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
"lwz 5,12(11)\n\t" \
"lwz 6,16(11)\n\t" /* arg4->r6 */ \
"lwz 7,20(11)\n\t" \
"lwz 8,24(11)\n\t" \
"lwz 9,28(11)\n\t" \
"lwz 10,32(11)\n\t" /* arg8->r10 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[10]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
_argvec[7] = (unsigned long)arg7; \
_argvec[8] = (unsigned long)arg8; \
_argvec[9] = (unsigned long)arg9; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"addi 1,1,-16\n\t" \
/* arg9 */ \
"lwz 3,36(11)\n\t" \
"stw 3,8(1)\n\t" \
/* args1-8 */ \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
"lwz 5,12(11)\n\t" \
"lwz 6,16(11)\n\t" /* arg4->r6 */ \
"lwz 7,20(11)\n\t" \
"lwz 8,24(11)\n\t" \
"lwz 9,28(11)\n\t" \
"lwz 10,32(11)\n\t" /* arg8->r10 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9,arg10) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[11]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
_argvec[7] = (unsigned long)arg7; \
_argvec[8] = (unsigned long)arg8; \
_argvec[9] = (unsigned long)arg9; \
_argvec[10] = (unsigned long)arg10; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"addi 1,1,-16\n\t" \
/* arg10 */ \
"lwz 3,40(11)\n\t" \
"stw 3,12(1)\n\t" \
/* arg9 */ \
"lwz 3,36(11)\n\t" \
"stw 3,8(1)\n\t" \
/* args1-8 */ \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
"lwz 5,12(11)\n\t" \
"lwz 6,16(11)\n\t" /* arg4->r6 */ \
"lwz 7,20(11)\n\t" \
"lwz 8,24(11)\n\t" \
"lwz 9,28(11)\n\t" \
"lwz 10,32(11)\n\t" /* arg8->r10 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9,arg10,arg11) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[12]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
_argvec[7] = (unsigned long)arg7; \
_argvec[8] = (unsigned long)arg8; \
_argvec[9] = (unsigned long)arg9; \
_argvec[10] = (unsigned long)arg10; \
_argvec[11] = (unsigned long)arg11; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"addi 1,1,-32\n\t" \
/* arg11 */ \
"lwz 3,44(11)\n\t" \
"stw 3,16(1)\n\t" \
/* arg10 */ \
"lwz 3,40(11)\n\t" \
"stw 3,12(1)\n\t" \
/* arg9 */ \
"lwz 3,36(11)\n\t" \
"stw 3,8(1)\n\t" \
/* args1-8 */ \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
"lwz 5,12(11)\n\t" \
"lwz 6,16(11)\n\t" /* arg4->r6 */ \
"lwz 7,20(11)\n\t" \
"lwz 8,24(11)\n\t" \
"lwz 9,28(11)\n\t" \
"lwz 10,32(11)\n\t" /* arg8->r10 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9,arg10,arg11,arg12) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[13]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
_argvec[7] = (unsigned long)arg7; \
_argvec[8] = (unsigned long)arg8; \
_argvec[9] = (unsigned long)arg9; \
_argvec[10] = (unsigned long)arg10; \
_argvec[11] = (unsigned long)arg11; \
_argvec[12] = (unsigned long)arg12; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"addi 1,1,-32\n\t" \
/* arg12 */ \
"lwz 3,48(11)\n\t" \
"stw 3,20(1)\n\t" \
/* arg11 */ \
"lwz 3,44(11)\n\t" \
"stw 3,16(1)\n\t" \
/* arg10 */ \
"lwz 3,40(11)\n\t" \
"stw 3,12(1)\n\t" \
/* arg9 */ \
"lwz 3,36(11)\n\t" \
"stw 3,8(1)\n\t" \
/* args1-8 */ \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
"lwz 5,12(11)\n\t" \
"lwz 6,16(11)\n\t" /* arg4->r6 */ \
"lwz 7,20(11)\n\t" \
"lwz 8,24(11)\n\t" \
"lwz 9,28(11)\n\t" \
"lwz 10,32(11)\n\t" /* arg8->r10 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#endif /* PLAT_ppc32_linux */
/* ------------------------ ppc64-linux ------------------------ */
#if defined(PLAT_ppc64_linux)
/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
/* These regs are trashed by the hidden call. */
#define __CALLER_SAVED_REGS \
"lr", "ctr", "xer", \
"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
"r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
"r11", "r12", "r13"
/* Macros to save and align the stack before making a function
call and restore it afterwards as gcc may not keep the stack
pointer aligned if it doesn't realise calls are being made
to other functions. */
#define VALGRIND_ALIGN_STACK \
"mr 28,1\n\t" \
"rldicr 1,1,0,59\n\t"
#define VALGRIND_RESTORE_STACK \
"mr 1,28\n\t"
/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
long) == 8. */
#define CALL_FN_W_v(lval, orig) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3+0]; \
volatile unsigned long _res; \
/* _argvec[0] holds current r2 across the call */ \
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
"ld 11, 0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_W(lval, orig, arg1) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3+1]; \
volatile unsigned long _res; \
/* _argvec[0] holds current r2 across the call */ \
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
"ld 3, 8(11)\n\t" /* arg1->r3 */ \
"ld 11, 0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3+2]; \
volatile unsigned long _res; \
/* _argvec[0] holds current r2 across the call */ \
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
_argvec[2+2] = (unsigned long)arg2; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
"ld 3, 8(11)\n\t" /* arg1->r3 */ \
"ld 4, 16(11)\n\t" /* arg2->r4 */ \
"ld 11, 0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3+3]; \
volatile unsigned long _res; \
/* _argvec[0] holds current r2 across the call */ \
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
_argvec[2+2] = (unsigned long)arg2; \
_argvec[2+3] = (unsigned long)arg3; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
"ld 3, 8(11)\n\t" /* arg1->r3 */ \
"ld 4, 16(11)\n\t" /* arg2->r4 */ \
"ld 5, 24(11)\n\t" /* arg3->r5 */ \
"ld 11, 0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3+4]; \
volatile unsigned long _res; \
/* _argvec[0] holds current r2 across the call */ \
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
_argvec[2+2] = (unsigned long)arg2; \
_argvec[2+3] = (unsigned long)arg3; \
_argvec[2+4] = (unsigned long)arg4; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
"ld 3, 8(11)\n\t" /* arg1->r3 */ \
"ld 4, 16(11)\n\t" /* arg2->r4 */ \
"ld 5, 24(11)\n\t" /* arg3->r5 */ \
"ld 6, 32(11)\n\t" /* arg4->r6 */ \
"ld 11, 0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3+5]; \
volatile unsigned long _res; \
/* _argvec[0] holds current r2 across the call */ \
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
_argvec[2+2] = (unsigned long)arg2; \
_argvec[2+3] = (unsigned long)arg3; \
_argvec[2+4] = (unsigned long)arg4; \
_argvec[2+5] = (unsigned long)arg5; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
"ld 3, 8(11)\n\t" /* arg1->r3 */ \
"ld 4, 16(11)\n\t" /* arg2->r4 */ \
"ld 5, 24(11)\n\t" /* arg3->r5 */ \
"ld 6, 32(11)\n\t" /* arg4->r6 */ \
"ld 7, 40(11)\n\t" /* arg5->r7 */ \
"ld 11, 0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3+6]; \
volatile unsigned long _res; \
/* _argvec[0] holds current r2 across the call */ \
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
_argvec[2+2] = (unsigned long)arg2; \
_argvec[2+3] = (unsigned long)arg3; \
_argvec[2+4] = (unsigned long)arg4; \
_argvec[2+5] = (unsigned long)arg5; \
_argvec[2+6] = (unsigned long)arg6; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
"ld 3, 8(11)\n\t" /* arg1->r3 */ \
"ld 4, 16(11)\n\t" /* arg2->r4 */ \
"ld 5, 24(11)\n\t" /* arg3->r5 */ \
"ld 6, 32(11)\n\t" /* arg4->r6 */ \
"ld 7, 40(11)\n\t" /* arg5->r7 */ \
"ld 8, 48(11)\n\t" /* arg6->r8 */ \
"ld 11, 0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3+7]; \
volatile unsigned long _res; \
/* _argvec[0] holds current r2 across the call */ \
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
_argvec[2+2] = (unsigned long)arg2; \
_argvec[2+3] = (unsigned long)arg3; \
_argvec[2+4] = (unsigned long)arg4; \
_argvec[2+5] = (unsigned long)arg5; \
_argvec[2+6] = (unsigned long)arg6; \
_argvec[2+7] = (unsigned long)arg7; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
"ld 3, 8(11)\n\t" /* arg1->r3 */ \
"ld 4, 16(11)\n\t" /* arg2->r4 */ \
"ld 5, 24(11)\n\t" /* arg3->r5 */ \
"ld 6, 32(11)\n\t" /* arg4->r6 */ \
"ld 7, 40(11)\n\t" /* arg5->r7 */ \
"ld 8, 48(11)\n\t" /* arg6->r8 */ \
"ld 9, 56(11)\n\t" /* arg7->r9 */ \
"ld 11, 0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3+8]; \
volatile unsigned long _res; \
/* _argvec[0] holds current r2 across the call */ \
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
_argvec[2+2] = (unsigned long)arg2; \
_argvec[2+3] = (unsigned long)arg3; \
_argvec[2+4] = (unsigned long)arg4; \
_argvec[2+5] = (unsigned long)arg5; \
_argvec[2+6] = (unsigned long)arg6; \
_argvec[2+7] = (unsigned long)arg7; \
_argvec[2+8] = (unsigned long)arg8; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
"ld 3, 8(11)\n\t" /* arg1->r3 */ \
"ld 4, 16(11)\n\t" /* arg2->r4 */ \
"ld 5, 24(11)\n\t" /* arg3->r5 */ \
"ld 6, 32(11)\n\t" /* arg4->r6 */ \
"ld 7, 40(11)\n\t" /* arg5->r7 */ \
"ld 8, 48(11)\n\t" /* arg6->r8 */ \
"ld 9, 56(11)\n\t" /* arg7->r9 */ \
"ld 10, 64(11)\n\t" /* arg8->r10 */ \
"ld 11, 0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3+9]; \
volatile unsigned long _res; \
/* _argvec[0] holds current r2 across the call */ \
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
_argvec[2+2] = (unsigned long)arg2; \
_argvec[2+3] = (unsigned long)arg3; \
_argvec[2+4] = (unsigned long)arg4; \
_argvec[2+5] = (unsigned long)arg5; \
_argvec[2+6] = (unsigned long)arg6; \
_argvec[2+7] = (unsigned long)arg7; \
_argvec[2+8] = (unsigned long)arg8; \
_argvec[2+9] = (unsigned long)arg9; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
"addi 1,1,-128\n\t" /* expand stack frame */ \
/* arg9 */ \
"ld 3,72(11)\n\t" \
"std 3,112(1)\n\t" \
/* args1-8 */ \
"ld 3, 8(11)\n\t" /* arg1->r3 */ \
"ld 4, 16(11)\n\t" /* arg2->r4 */ \
"ld 5, 24(11)\n\t" /* arg3->r5 */ \
"ld 6, 32(11)\n\t" /* arg4->r6 */ \
"ld 7, 40(11)\n\t" /* arg5->r7 */ \
"ld 8, 48(11)\n\t" /* arg6->r8 */ \
"ld 9, 56(11)\n\t" /* arg7->r9 */ \
"ld 10, 64(11)\n\t" /* arg8->r10 */ \
"ld 11, 0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9,arg10) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3+10]; \
volatile unsigned long _res; \
/* _argvec[0] holds current r2 across the call */ \
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
_argvec[2+2] = (unsigned long)arg2; \
_argvec[2+3] = (unsigned long)arg3; \
_argvec[2+4] = (unsigned long)arg4; \
_argvec[2+5] = (unsigned long)arg5; \
_argvec[2+6] = (unsigned long)arg6; \
_argvec[2+7] = (unsigned long)arg7; \
_argvec[2+8] = (unsigned long)arg8; \
_argvec[2+9] = (unsigned long)arg9; \
_argvec[2+10] = (unsigned long)arg10; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
"addi 1,1,-128\n\t" /* expand stack frame */ \
/* arg10 */ \
"ld 3,80(11)\n\t" \
"std 3,120(1)\n\t" \
/* arg9 */ \
"ld 3,72(11)\n\t" \
"std 3,112(1)\n\t" \
/* args1-8 */ \
"ld 3, 8(11)\n\t" /* arg1->r3 */ \
"ld 4, 16(11)\n\t" /* arg2->r4 */ \
"ld 5, 24(11)\n\t" /* arg3->r5 */ \
"ld 6, 32(11)\n\t" /* arg4->r6 */ \
"ld 7, 40(11)\n\t" /* arg5->r7 */ \
"ld 8, 48(11)\n\t" /* arg6->r8 */ \
"ld 9, 56(11)\n\t" /* arg7->r9 */ \
"ld 10, 64(11)\n\t" /* arg8->r10 */ \
"ld 11, 0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9,arg10,arg11) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3+11]; \
volatile unsigned long _res; \
/* _argvec[0] holds current r2 across the call */ \
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
_argvec[2+2] = (unsigned long)arg2; \
_argvec[2+3] = (unsigned long)arg3; \
_argvec[2+4] = (unsigned long)arg4; \
_argvec[2+5] = (unsigned long)arg5; \
_argvec[2+6] = (unsigned long)arg6; \
_argvec[2+7] = (unsigned long)arg7; \
_argvec[2+8] = (unsigned long)arg8; \
_argvec[2+9] = (unsigned long)arg9; \
_argvec[2+10] = (unsigned long)arg10; \
_argvec[2+11] = (unsigned long)arg11; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
"addi 1,1,-144\n\t" /* expand stack frame */ \
/* arg11 */ \
"ld 3,88(11)\n\t" \
"std 3,128(1)\n\t" \
/* arg10 */ \
"ld 3,80(11)\n\t" \
"std 3,120(1)\n\t" \
/* arg9 */ \
"ld 3,72(11)\n\t" \
"std 3,112(1)\n\t" \
/* args1-8 */ \
"ld 3, 8(11)\n\t" /* arg1->r3 */ \
"ld 4, 16(11)\n\t" /* arg2->r4 */ \
"ld 5, 24(11)\n\t" /* arg3->r5 */ \
"ld 6, 32(11)\n\t" /* arg4->r6 */ \
"ld 7, 40(11)\n\t" /* arg5->r7 */ \
"ld 8, 48(11)\n\t" /* arg6->r8 */ \
"ld 9, 56(11)\n\t" /* arg7->r9 */ \
"ld 10, 64(11)\n\t" /* arg8->r10 */ \
"ld 11, 0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9,arg10,arg11,arg12) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3+12]; \
volatile unsigned long _res; \
/* _argvec[0] holds current r2 across the call */ \
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
_argvec[2+2] = (unsigned long)arg2; \
_argvec[2+3] = (unsigned long)arg3; \
_argvec[2+4] = (unsigned long)arg4; \
_argvec[2+5] = (unsigned long)arg5; \
_argvec[2+6] = (unsigned long)arg6; \
_argvec[2+7] = (unsigned long)arg7; \
_argvec[2+8] = (unsigned long)arg8; \
_argvec[2+9] = (unsigned long)arg9; \
_argvec[2+10] = (unsigned long)arg10; \
_argvec[2+11] = (unsigned long)arg11; \
_argvec[2+12] = (unsigned long)arg12; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
"addi 1,1,-144\n\t" /* expand stack frame */ \
/* arg12 */ \
"ld 3,96(11)\n\t" \
"std 3,136(1)\n\t" \
/* arg11 */ \
"ld 3,88(11)\n\t" \
"std 3,128(1)\n\t" \
/* arg10 */ \
"ld 3,80(11)\n\t" \
"std 3,120(1)\n\t" \
/* arg9 */ \
"ld 3,72(11)\n\t" \
"std 3,112(1)\n\t" \
/* args1-8 */ \
"ld 3, 8(11)\n\t" /* arg1->r3 */ \
"ld 4, 16(11)\n\t" /* arg2->r4 */ \
"ld 5, 24(11)\n\t" /* arg3->r5 */ \
"ld 6, 32(11)\n\t" /* arg4->r6 */ \
"ld 7, 40(11)\n\t" /* arg5->r7 */ \
"ld 8, 48(11)\n\t" /* arg6->r8 */ \
"ld 9, 56(11)\n\t" /* arg7->r9 */ \
"ld 10, 64(11)\n\t" /* arg8->r10 */ \
"ld 11, 0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#endif /* PLAT_ppc64_linux */
/* ------------------------- arm-linux ------------------------- */
#if defined(PLAT_arm_linux)
/* These regs are trashed by the hidden call. */
#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
/* Macros to save and align the stack before making a function
call and restore it afterwards as gcc may not keep the stack
pointer aligned if it doesn't realise calls are being made
to other functions. */
/* This is a bit tricky. We store the original stack pointer in r10
as it is callee-saves. gcc doesn't allow the use of r11 for some
reason. Also, we can't directly "bic" the stack pointer in thumb
mode since r13 isn't an allowed register number in that context.
So use r4 as a temporary, since that is about to get trashed
anyway, just after each use of this macro. Side effect is we need
to be very careful about any future changes, since
VALGRIND_ALIGN_STACK simply assumes r4 is usable. */
#define VALGRIND_ALIGN_STACK \
"mov r10, sp\n\t" \
"mov r4, sp\n\t" \
"bic r4, r4, #7\n\t" \
"mov sp, r4\n\t"
#define VALGRIND_RESTORE_STACK \
"mov sp, r10\n\t"
/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
long) == 4. */
#define CALL_FN_W_v(lval, orig) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[1]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"ldr r4, [%1] \n\t" /* target->r4 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
VALGRIND_RESTORE_STACK \
"mov %0, r0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_W(lval, orig, arg1) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[2]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"ldr r0, [%1, #4] \n\t" \
"ldr r4, [%1] \n\t" /* target->r4 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
VALGRIND_RESTORE_STACK \
"mov %0, r0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"ldr r0, [%1, #4] \n\t" \
"ldr r1, [%1, #8] \n\t" \
"ldr r4, [%1] \n\t" /* target->r4 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
VALGRIND_RESTORE_STACK \
"mov %0, r0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[4]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"ldr r0, [%1, #4] \n\t" \
"ldr r1, [%1, #8] \n\t" \
"ldr r2, [%1, #12] \n\t" \
"ldr r4, [%1] \n\t" /* target->r4 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
VALGRIND_RESTORE_STACK \
"mov %0, r0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[5]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"ldr r0, [%1, #4] \n\t" \
"ldr r1, [%1, #8] \n\t" \
"ldr r2, [%1, #12] \n\t" \
"ldr r3, [%1, #16] \n\t" \
"ldr r4, [%1] \n\t" /* target->r4 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
VALGRIND_RESTORE_STACK \
"mov %0, r0" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[6]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"sub sp, sp, #4 \n\t" \
"ldr r0, [%1, #20] \n\t" \
"push {r0} \n\t" \
"ldr r0, [%1, #4] \n\t" \
"ldr r1, [%1, #8] \n\t" \
"ldr r2, [%1, #12] \n\t" \
"ldr r3, [%1, #16] \n\t" \
"ldr r4, [%1] \n\t" /* target->r4 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
VALGRIND_RESTORE_STACK \
"mov %0, r0" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[7]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"ldr r0, [%1, #20] \n\t" \
"ldr r1, [%1, #24] \n\t" \
"push {r0, r1} \n\t" \
"ldr r0, [%1, #4] \n\t" \
"ldr r1, [%1, #8] \n\t" \
"ldr r2, [%1, #12] \n\t" \
"ldr r3, [%1, #16] \n\t" \
"ldr r4, [%1] \n\t" /* target->r4 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
VALGRIND_RESTORE_STACK \
"mov %0, r0" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[8]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"sub sp, sp, #4 \n\t" \
"ldr r0, [%1, #20] \n\t" \
"ldr r1, [%1, #24] \n\t" \
"ldr r2, [%1, #28] \n\t" \
"push {r0, r1, r2} \n\t" \
"ldr r0, [%1, #4] \n\t" \
"ldr r1, [%1, #8] \n\t" \
"ldr r2, [%1, #12] \n\t" \
"ldr r3, [%1, #16] \n\t" \
"ldr r4, [%1] \n\t" /* target->r4 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
VALGRIND_RESTORE_STACK \
"mov %0, r0" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[9]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"ldr r0, [%1, #20] \n\t" \
"ldr r1, [%1, #24] \n\t" \
"ldr r2, [%1, #28] \n\t" \
"ldr r3, [%1, #32] \n\t" \
"push {r0, r1, r2, r3} \n\t" \
"ldr r0, [%1, #4] \n\t" \
"ldr r1, [%1, #8] \n\t" \
"ldr r2, [%1, #12] \n\t" \
"ldr r3, [%1, #16] \n\t" \
"ldr r4, [%1] \n\t" /* target->r4 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
VALGRIND_RESTORE_STACK \
"mov %0, r0" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[10]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"sub sp, sp, #4 \n\t" \
"ldr r0, [%1, #20] \n\t" \
"ldr r1, [%1, #24] \n\t" \
"ldr r2, [%1, #28] \n\t" \
"ldr r3, [%1, #32] \n\t" \
"ldr r4, [%1, #36] \n\t" \
"push {r0, r1, r2, r3, r4} \n\t" \
"ldr r0, [%1, #4] \n\t" \
"ldr r1, [%1, #8] \n\t" \
"ldr r2, [%1, #12] \n\t" \
"ldr r3, [%1, #16] \n\t" \
"ldr r4, [%1] \n\t" /* target->r4 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
VALGRIND_RESTORE_STACK \
"mov %0, r0" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9,arg10) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[11]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"ldr r0, [%1, #40] \n\t" \
"push {r0} \n\t" \
"ldr r0, [%1, #20] \n\t" \
"ldr r1, [%1, #24] \n\t" \
"ldr r2, [%1, #28] \n\t" \
"ldr r3, [%1, #32] \n\t" \
"ldr r4, [%1, #36] \n\t" \
"push {r0, r1, r2, r3, r4} \n\t" \
"ldr r0, [%1, #4] \n\t" \
"ldr r1, [%1, #8] \n\t" \
"ldr r2, [%1, #12] \n\t" \
"ldr r3, [%1, #16] \n\t" \
"ldr r4, [%1] \n\t" /* target->r4 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
VALGRIND_RESTORE_STACK \
"mov %0, r0" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
arg6,arg7,arg8,arg9,arg10, \
arg11) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[12]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
_argvec[11] = (unsigned long)(arg11); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"sub sp, sp, #4 \n\t" \
"ldr r0, [%1, #40] \n\t" \
"ldr r1, [%1, #44] \n\t" \
"push {r0, r1} \n\t" \
"ldr r0, [%1, #20] \n\t" \
"ldr r1, [%1, #24] \n\t" \
"ldr r2, [%1, #28] \n\t" \
"ldr r3, [%1, #32] \n\t" \
"ldr r4, [%1, #36] \n\t" \
"push {r0, r1, r2, r3, r4} \n\t" \
"ldr r0, [%1, #4] \n\t" \
"ldr r1, [%1, #8] \n\t" \
"ldr r2, [%1, #12] \n\t" \
"ldr r3, [%1, #16] \n\t" \
"ldr r4, [%1] \n\t" /* target->r4 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
VALGRIND_RESTORE_STACK \
"mov %0, r0" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
arg6,arg7,arg8,arg9,arg10, \
arg11,arg12) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[13]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
_argvec[11] = (unsigned long)(arg11); \
_argvec[12] = (unsigned long)(arg12); \
__asm__ volatile( \
VALGRIND_ALIGN_STACK \
"ldr r0, [%1, #40] \n\t" \
"ldr r1, [%1, #44] \n\t" \
"ldr r2, [%1, #48] \n\t" \
"push {r0, r1, r2} \n\t" \
"ldr r0, [%1, #20] \n\t" \
"ldr r1, [%1, #24] \n\t" \
"ldr r2, [%1, #28] \n\t" \
"ldr r3, [%1, #32] \n\t" \
"ldr r4, [%1, #36] \n\t" \
"push {r0, r1, r2, r3, r4} \n\t" \
"ldr r0, [%1, #4] \n\t" \
"ldr r1, [%1, #8] \n\t" \
"ldr r2, [%1, #12] \n\t" \
"ldr r3, [%1, #16] \n\t" \
"ldr r4, [%1] \n\t" /* target->r4 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
VALGRIND_RESTORE_STACK \
"mov %0, r0" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#endif /* PLAT_arm_linux */
/* ------------------------- s390x-linux ------------------------- */
#if defined(PLAT_s390x_linux)
/* Similar workaround as amd64 (see above), but we use r11 as frame
pointer and save the old r11 in r7. r11 might be used for
argvec, therefore we copy argvec in r1 since r1 is clobbered
after the call anyway. */
#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
# define __FRAME_POINTER \
,"d"(__builtin_dwarf_cfa())
# define VALGRIND_CFI_PROLOGUE \
".cfi_remember_state\n\t" \
"lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
"lgr 7,11\n\t" \
"lgr 11,%2\n\t" \
".cfi_def_cfa r11, 0\n\t"
# define VALGRIND_CFI_EPILOGUE \
"lgr 11, 7\n\t" \
".cfi_restore_state\n\t"
#else
# define __FRAME_POINTER
# define VALGRIND_CFI_PROLOGUE \
"lgr 1,%1\n\t"
# define VALGRIND_CFI_EPILOGUE
#endif
/* Nb: On s390 the stack pointer is properly aligned *at all times*
according to the s390 GCC maintainer. (The ABI specification is not
precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and
VALGRIND_RESTORE_STACK are not defined here. */
/* These regs are trashed by the hidden call. Note that we overwrite
r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
function a proper return address. All others are ABI defined call
clobbers. */
#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
"f0","f1","f2","f3","f4","f5","f6","f7"
/* Nb: Although r11 is modified in the asm snippets below (inside
VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for
two reasons:
(1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not
modified
(2) GCC will complain that r11 cannot appear inside a clobber section,
when compiled with -O -fno-omit-frame-pointer
*/
#define CALL_FN_W_v(lval, orig) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[1]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
"aghi 15,-160\n\t" \
"lg 1, 0(1)\n\t" /* target->r1 */ \
VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,160\n\t" \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=d" (_res) \
: /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
/* The call abi has the arguments in r2-r6 and stack */
#define CALL_FN_W_W(lval, orig, arg1) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[2]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
"aghi 15,-160\n\t" \
"lg 2, 8(1)\n\t" \
"lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,160\n\t" \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
"aghi 15,-160\n\t" \
"lg 2, 8(1)\n\t" \
"lg 3,16(1)\n\t" \
"lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,160\n\t" \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[4]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
"aghi 15,-160\n\t" \
"lg 2, 8(1)\n\t" \
"lg 3,16(1)\n\t" \
"lg 4,24(1)\n\t" \
"lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,160\n\t" \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[5]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
"aghi 15,-160\n\t" \
"lg 2, 8(1)\n\t" \
"lg 3,16(1)\n\t" \
"lg 4,24(1)\n\t" \
"lg 5,32(1)\n\t" \
"lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,160\n\t" \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[6]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
"aghi 15,-160\n\t" \
"lg 2, 8(1)\n\t" \
"lg 3,16(1)\n\t" \
"lg 4,24(1)\n\t" \
"lg 5,32(1)\n\t" \
"lg 6,40(1)\n\t" \
"lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,160\n\t" \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
arg6) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[7]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
"aghi 15,-168\n\t" \
"lg 2, 8(1)\n\t" \
"lg 3,16(1)\n\t" \
"lg 4,24(1)\n\t" \
"lg 5,32(1)\n\t" \
"lg 6,40(1)\n\t" \
"mvc 160(8,15), 48(1)\n\t" \
"lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,168\n\t" \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
arg6, arg7) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[8]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
_argvec[7] = (unsigned long)arg7; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
"aghi 15,-176\n\t" \
"lg 2, 8(1)\n\t" \
"lg 3,16(1)\n\t" \
"lg 4,24(1)\n\t" \
"lg 5,32(1)\n\t" \
"lg 6,40(1)\n\t" \
"mvc 160(8,15), 48(1)\n\t" \
"mvc 168(8,15), 56(1)\n\t" \
"lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,176\n\t" \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
arg6, arg7 ,arg8) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[9]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
_argvec[7] = (unsigned long)arg7; \
_argvec[8] = (unsigned long)arg8; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
"aghi 15,-184\n\t" \
"lg 2, 8(1)\n\t" \
"lg 3,16(1)\n\t" \
"lg 4,24(1)\n\t" \
"lg 5,32(1)\n\t" \
"lg 6,40(1)\n\t" \
"mvc 160(8,15), 48(1)\n\t" \
"mvc 168(8,15), 56(1)\n\t" \
"mvc 176(8,15), 64(1)\n\t" \
"lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,184\n\t" \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
arg6, arg7 ,arg8, arg9) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[10]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
_argvec[7] = (unsigned long)arg7; \
_argvec[8] = (unsigned long)arg8; \
_argvec[9] = (unsigned long)arg9; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
"aghi 15,-192\n\t" \
"lg 2, 8(1)\n\t" \
"lg 3,16(1)\n\t" \
"lg 4,24(1)\n\t" \
"lg 5,32(1)\n\t" \
"lg 6,40(1)\n\t" \
"mvc 160(8,15), 48(1)\n\t" \
"mvc 168(8,15), 56(1)\n\t" \
"mvc 176(8,15), 64(1)\n\t" \
"mvc 184(8,15), 72(1)\n\t" \
"lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,192\n\t" \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
arg6, arg7 ,arg8, arg9, arg10) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[11]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
_argvec[7] = (unsigned long)arg7; \
_argvec[8] = (unsigned long)arg8; \
_argvec[9] = (unsigned long)arg9; \
_argvec[10] = (unsigned long)arg10; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
"aghi 15,-200\n\t" \
"lg 2, 8(1)\n\t" \
"lg 3,16(1)\n\t" \
"lg 4,24(1)\n\t" \
"lg 5,32(1)\n\t" \
"lg 6,40(1)\n\t" \
"mvc 160(8,15), 48(1)\n\t" \
"mvc 168(8,15), 56(1)\n\t" \
"mvc 176(8,15), 64(1)\n\t" \
"mvc 184(8,15), 72(1)\n\t" \
"mvc 192(8,15), 80(1)\n\t" \
"lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,200\n\t" \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
arg6, arg7 ,arg8, arg9, arg10, arg11) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[12]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
_argvec[7] = (unsigned long)arg7; \
_argvec[8] = (unsigned long)arg8; \
_argvec[9] = (unsigned long)arg9; \
_argvec[10] = (unsigned long)arg10; \
_argvec[11] = (unsigned long)arg11; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
"aghi 15,-208\n\t" \
"lg 2, 8(1)\n\t" \
"lg 3,16(1)\n\t" \
"lg 4,24(1)\n\t" \
"lg 5,32(1)\n\t" \
"lg 6,40(1)\n\t" \
"mvc 160(8,15), 48(1)\n\t" \
"mvc 168(8,15), 56(1)\n\t" \
"mvc 176(8,15), 64(1)\n\t" \
"mvc 184(8,15), 72(1)\n\t" \
"mvc 192(8,15), 80(1)\n\t" \
"mvc 200(8,15), 88(1)\n\t" \
"lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,208\n\t" \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[13]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
_argvec[7] = (unsigned long)arg7; \
_argvec[8] = (unsigned long)arg8; \
_argvec[9] = (unsigned long)arg9; \
_argvec[10] = (unsigned long)arg10; \
_argvec[11] = (unsigned long)arg11; \
_argvec[12] = (unsigned long)arg12; \
__asm__ volatile( \
VALGRIND_CFI_PROLOGUE \
"aghi 15,-216\n\t" \
"lg 2, 8(1)\n\t" \
"lg 3,16(1)\n\t" \
"lg 4,24(1)\n\t" \
"lg 5,32(1)\n\t" \
"lg 6,40(1)\n\t" \
"mvc 160(8,15), 48(1)\n\t" \
"mvc 168(8,15), 56(1)\n\t" \
"mvc 176(8,15), 64(1)\n\t" \
"mvc 184(8,15), 72(1)\n\t" \
"mvc 192(8,15), 80(1)\n\t" \
"mvc 200(8,15), 88(1)\n\t" \
"mvc 208(8,15), 96(1)\n\t" \
"lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,216\n\t" \
VALGRIND_CFI_EPILOGUE \
: /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#endif /* PLAT_s390x_linux */
/* ------------------------- mips-linux ------------------------- */
#if defined(PLAT_mips32_linux)
/* These regs are trashed by the hidden call. */
#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
"$25", "$31"
/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
long) == 4. */
#define CALL_FN_W_v(lval, orig) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[1]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
"subu $29, $29, 8 \n\t" \
"sw $gp, 0($sp) \n\t" \
"sw $ra, 4($sp) \n\t" \
"subu $29, $29, 16 \n\t" \
"lw $t9, 0(%1) \n\t" /* target->t9 */ \
VALGRIND_CALL_NOREDIR_T9 \
"addu $29, $29, 16\n\t" \
"lw $gp, 0($sp) \n\t" \
"lw $ra, 4($sp) \n\t" \
"addu $29, $29, 8 \n\t" \
"move %0, $v0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_W(lval, orig, arg1) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[2]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
__asm__ volatile( \
"subu $29, $29, 8 \n\t" \
"sw $gp, 0($sp) \n\t" \
"sw $ra, 4($sp) \n\t" \
"subu $29, $29, 16 \n\t" \
"lw $a0, 4(%1) \n\t" /* arg1*/ \
"lw $t9, 0(%1) \n\t" /* target->t9 */ \
VALGRIND_CALL_NOREDIR_T9 \
"addu $29, $29, 16 \n\t" \
"lw $gp, 0($sp) \n\t" \
"lw $ra, 4($sp) \n\t" \
"addu $29, $29, 8 \n\t" \
"move %0, $v0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
__asm__ volatile( \
"subu $29, $29, 8 \n\t" \
"sw $gp, 0($sp) \n\t" \
"sw $ra, 4($sp) \n\t" \
"subu $29, $29, 16 \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $t9, 0(%1) \n\t" /* target->t9 */ \
VALGRIND_CALL_NOREDIR_T9 \
"addu $29, $29, 16 \n\t" \
"lw $gp, 0($sp) \n\t" \
"lw $ra, 4($sp) \n\t" \
"addu $29, $29, 8 \n\t" \
"move %0, $v0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[4]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
__asm__ volatile( \
"subu $29, $29, 8 \n\t" \
"sw $gp, 0($sp) \n\t" \
"sw $ra, 4($sp) \n\t" \
"subu $29, $29, 16 \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2, 12(%1) \n\t" \
"lw $t9, 0(%1) \n\t" /* target->t9 */ \
VALGRIND_CALL_NOREDIR_T9 \
"addu $29, $29, 16 \n\t" \
"lw $gp, 0($sp) \n\t" \
"lw $ra, 4($sp) \n\t" \
"addu $29, $29, 8 \n\t" \
"move %0, $v0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[5]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
__asm__ volatile( \
"subu $29, $29, 8 \n\t" \
"sw $gp, 0($sp) \n\t" \
"sw $ra, 4($sp) \n\t" \
"subu $29, $29, 16 \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2, 12(%1) \n\t" \
"lw $a3, 16(%1) \n\t" \
"lw $t9, 0(%1) \n\t" /* target->t9 */ \
VALGRIND_CALL_NOREDIR_T9 \
"addu $29, $29, 16 \n\t" \
"lw $gp, 0($sp) \n\t" \
"lw $ra, 4($sp) \n\t" \
"addu $29, $29, 8 \n\t" \
"move %0, $v0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[6]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
__asm__ volatile( \
"subu $29, $29, 8 \n\t" \
"sw $gp, 0($sp) \n\t" \
"sw $ra, 4($sp) \n\t" \
"lw $a0, 20(%1) \n\t" \
"subu $sp, $sp, 24\n\t" \
"sw $a0, 16($sp) \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2, 12(%1) \n\t" \
"lw $a3, 16(%1) \n\t" \
"lw $t9, 0(%1) \n\t" /* target->t9 */ \
VALGRIND_CALL_NOREDIR_T9 \
"addu $29, $29, 24 \n\t" \
"lw $gp, 0($sp) \n\t" \
"lw $ra, 4($sp) \n\t" \
"addu $sp, $sp, 8 \n\t" \
"move %0, $v0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[7]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
__asm__ volatile( \
"subu $29, $29, 8 \n\t" \
"sw $gp, 0($sp) \n\t" \
"sw $ra, 4($sp) \n\t" \
"lw $a0, 20(%1) \n\t" \
"subu $sp, $sp, 32\n\t" \
"sw $a0, 16($sp) \n\t" \
"lw $a0, 24(%1) \n\t" \
"nop\n\t" \
"sw $a0, 20($sp) \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2, 12(%1) \n\t" \
"lw $a3, 16(%1) \n\t" \
"lw $t9, 0(%1) \n\t" /* target->t9 */ \
VALGRIND_CALL_NOREDIR_T9 \
"addu $sp, $sp, 32 \n\t" \
"lw $gp, 0($sp) \n\t" \
"lw $ra, 4($sp) \n\t" \
"addu $sp, $sp, 8 \n\t" \
"move %0, $v0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[8]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
__asm__ volatile( \
"subu $29, $29, 8 \n\t" \
"sw $gp, 0($sp) \n\t" \
"sw $ra, 4($sp) \n\t" \
"lw $a0, 20(%1) \n\t" \
"subu $sp, $sp, 32\n\t" \
"sw $a0, 16($sp) \n\t" \
"lw $a0, 24(%1) \n\t" \
"sw $a0, 20($sp) \n\t" \
"lw $a0, 28(%1) \n\t" \
"sw $a0, 24($sp) \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2, 12(%1) \n\t" \
"lw $a3, 16(%1) \n\t" \
"lw $t9, 0(%1) \n\t" /* target->t9 */ \
VALGRIND_CALL_NOREDIR_T9 \
"addu $sp, $sp, 32 \n\t" \
"lw $gp, 0($sp) \n\t" \
"lw $ra, 4($sp) \n\t" \
"addu $sp, $sp, 8 \n\t" \
"move %0, $v0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[9]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
__asm__ volatile( \
"subu $29, $29, 8 \n\t" \
"sw $gp, 0($sp) \n\t" \
"sw $ra, 4($sp) \n\t" \
"lw $a0, 20(%1) \n\t" \
"subu $sp, $sp, 40\n\t" \
"sw $a0, 16($sp) \n\t" \
"lw $a0, 24(%1) \n\t" \
"sw $a0, 20($sp) \n\t" \
"lw $a0, 28(%1) \n\t" \
"sw $a0, 24($sp) \n\t" \
"lw $a0, 32(%1) \n\t" \
"sw $a0, 28($sp) \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2, 12(%1) \n\t" \
"lw $a3, 16(%1) \n\t" \
"lw $t9, 0(%1) \n\t" /* target->t9 */ \
VALGRIND_CALL_NOREDIR_T9 \
"addu $sp, $sp, 40 \n\t" \
"lw $gp, 0($sp) \n\t" \
"lw $ra, 4($sp) \n\t" \
"addu $sp, $sp, 8 \n\t" \
"move %0, $v0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[10]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
__asm__ volatile( \
"subu $29, $29, 8 \n\t" \
"sw $gp, 0($sp) \n\t" \
"sw $ra, 4($sp) \n\t" \
"lw $a0, 20(%1) \n\t" \
"subu $sp, $sp, 40\n\t" \
"sw $a0, 16($sp) \n\t" \
"lw $a0, 24(%1) \n\t" \
"sw $a0, 20($sp) \n\t" \
"lw $a0, 28(%1) \n\t" \
"sw $a0, 24($sp) \n\t" \
"lw $a0, 32(%1) \n\t" \
"sw $a0, 28($sp) \n\t" \
"lw $a0, 36(%1) \n\t" \
"sw $a0, 32($sp) \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2, 12(%1) \n\t" \
"lw $a3, 16(%1) \n\t" \
"lw $t9, 0(%1) \n\t" /* target->t9 */ \
VALGRIND_CALL_NOREDIR_T9 \
"addu $sp, $sp, 40 \n\t" \
"lw $gp, 0($sp) \n\t" \
"lw $ra, 4($sp) \n\t" \
"addu $sp, $sp, 8 \n\t" \
"move %0, $v0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9,arg10) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[11]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
__asm__ volatile( \
"subu $29, $29, 8 \n\t" \
"sw $gp, 0($sp) \n\t" \
"sw $ra, 4($sp) \n\t" \
"lw $a0, 20(%1) \n\t" \
"subu $sp, $sp, 48\n\t" \
"sw $a0, 16($sp) \n\t" \
"lw $a0, 24(%1) \n\t" \
"sw $a0, 20($sp) \n\t" \
"lw $a0, 28(%1) \n\t" \
"sw $a0, 24($sp) \n\t" \
"lw $a0, 32(%1) \n\t" \
"sw $a0, 28($sp) \n\t" \
"lw $a0, 36(%1) \n\t" \
"sw $a0, 32($sp) \n\t" \
"lw $a0, 40(%1) \n\t" \
"sw $a0, 36($sp) \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2, 12(%1) \n\t" \
"lw $a3, 16(%1) \n\t" \
"lw $t9, 0(%1) \n\t" /* target->t9 */ \
VALGRIND_CALL_NOREDIR_T9 \
"addu $sp, $sp, 48 \n\t" \
"lw $gp, 0($sp) \n\t" \
"lw $ra, 4($sp) \n\t" \
"addu $sp, $sp, 8 \n\t" \
"move %0, $v0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
arg6,arg7,arg8,arg9,arg10, \
arg11) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[12]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
_argvec[11] = (unsigned long)(arg11); \
__asm__ volatile( \
"subu $29, $29, 8 \n\t" \
"sw $gp, 0($sp) \n\t" \
"sw $ra, 4($sp) \n\t" \
"lw $a0, 20(%1) \n\t" \
"subu $sp, $sp, 48\n\t" \
"sw $a0, 16($sp) \n\t" \
"lw $a0, 24(%1) \n\t" \
"sw $a0, 20($sp) \n\t" \
"lw $a0, 28(%1) \n\t" \
"sw $a0, 24($sp) \n\t" \
"lw $a0, 32(%1) \n\t" \
"sw $a0, 28($sp) \n\t" \
"lw $a0, 36(%1) \n\t" \
"sw $a0, 32($sp) \n\t" \
"lw $a0, 40(%1) \n\t" \
"sw $a0, 36($sp) \n\t" \
"lw $a0, 44(%1) \n\t" \
"sw $a0, 40($sp) \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2, 12(%1) \n\t" \
"lw $a3, 16(%1) \n\t" \
"lw $t9, 0(%1) \n\t" /* target->t9 */ \
VALGRIND_CALL_NOREDIR_T9 \
"addu $sp, $sp, 48 \n\t" \
"lw $gp, 0($sp) \n\t" \
"lw $ra, 4($sp) \n\t" \
"addu $sp, $sp, 8 \n\t" \
"move %0, $v0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
arg6,arg7,arg8,arg9,arg10, \
arg11,arg12) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[13]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
_argvec[11] = (unsigned long)(arg11); \
_argvec[12] = (unsigned long)(arg12); \
__asm__ volatile( \
"subu $29, $29, 8 \n\t" \
"sw $gp, 0($sp) \n\t" \
"sw $ra, 4($sp) \n\t" \
"lw $a0, 20(%1) \n\t" \
"subu $sp, $sp, 56\n\t" \
"sw $a0, 16($sp) \n\t" \
"lw $a0, 24(%1) \n\t" \
"sw $a0, 20($sp) \n\t" \
"lw $a0, 28(%1) \n\t" \
"sw $a0, 24($sp) \n\t" \
"lw $a0, 32(%1) \n\t" \
"sw $a0, 28($sp) \n\t" \
"lw $a0, 36(%1) \n\t" \
"sw $a0, 32($sp) \n\t" \
"lw $a0, 40(%1) \n\t" \
"sw $a0, 36($sp) \n\t" \
"lw $a0, 44(%1) \n\t" \
"sw $a0, 40($sp) \n\t" \
"lw $a0, 48(%1) \n\t" \
"sw $a0, 44($sp) \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2, 12(%1) \n\t" \
"lw $a3, 16(%1) \n\t" \
"lw $t9, 0(%1) \n\t" /* target->t9 */ \
VALGRIND_CALL_NOREDIR_T9 \
"addu $sp, $sp, 56 \n\t" \
"lw $gp, 0($sp) \n\t" \
"lw $ra, 4($sp) \n\t" \
"addu $sp, $sp, 8 \n\t" \
"move %0, $v0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "0" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#endif /* PLAT_mips32_linux */
/* ------------------------------------------------------------------ */
/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
/* */
/* ------------------------------------------------------------------ */
/* Some request codes. There are many more of these, but most are not
exposed to end-user view. These are the public ones, all of the
form 0x1000 + small_number.
Core ones are in the range 0x00000000--0x0000ffff. The non-public
ones start at 0x2000.
*/
/* These macros are used by tools -- they must be public, but don't
embed them into other programs. */
#define VG_USERREQ_TOOL_BASE(a,b) \
((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
#define VG_IS_TOOL_USERREQ(a, b, v) \
(VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
This enum comprises an ABI exported by Valgrind to programs
which use client requests. DO NOT CHANGE THE ORDER OF THESE
ENTRIES, NOR DELETE ANY -- add new ones at the end. */
typedef
enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
/* These allow any function to be called from the simulated
CPU but run on the real CPU. Nb: the first arg passed to
the function is always the ThreadId of the running
thread! So CLIENT_CALL0 actually requires a 1 arg
function, etc. */
VG_USERREQ__CLIENT_CALL0 = 0x1101,
VG_USERREQ__CLIENT_CALL1 = 0x1102,
VG_USERREQ__CLIENT_CALL2 = 0x1103,
VG_USERREQ__CLIENT_CALL3 = 0x1104,
/* Can be useful in regression testing suites -- eg. can
send Valgrind's output to /dev/null and still count
errors. */
VG_USERREQ__COUNT_ERRORS = 0x1201,
/* Allows a string (gdb monitor command) to be passed to the tool
Used for interaction with vgdb/gdb */
VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
/* These are useful and can be interpreted by any tool that
tracks malloc() et al, by using vg_replace_malloc.c. */
VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
VG_USERREQ__FREELIKE_BLOCK = 0x1302,
/* Memory pool support. */
VG_USERREQ__CREATE_MEMPOOL = 0x1303,
VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
VG_USERREQ__MEMPOOL_FREE = 0x1306,
VG_USERREQ__MEMPOOL_TRIM = 0x1307,
VG_USERREQ__MOVE_MEMPOOL = 0x1308,
VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
/* Allow printfs to valgrind log. */
/* The first two pass the va_list argument by value, which
assumes it is the same size as or smaller than a UWord,
which generally isn't the case. Hence are deprecated.
The second two pass the vargs by reference and so are
immune to this problem. */
/* both :: char* fmt, va_list vargs (DEPRECATED) */
VG_USERREQ__PRINTF = 0x1401,
VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
/* both :: char* fmt, va_list* vargs */
VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
/* Stack support. */
VG_USERREQ__STACK_REGISTER = 0x1501,
VG_USERREQ__STACK_DEREGISTER = 0x1502,
VG_USERREQ__STACK_CHANGE = 0x1503,
/* Wine support */
VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
/* Querying of debug info. */
VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
/* Disable/enable error reporting level. Takes a single
Word arg which is the delta to this thread's error
disablement indicator. Hence 1 disables or further
disables errors, and -1 moves back towards enablement.
Other values are not allowed. */
VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801
} Vg_ClientRequest;
#if !defined(__GNUC__)
# define __extension__ /* */
#endif
/* Returns the number of Valgrinds this code is running under. That
is, 0 if running natively, 1 if running under Valgrind, 2 if
running under Valgrind which is running under another Valgrind,
etc. */
#define RUNNING_ON_VALGRIND \
(unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
VG_USERREQ__RUNNING_ON_VALGRIND, \
0, 0, 0, 0, 0) \
/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
_qzz_len - 1]. Useful if you are debugging a JITter or some such,
since it provides a way to make sure valgrind will retranslate the
invalidated area. Returns no value. */
#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \
_qzz_addr, _qzz_len, 0, 0, 0)
/* These requests are for getting Valgrind itself to print something.
Possibly with a backtrace. This is a really ugly hack. The return value
is the number of characters printed, excluding the "**** " part at the
start and the backtrace (if present). */
#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
/* Modern GCC will optimize the static routine out if unused,
and unused attribute will shut down warnings about it. */
static int VALGRIND_PRINTF(const char *format, ...)
__attribute__((format(__printf__, 1, 2), __unused__));
#endif
static int
#if defined(_MSC_VER)
__inline
#endif
VALGRIND_PRINTF(const char *format, ...)
{
#if defined(NVALGRIND)
return 0;
#else /* NVALGRIND */
#if defined(_MSC_VER)
uintptr_t _qzz_res;
#else
unsigned long _qzz_res;
#endif
va_list vargs;
va_start(vargs, format);
#if defined(_MSC_VER)
_qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
VG_USERREQ__PRINTF_VALIST_BY_REF,
(uintptr_t)format,
(uintptr_t)&vargs,
0, 0, 0);
#else
_qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
VG_USERREQ__PRINTF_VALIST_BY_REF,
(unsigned long)format,
(unsigned long)&vargs,
0, 0, 0);
#endif
va_end(vargs);
return (int)_qzz_res;
#endif /* NVALGRIND */
}
#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
__attribute__((format(__printf__, 1, 2), __unused__));
#endif
static int
#if defined(_MSC_VER)
__inline
#endif
VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
{
#if defined(NVALGRIND)
return 0;
#else /* NVALGRIND */
#if defined(_MSC_VER)
uintptr_t _qzz_res;
#else
unsigned long _qzz_res;
#endif
va_list vargs;
va_start(vargs, format);
#if defined(_MSC_VER)
_qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
(uintptr_t)format,
(uintptr_t)&vargs,
0, 0, 0);
#else
_qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
(unsigned long)format,
(unsigned long)&vargs,
0, 0, 0);
#endif
va_end(vargs);
return (int)_qzz_res;
#endif /* NVALGRIND */
}
/* These requests allow control to move from the simulated CPU to the
real CPU, calling an arbitary function.
Note that the current ThreadId is inserted as the first argument.
So this call:
VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
requires f to have this signature:
Word f(Word tid, Word arg1, Word arg2)
where "Word" is a word-sized type.
Note that these client requests are not entirely reliable. For example,
if you call a function with them that subsequently calls printf(),
there's a high chance Valgrind will crash. Generally, your prospects of
these working are made higher if the called function does not refer to
any global variables, and does not refer to any libc or other functions
(printf et al). Any kind of entanglement with libc or dynamic linking is
likely to have a bad outcome, for tricky reasons which we've grappled
with a lot in the past.
*/
#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
VG_USERREQ__CLIENT_CALL0, \
_qyy_fn, \
0, 0, 0, 0)
#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
VG_USERREQ__CLIENT_CALL1, \
_qyy_fn, \
_qyy_arg1, 0, 0, 0)
#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
VG_USERREQ__CLIENT_CALL2, \
_qyy_fn, \
_qyy_arg1, _qyy_arg2, 0, 0)
#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
VG_USERREQ__CLIENT_CALL3, \
_qyy_fn, \
_qyy_arg1, _qyy_arg2, \
_qyy_arg3, 0)
/* Counts the number of errors that have been recorded by a tool. Nb:
the tool must record the errors with VG_(maybe_record_error)() or
VG_(unique_error)() for them to be counted. */
#define VALGRIND_COUNT_ERRORS \
(unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \
0 /* default return */, \
VG_USERREQ__COUNT_ERRORS, \
0, 0, 0, 0, 0)
/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
when heap blocks are allocated in order to give accurate results. This
happens automatically for the standard allocator functions such as
malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
delete[], etc.
But if your program uses a custom allocator, this doesn't automatically
happen, and Valgrind will not do as well. For example, if you allocate
superblocks with mmap() and then allocates chunks of the superblocks, all
Valgrind's observations will be at the mmap() level and it won't know that
the chunks should be considered separate entities. In Memcheck's case,
that means you probably won't get heap block overrun detection (because
there won't be redzones marked as unaddressable) and you definitely won't
get any leak detection.
The following client requests allow a custom allocator to be annotated so
that it can be handled accurately by Valgrind.
VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
by a malloc()-like function. For Memcheck (an illustrative case), this
does two things:
- It records that the block has been allocated. This means any addresses
within the block mentioned in error messages will be
identified as belonging to the block. It also means that if the block
isn't freed it will be detected by the leak checker.
- It marks the block as being addressable and undefined (if 'is_zeroed' is
not set), or addressable and defined (if 'is_zeroed' is set). This
controls how accesses to the block by the program are handled.
'addr' is the start of the usable block (ie. after any
redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
can apply redzones -- these are blocks of padding at the start and end of
each block. Adding redzones is recommended as it makes it much more likely
Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
zeroed (or filled with another predictable value), as is the case for
calloc().
VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
heap block -- that will be used by the client program -- is allocated.
It's best to put it at the outermost level of the allocator if possible;
for example, if you have a function my_alloc() which calls
internal_alloc(), and the client request is put inside internal_alloc(),
stack traces relating to the heap block will contain entries for both
my_alloc() and internal_alloc(), which is probably not what you want.
For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
custom blocks from within a heap block, B, that has been allocated with
malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
-- the custom blocks will take precedence.
VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
Memcheck, it does two things:
- It records that the block has been deallocated. This assumes that the
block was annotated as having been allocated via
VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
- It marks the block as being unaddressable.
VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
heap block is deallocated.
VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
Memcheck, it does four things:
- It records that the size of a block has been changed. This assumes that
the block was annotated as having been allocated via
VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
- If the block shrunk, it marks the freed memory as being unaddressable.
- If the block grew, it marks the new area as undefined and defines a red
zone past the end of the new block.
- The V-bits of the overlap between the old and the new block are preserved.
VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
and before deallocation of the old block.
In many cases, these three client requests will not be enough to get your
allocator working well with Memcheck. More specifically, if your allocator
writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
will be necessary to mark the memory as addressable just before the zeroing
occurs, otherwise you'll get a lot of invalid write errors. For example,
you'll need to do this if your allocator recycles freed blocks, but it
zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
Alternatively, if your allocator reuses freed blocks for allocator-internal
data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
Really, what's happening is a blurring of the lines between the client
program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
memory should be considered unaddressable to the client program, but the
allocator knows more than the rest of the client program and so may be able
to safely access it. Extra client requests are necessary for Valgrind to
understand the distinction between the allocator and the rest of the
program.
Ignored if addr == 0.
*/
#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \
addr, sizeB, rzB, is_zeroed, 0)
/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
Ignored if addr == 0.
*/
#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \
addr, oldSizeB, newSizeB, rzB, 0)
/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
Ignored if addr == 0.
*/
#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \
addr, rzB, 0, 0, 0)
/* Create a memory pool. */
#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \
pool, rzB, is_zeroed, 0, 0)
/* Destroy a memory pool. */
#define VALGRIND_DESTROY_MEMPOOL(pool) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \
pool, 0, 0, 0, 0)
/* Associate a piece of memory with a memory pool. */
#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \
pool, addr, size, 0, 0)
/* Disassociate a piece of memory from a memory pool. */
#define VALGRIND_MEMPOOL_FREE(pool, addr) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \
pool, addr, 0, 0, 0)
/* Disassociate any pieces outside a particular range. */
#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \
pool, addr, size, 0, 0)
/* Resize and/or move a piece associated with a memory pool. */
#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \
poolA, poolB, 0, 0, 0)
/* Resize and/or move a piece associated with a memory pool. */
#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \
pool, addrA, addrB, size, 0)
/* Return 1 if a mempool exists, else 0. */
#define VALGRIND_MEMPOOL_EXISTS(pool) \
(unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
VG_USERREQ__MEMPOOL_EXISTS, \
pool, 0, 0, 0, 0)
/* Mark a piece of memory as being a stack. Returns a stack id. */
#define VALGRIND_STACK_REGISTER(start, end) \
(unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
VG_USERREQ__STACK_REGISTER, \
start, end, 0, 0, 0)
/* Unmark the piece of memory associated with a stack id as being a
stack. */
#define VALGRIND_STACK_DEREGISTER(id) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
id, 0, 0, 0, 0)
/* Change the start and end address of the stack id. */
#define VALGRIND_STACK_CHANGE(id, start, end) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \
id, start, end, 0, 0)
/* Load PDB debug info for Wine PE image_map. */
#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
fd, ptr, total_size, delta, 0)
/* Map a code address to a source file name and line number. buf64
must point to a 64-byte buffer in the caller's address space. The
result will be dumped in there and is guaranteed to be zero
terminated. If no info is found, the first byte is set to zero. */
#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
(unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
VG_USERREQ__MAP_IP_TO_SRCLOC, \
addr, buf64, 0, 0, 0)
/* Disable error reporting for this thread. Behaves in a stack like
way, so you can safely call this multiple times provided that
VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
to re-enable reporting. The first call of this macro disables
reporting. Subsequent calls have no effect except to increase the
number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
reporting. Child threads do not inherit this setting from their
parents -- they are always created with reporting enabled. */
#define VALGRIND_DISABLE_ERROR_REPORTING \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
1, 0, 0, 0, 0)
/* Re-enable error reporting, as per comments on
VALGRIND_DISABLE_ERROR_REPORTING. */
#define VALGRIND_ENABLE_ERROR_REPORTING \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
-1, 0, 0, 0, 0)
#undef PLAT_x86_darwin
#undef PLAT_amd64_darwin
#undef PLAT_x86_win32
#undef PLAT_x86_linux
#undef PLAT_amd64_linux
#undef PLAT_ppc32_linux
#undef PLAT_ppc64_linux
#undef PLAT_arm_linux
#undef PLAT_s390x_linux
#undef PLAT_mips32_linux
#endif /* __VALGRIND_H */
pkg-config-0.29.1/glib/glib/gtimezone.c 0000664 0001750 0001750 00000147234 12651243552 014571 0000000 0000000 /*
* Copyright © 2010 Codethink Limited
*
* This 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 of the licence, 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ryan Lortie
*/
/* Prologue {{{1 */
#include "config.h"
#include "gtimezone.h"
#include
#include
#include
#include "gmappedfile.h"
#include "gtestutils.h"
#include "gfileutils.h"
#include "gstrfuncs.h"
#include "ghash.h"
#include "gthread.h"
#include "gbytes.h"
#include "gslice.h"
#include "gdatetime.h"
#include "gdate.h"
#ifdef G_OS_WIN32
#define STRICT
#include
#endif
/**
* SECTION:timezone
* @title: GTimeZone
* @short_description: a structure representing a time zone
* @see_also: #GDateTime
*
* #GTimeZone is a structure that represents a time zone, at no
* particular point in time. It is refcounted and immutable.
*
* A time zone contains a number of intervals. Each interval has
* an abbreviation to describe it, an offet to UTC and a flag indicating
* if the daylight savings time is in effect during that interval. A
* time zone always has at least one interval -- interval 0.
*
* Every UTC time is contained within exactly one interval, but a given
* local time may be contained within zero, one or two intervals (due to
* incontinuities associated with daylight savings time).
*
* An interval may refer to a specific period of time (eg: the duration
* of daylight savings time during 2010) or it may refer to many periods
* of time that share the same properties (eg: all periods of daylight
* savings time). It is also possible (usually for political reasons)
* that some properties (like the abbreviation) change between intervals
* without other properties changing.
*
* #GTimeZone is available since GLib 2.26.
*/
/**
* GTimeZone:
*
* #GTimeZone is an opaque structure whose members cannot be accessed
* directly.
*
* Since: 2.26
**/
/* IANA zoneinfo file format {{{1 */
/* unaligned */
typedef struct { gchar bytes[8]; } gint64_be;
typedef struct { gchar bytes[4]; } gint32_be;
typedef struct { gchar bytes[4]; } guint32_be;
static inline gint64 gint64_from_be (const gint64_be be) {
gint64 tmp; memcpy (&tmp, &be, sizeof tmp); return GINT64_FROM_BE (tmp);
}
static inline gint32 gint32_from_be (const gint32_be be) {
gint32 tmp; memcpy (&tmp, &be, sizeof tmp); return GINT32_FROM_BE (tmp);
}
static inline guint32 guint32_from_be (const guint32_be be) {
guint32 tmp; memcpy (&tmp, &be, sizeof tmp); return GUINT32_FROM_BE (tmp);
}
/* The layout of an IANA timezone file header */
struct tzhead
{
gchar tzh_magic[4];
gchar tzh_version;
guchar tzh_reserved[15];
guint32_be tzh_ttisgmtcnt;
guint32_be tzh_ttisstdcnt;
guint32_be tzh_leapcnt;
guint32_be tzh_timecnt;
guint32_be tzh_typecnt;
guint32_be tzh_charcnt;
};
struct ttinfo
{
gint32_be tt_gmtoff;
guint8 tt_isdst;
guint8 tt_abbrind;
};
/* A Transition Date structure for TZ Rules, an intermediate structure
for parsing MSWindows and Environment-variable time zones. It
Generalizes MSWindows's SYSTEMTIME struct.
*/
typedef struct
{
gint year;
gint mon;
gint mday;
gint wday;
gint week;
gint hour;
gint min;
gint sec;
} TimeZoneDate;
/* POSIX Timezone abbreviations are typically 3 or 4 characters, but
Microsoft uses 32-character names. We'll use one larger to ensure
we have room for the terminating \0.
*/
#define NAME_SIZE 33
/* A MSWindows-style time zone transition rule. Generalizes the
MSWindows TIME_ZONE_INFORMATION struct. Also used to compose time
zones from tzset-style identifiers.
*/
typedef struct
{
gint start_year;
gint32 std_offset;
gint32 dlt_offset;
TimeZoneDate dlt_start;
TimeZoneDate dlt_end;
gchar std_name[NAME_SIZE];
gchar dlt_name[NAME_SIZE];
} TimeZoneRule;
/* GTimeZone's internal representation of a Daylight Savings (Summer)
time interval.
*/
typedef struct
{
gint32 gmt_offset;
gboolean is_dst;
gboolean is_standard;
gboolean is_gmt;
gchar *abbrev;
} TransitionInfo;
/* GTimeZone's representation of a transition time to or from Daylight
Savings (Summer) time and Standard time for the zone. */
typedef struct
{
gint64 time;
gint info_index;
} Transition;
/* GTimeZone structure */
struct _GTimeZone
{
gchar *name;
GArray *t_info; /* Array of TransitionInfo */
GArray *transitions; /* Array of Transition */
gint ref_count;
};
G_LOCK_DEFINE_STATIC (time_zones);
static GHashTable/**/ *time_zones;
#define MIN_TZYEAR 1916 /* Daylight Savings started in WWI */
#define MAX_TZYEAR 2999 /* And it's not likely ever to go away, but
there's no point in getting carried
away. */
/**
* g_time_zone_unref:
* @tz: a #GTimeZone
*
* Decreases the reference count on @tz.
*
* Since: 2.26
**/
void
g_time_zone_unref (GTimeZone *tz)
{
int ref_count;
again:
ref_count = g_atomic_int_get (&tz->ref_count);
g_assert (ref_count > 0);
if (ref_count == 1)
{
if (tz->name != NULL)
{
G_LOCK(time_zones);
/* someone else might have grabbed a ref in the meantime */
if G_UNLIKELY (g_atomic_int_get (&tz->ref_count) != 1)
{
G_UNLOCK(time_zones);
goto again;
}
g_hash_table_remove (time_zones, tz->name);
G_UNLOCK(time_zones);
}
if (tz->t_info != NULL)
{
gint idx;
for (idx = 0; idx < tz->t_info->len; idx++)
{
TransitionInfo *info = &g_array_index (tz->t_info, TransitionInfo, idx);
g_free (info->abbrev);
}
g_array_free (tz->t_info, TRUE);
}
if (tz->transitions != NULL)
g_array_free (tz->transitions, TRUE);
g_free (tz->name);
g_slice_free (GTimeZone, tz);
}
else if G_UNLIKELY (!g_atomic_int_compare_and_exchange (&tz->ref_count,
ref_count,
ref_count - 1))
goto again;
}
/**
* g_time_zone_ref:
* @tz: a #GTimeZone
*
* Increases the reference count on @tz.
*
* Returns: a new reference to @tz.
*
* Since: 2.26
**/
GTimeZone *
g_time_zone_ref (GTimeZone *tz)
{
g_assert (tz->ref_count > 0);
g_atomic_int_inc (&tz->ref_count);
return tz;
}
/* fake zoneinfo creation (for RFC3339/ISO 8601 timezones) {{{1 */
/*
* parses strings of the form h or hh[[:]mm[[[:]ss]]] where:
* - h[h] is 0 to 23
* - mm is 00 to 59
* - ss is 00 to 59
*/
static gboolean
parse_time (const gchar *time_,
gint32 *offset)
{
if (*time_ < '0' || '9' < *time_)
return FALSE;
*offset = 60 * 60 * (*time_++ - '0');
if (*time_ == '\0')
return TRUE;
if (*time_ != ':')
{
if (*time_ < '0' || '9' < *time_)
return FALSE;
*offset *= 10;
*offset += 60 * 60 * (*time_++ - '0');
if (*offset > 23 * 60 * 60)
return FALSE;
if (*time_ == '\0')
return TRUE;
}
if (*time_ == ':')
time_++;
if (*time_ < '0' || '5' < *time_)
return FALSE;
*offset += 10 * 60 * (*time_++ - '0');
if (*time_ < '0' || '9' < *time_)
return FALSE;
*offset += 60 * (*time_++ - '0');
if (*time_ == '\0')
return TRUE;
if (*time_ == ':')
time_++;
if (*time_ < '0' || '5' < *time_)
return FALSE;
*offset += 10 * (*time_++ - '0');
if (*time_ < '0' || '9' < *time_)
return FALSE;
*offset += *time_++ - '0';
return *time_ == '\0';
}
static gboolean
parse_constant_offset (const gchar *name,
gint32 *offset)
{
if (g_strcmp0 (name, "UTC") == 0)
{
*offset = 0;
return TRUE;
}
if (*name >= '0' && '9' >= *name)
return parse_time (name, offset);
switch (*name++)
{
case 'Z':
*offset = 0;
return !*name;
case '+':
return parse_time (name, offset);
case '-':
if (parse_time (name, offset))
{
*offset = -*offset;
return TRUE;
}
default:
return FALSE;
}
}
static void
zone_for_constant_offset (GTimeZone *gtz, const gchar *name)
{
gint32 offset;
TransitionInfo info;
if (name == NULL || !parse_constant_offset (name, &offset))
return;
info.gmt_offset = offset;
info.is_dst = FALSE;
info.is_standard = TRUE;
info.is_gmt = TRUE;
info.abbrev = g_strdup (name);
gtz->t_info = g_array_sized_new (FALSE, TRUE, sizeof (TransitionInfo), 1);
g_array_append_val (gtz->t_info, info);
/* Constant offset, no transitions */
gtz->transitions = NULL;
}
#ifdef G_OS_UNIX
static GBytes*
zone_info_unix (const gchar *identifier)
{
gchar *filename;
GMappedFile *file = NULL;
GBytes *zoneinfo = NULL;
/* identifier can be a relative or absolute path name;
if relative, it is interpreted starting from /usr/share/zoneinfo
while the POSIX standard says it should start with :,
glibc allows both syntaxes, so we should too */
if (identifier != NULL)
{
const gchar *tzdir;
tzdir = getenv ("TZDIR");
if (tzdir == NULL)
tzdir = "/usr/share/zoneinfo";
if (*identifier == ':')
identifier ++;
if (g_path_is_absolute (identifier))
filename = g_strdup (identifier);
else
filename = g_build_filename (tzdir, identifier, NULL);
}
else
filename = g_strdup ("/etc/localtime");
file = g_mapped_file_new (filename, FALSE, NULL);
if (file != NULL)
{
zoneinfo = g_bytes_new_with_free_func (g_mapped_file_get_contents (file),
g_mapped_file_get_length (file),
(GDestroyNotify)g_mapped_file_unref,
g_mapped_file_ref (file));
g_mapped_file_unref (file);
}
g_free (filename);
return zoneinfo;
}
static void
init_zone_from_iana_info (GTimeZone *gtz, GBytes *zoneinfo)
{
gsize size;
guint index;
guint32 time_count, type_count, leap_count, isgmt_count;
guint32 isstd_count, char_count ;
guint8 *tz_transitions, *tz_type_index, *tz_ttinfo;
guint8 *tz_leaps, *tz_isgmt, *tz_isstd;
guint8 *tz_abbrs;
gsize timesize = sizeof (gint32), countsize = sizeof (gint32);
const struct tzhead *header = g_bytes_get_data (zoneinfo, &size);
g_return_if_fail (size >= sizeof (struct tzhead) &&
memcmp (header, "TZif", 4) == 0);
if (header->tzh_version == '2')
{
/* Skip ahead to the newer 64-bit data if it's available. */
header = (const struct tzhead *)
(((const gchar *) (header + 1)) +
guint32_from_be(header->tzh_ttisgmtcnt) +
guint32_from_be(header->tzh_ttisstdcnt) +
8 * guint32_from_be(header->tzh_leapcnt) +
5 * guint32_from_be(header->tzh_timecnt) +
6 * guint32_from_be(header->tzh_typecnt) +
guint32_from_be(header->tzh_charcnt));
timesize = sizeof (gint64);
}
time_count = guint32_from_be(header->tzh_timecnt);
type_count = guint32_from_be(header->tzh_typecnt);
leap_count = guint32_from_be(header->tzh_leapcnt);
isgmt_count = guint32_from_be(header->tzh_ttisgmtcnt);
isstd_count = guint32_from_be(header->tzh_ttisstdcnt);
char_count = guint32_from_be(header->tzh_charcnt);
g_assert (type_count == isgmt_count);
g_assert (type_count == isstd_count);
tz_transitions = ((guint8 *) (header) + sizeof (*header));
tz_type_index = tz_transitions + timesize * time_count;
tz_ttinfo = tz_type_index + time_count;
tz_abbrs = tz_ttinfo + sizeof (struct ttinfo) * type_count;
tz_leaps = tz_abbrs + char_count;
tz_isstd = tz_leaps + (timesize + countsize) * leap_count;
tz_isgmt = tz_isstd + isstd_count;
gtz->t_info = g_array_sized_new (FALSE, TRUE, sizeof (TransitionInfo),
type_count);
gtz->transitions = g_array_sized_new (FALSE, TRUE, sizeof (Transition),
time_count);
for (index = 0; index < type_count; index++)
{
TransitionInfo t_info;
struct ttinfo info = ((struct ttinfo*)tz_ttinfo)[index];
t_info.gmt_offset = gint32_from_be (info.tt_gmtoff);
t_info.is_dst = info.tt_isdst ? TRUE : FALSE;
t_info.is_standard = tz_isstd[index] ? TRUE : FALSE;
t_info.is_gmt = tz_isgmt[index] ? TRUE : FALSE;
t_info.abbrev = g_strdup ((gchar *) &tz_abbrs[info.tt_abbrind]);
g_array_append_val (gtz->t_info, t_info);
}
for (index = 0; index < time_count; index++)
{
Transition trans;
if (header->tzh_version == '2')
trans.time = gint64_from_be (((gint64_be*)tz_transitions)[index]);
else
trans.time = gint32_from_be (((gint32_be*)tz_transitions)[index]);
trans.info_index = tz_type_index[index];
g_assert (trans.info_index >= 0);
g_assert (trans.info_index < gtz->t_info->len);
g_array_append_val (gtz->transitions, trans);
}
}
#elif defined (G_OS_WIN32)
static void
copy_windows_systemtime (SYSTEMTIME *s_time, TimeZoneDate *tzdate)
{
tzdate->sec = s_time->wSecond;
tzdate->min = s_time->wMinute;
tzdate->hour = s_time->wHour;
tzdate->mon = s_time->wMonth;
tzdate->year = s_time->wYear;
tzdate->wday = s_time->wDayOfWeek ? s_time->wDayOfWeek : 7;
if (s_time->wYear)
{
tzdate->mday = s_time->wDay;
tzdate->wday = 0;
}
else
tzdate->week = s_time->wDay;
}
/* UTC = local time + bias while local time = UTC + offset */
static void
rule_from_windows_time_zone_info (TimeZoneRule *rule,
TIME_ZONE_INFORMATION *tzi)
{
/* Set offset */
if (tzi->StandardDate.wMonth)
{
rule->std_offset = -(tzi->Bias + tzi->StandardBias) * 60;
rule->dlt_offset = -(tzi->Bias + tzi->DaylightBias) * 60;
copy_windows_systemtime (&(tzi->DaylightDate), &(rule->dlt_start));
copy_windows_systemtime (&(tzi->StandardDate), &(rule->dlt_end));
}
else
{
rule->std_offset = -tzi->Bias * 60;
rule->dlt_start.mon = 0;
}
strncpy (rule->std_name, (gchar*)tzi->StandardName, NAME_SIZE - 1);
strncpy (rule->dlt_name, (gchar*)tzi->DaylightName, NAME_SIZE - 1);
}
static gchar*
windows_default_tzname (void)
{
const gchar *subkey =
"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
HKEY key;
gchar *key_name = NULL;
if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey, 0,
KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
DWORD size = 0;
if (RegQueryValueExA (key, "TimeZoneKeyName", NULL, NULL,
NULL, &size) == ERROR_SUCCESS)
{
key_name = g_malloc ((gint)size);
if (RegQueryValueExA (key, "TimeZoneKeyName", NULL, NULL,
(LPBYTE)key_name, &size) != ERROR_SUCCESS)
{
g_free (key_name);
key_name = NULL;
}
}
RegCloseKey (key);
}
return key_name;
}
typedef struct
{
LONG Bias;
LONG StandardBias;
LONG DaylightBias;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
} RegTZI;
static void
system_time_copy (SYSTEMTIME *orig, SYSTEMTIME *target)
{
g_return_if_fail (orig != NULL);
g_return_if_fail (target != NULL);
target->wYear = orig->wYear;
target->wMonth = orig->wMonth;
target->wDayOfWeek = orig->wDayOfWeek;
target->wDay = orig->wDay;
target->wHour = orig->wHour;
target->wMinute = orig->wMinute;
target->wSecond = orig->wSecond;
target->wMilliseconds = orig->wMilliseconds;
}
static void
register_tzi_to_tzi (RegTZI *reg, TIME_ZONE_INFORMATION *tzi)
{
g_return_if_fail (reg != NULL);
g_return_if_fail (tzi != NULL);
tzi->Bias = reg->Bias;
system_time_copy (&(reg->StandardDate), &(tzi->StandardDate));
tzi->StandardBias = reg->StandardBias;
system_time_copy (&(reg->DaylightDate), &(tzi->DaylightDate));
tzi->DaylightBias = reg->DaylightBias;
}
static gint
rules_from_windows_time_zone (const gchar *identifier, TimeZoneRule **rules)
{
HKEY key;
gchar *subkey, *subkey_dynamic;
gchar *key_name = NULL;
const gchar *reg_key =
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\";
TIME_ZONE_INFORMATION tzi;
DWORD size;
gint rules_num = 0;
RegTZI regtzi, regtzi_prev;
*rules = NULL;
key_name = NULL;
if (!identifier)
key_name = windows_default_tzname ();
else
key_name = g_strdup (identifier);
if (!key_name)
return 0;
subkey = g_strconcat (reg_key, key_name, NULL);
subkey_dynamic = g_strconcat (subkey, "\\Dynamic DST", NULL);
if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey, 0,
KEY_QUERY_VALUE, &key) != ERROR_SUCCESS)
return 0;
size = sizeof tzi.StandardName;
if (RegQueryValueExA (key, "Std", NULL, NULL,
(LPBYTE)&(tzi.StandardName), &size) != ERROR_SUCCESS)
goto failed;
if (RegQueryValueExA (key, "Dlt", NULL, NULL,
(LPBYTE)&(tzi.DaylightName), &size) != ERROR_SUCCESS)
goto failed;
RegCloseKey (key);
if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey_dynamic, 0,
KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
DWORD first, last;
int year, i;
gchar *s;
size = sizeof first;
if (RegQueryValueExA (key, "FirstEntry", NULL, NULL,
(LPBYTE) &first, &size) != ERROR_SUCCESS)
goto failed;
size = sizeof last;
if (RegQueryValueExA (key, "LastEntry", NULL, NULL,
(LPBYTE) &last, &size) != ERROR_SUCCESS)
goto failed;
rules_num = last - first + 2;
*rules = g_new0 (TimeZoneRule, rules_num);
for (year = first, i = 0; year <= last; year++)
{
s = g_strdup_printf ("%d", year);
size = sizeof regtzi;
if (RegQueryValueExA (key, s, NULL, NULL,
(LPBYTE) ®tzi, &size) != ERROR_SUCCESS)
{
g_free (*rules);
*rules = NULL;
break;
}
g_free (s);
if (year > first && memcmp (®tzi_prev, ®tzi, sizeof regtzi) == 0)
continue;
else
memcpy (®tzi_prev, ®tzi, sizeof regtzi);
register_tzi_to_tzi (®tzi, &tzi);
rule_from_windows_time_zone_info (&(*rules)[i], &tzi);
(*rules)[i++].start_year = year;
}
rules_num = i + 1;
failed:
RegCloseKey (key);
}
else if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey, 0,
KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
size = sizeof regtzi;
if (RegQueryValueExA (key, "TZI", NULL, NULL,
(LPBYTE) ®tzi, &size) == ERROR_SUCCESS)
{
rules_num = 2;
*rules = g_new0 (TimeZoneRule, 2);
register_tzi_to_tzi (®tzi, &tzi);
rule_from_windows_time_zone_info (&(*rules)[0], &tzi);
}
RegCloseKey (key);
}
g_free (subkey_dynamic);
g_free (subkey);
g_free (key_name);
if (*rules)
{
(*rules)[0].start_year = MIN_TZYEAR;
if ((*rules)[rules_num - 2].start_year < MAX_TZYEAR)
(*rules)[rules_num - 1].start_year = MAX_TZYEAR;
else
(*rules)[rules_num - 1].start_year = (*rules)[rules_num - 2].start_year + 1;
return rules_num;
}
else
return 0;
}
#endif
static void
find_relative_date (TimeZoneDate *buffer)
{
gint wday;
GDate date;
g_date_clear (&date, 1);
wday = buffer->wday;
/* Get last day if last is needed, first day otherwise */
if (buffer->mon == 13 || buffer->mon == 14) /* Julian Date */
{
g_date_set_dmy (&date, 1, 1, buffer->year);
if (wday >= 59 && buffer->mon == 13 && g_date_is_leap_year (buffer->year))
g_date_add_days (&date, wday);
else
g_date_add_days (&date, wday - 1);
buffer->mon = (int) g_date_get_month (&date);
buffer->mday = (int) g_date_get_day (&date);
buffer->wday = 0;
}
else /* M.W.D */
{
guint days;
guint days_in_month = g_date_days_in_month (buffer->mon, buffer->year);
GDateWeekday first_wday;
g_date_set_dmy (&date, 1, buffer->mon, buffer->year);
first_wday = g_date_get_weekday (&date);
if (first_wday > wday)
++(buffer->week);
/* week is 1 <= w <= 5, we need 0-based */
days = 7 * (buffer->week - 1) + wday - first_wday;
while (days > days_in_month)
days -= 7;
g_date_add_days (&date, days);
buffer->mday = g_date_get_day (&date);
}
}
/* Offset is previous offset of local time. Returns 0 if month is 0 */
static gint64
boundary_for_year (TimeZoneDate *boundary,
gint year,
gint32 offset)
{
TimeZoneDate buffer;
GDate date;
const guint64 unix_epoch_start = 719163L;
const guint64 seconds_per_day = 86400L;
if (!boundary->mon)
return 0;
buffer = *boundary;
if (boundary->year == 0)
{
buffer.year = year;
if (buffer.wday)
find_relative_date (&buffer);
}
g_assert (buffer.year == year);
g_date_clear (&date, 1);
g_date_set_dmy (&date, buffer.mday, buffer.mon, buffer.year);
return ((g_date_get_julian (&date) - unix_epoch_start) * seconds_per_day +
buffer.hour * 3600 + buffer.min * 60 + buffer.sec - offset);
}
static void
fill_transition_info_from_rule (TransitionInfo *info,
TimeZoneRule *rule,
gboolean is_dst)
{
gint offset = is_dst ? rule->dlt_offset : rule->std_offset;
gchar *name = is_dst ? rule->dlt_name : rule->std_name;
info->gmt_offset = offset;
info->is_dst = is_dst;
info->is_standard = FALSE;
info->is_gmt = FALSE;
if (name)
info->abbrev = g_strdup (name);
else
info->abbrev = g_strdup_printf ("%+03d%02d",
(int) offset / 3600,
(int) abs (offset / 60) % 60);
}
static void
init_zone_from_rules (GTimeZone *gtz,
TimeZoneRule *rules,
gint rules_num)
{
guint type_count = 0, trans_count = 0, info_index = 0;
guint ri; /* rule index */
gboolean skip_first_std_trans = TRUE;
gint32 last_offset;
type_count = 0;
trans_count = 0;
/* Last rule only contains max year */
for (ri = 0; ri < rules_num - 1; ri++)
{
if (rules[ri].dlt_start.mon || rules[ri].dlt_end.mon)
{
guint rulespan = (rules[ri + 1].start_year - rules[ri].start_year);
guint transitions = rules[ri].dlt_start.mon > 0 ? 1 : 0;
transitions += rules[ri].dlt_end.mon > 0 ? 1 : 0;
type_count += rules[ri].dlt_start.mon > 0 ? 2 : 1;
trans_count += transitions * rulespan;
}
else
type_count++;
}
gtz->t_info = g_array_sized_new (FALSE, TRUE, sizeof (TransitionInfo), type_count);
gtz->transitions = g_array_sized_new (FALSE, TRUE, sizeof (Transition), trans_count);
last_offset = rules[0].std_offset;
for (ri = 0; ri < rules_num - 1; ri++)
{
if ((rules[ri].std_offset || rules[ri].dlt_offset) &&
rules[ri].dlt_start.mon == 0 && rules[ri].dlt_end.mon == 0)
{
TransitionInfo std_info;
/* Standard */
fill_transition_info_from_rule (&std_info, &(rules[ri]), FALSE);
g_array_append_val (gtz->t_info, std_info);
if (ri > 0 &&
((rules[ri - 1].dlt_start.mon > 12 &&
rules[ri - 1].dlt_start.wday > rules[ri - 1].dlt_end.wday) ||
rules[ri - 1].dlt_start.mon > rules[ri - 1].dlt_end.mon))
{
/* The previous rule was a southern hemisphere rule that
starts the year with DST, so we need to add a
transition to return to standard time */
guint year = rules[ri].start_year;
gint64 std_time = boundary_for_year (&rules[ri].dlt_end,
year, last_offset);
Transition std_trans = {std_time, info_index};
g_array_append_val (gtz->transitions, std_trans);
}
last_offset = rules[ri].std_offset;
++info_index;
skip_first_std_trans = TRUE;
}
else if (rules[ri].std_offset || rules[ri].dlt_offset)
{
const guint start_year = rules[ri].start_year;
const guint end_year = rules[ri + 1].start_year;
gboolean dlt_first;
guint year;
TransitionInfo std_info, dlt_info;
if (rules[ri].dlt_start.mon > 12)
dlt_first = rules[ri].dlt_start.wday > rules[ri].dlt_end.wday;
else
dlt_first = rules[ri].dlt_start.mon > rules[ri].dlt_end.mon;
/* Standard rules are always even, because before the first
transition is always standard time, and 0 is even. */
fill_transition_info_from_rule (&std_info, &(rules[ri]), FALSE);
fill_transition_info_from_rule (&dlt_info, &(rules[ri]), TRUE);
g_array_append_val (gtz->t_info, std_info);
g_array_append_val (gtz->t_info, dlt_info);
/* Transition dates. We hope that a year which ends daylight
time in a southern-hemisphere country (i.e., one that
begins the year in daylight time) will include a rule
which has only a dlt_end. */
for (year = start_year; year < end_year; year++)
{
gint32 dlt_offset = (dlt_first ? last_offset :
rules[ri].dlt_offset);
gint32 std_offset = (dlt_first ? rules[ri].std_offset :
last_offset);
/* NB: boundary_for_year returns 0 if mon == 0 */
gint64 std_time = boundary_for_year (&rules[ri].dlt_end,
year, dlt_offset);
gint64 dlt_time = boundary_for_year (&rules[ri].dlt_start,
year, std_offset);
Transition std_trans = {std_time, info_index};
Transition dlt_trans = {dlt_time, info_index + 1};
last_offset = (dlt_first ? rules[ri].dlt_offset :
rules[ri].std_offset);
if (dlt_first)
{
if (skip_first_std_trans)
skip_first_std_trans = FALSE;
else if (std_time)
g_array_append_val (gtz->transitions, std_trans);
if (dlt_time)
g_array_append_val (gtz->transitions, dlt_trans);
}
else
{
if (dlt_time)
g_array_append_val (gtz->transitions, dlt_trans);
if (std_time)
g_array_append_val (gtz->transitions, std_trans);
}
}
info_index += 2;
}
}
if (ri > 0 &&
((rules[ri - 1].dlt_start.mon > 12 &&
rules[ri - 1].dlt_start.wday > rules[ri - 1].dlt_end.wday) ||
rules[ri - 1].dlt_start.mon > rules[ri - 1].dlt_end.mon))
{
/* The previous rule was a southern hemisphere rule that
starts the year with DST, so we need to add a
transition to return to standard time */
TransitionInfo info;
guint year = rules[ri].start_year;
Transition trans;
fill_transition_info_from_rule (&info, &(rules[ri - 1]), FALSE);
g_array_append_val (gtz->t_info, info);
trans.time = boundary_for_year (&rules[ri - 1].dlt_end,
year, last_offset);
trans.info_index = info_index;
g_array_append_val (gtz->transitions, trans);
}
}
/*
* parses date[/time] for parsing TZ environment variable
*
* date is either Mm.w.d, Jn or N
* - m is 1 to 12
* - w is 1 to 5
* - d is 0 to 6
* - n is 1 to 365
* - N is 0 to 365
*
* time is either h or hh[[:]mm[[[:]ss]]]
* - h[h] is 0 to 23
* - mm is 00 to 59
* - ss is 00 to 59
*/
static gboolean
parse_mwd_boundary (gchar **pos, TimeZoneDate *boundary)
{
gint month, week, day;
if (**pos == '\0' || **pos < '0' || '9' < **pos)
return FALSE;
month = *(*pos)++ - '0';
if ((month == 1 && **pos >= '0' && '2' >= **pos) ||
(month == 0 && **pos >= '0' && '9' >= **pos))
{
month *= 10;
month += *(*pos)++ - '0';
}
if (*(*pos)++ != '.' || month == 0)
return FALSE;
if (**pos == '\0' || **pos < '1' || '5' < **pos)
return FALSE;
week = *(*pos)++ - '0';
if (*(*pos)++ != '.')
return FALSE;
if (**pos == '\0' || **pos < '0' || '6' < **pos)
return FALSE;
day = *(*pos)++ - '0';
if (!day)
day += 7;
boundary->year = 0;
boundary->mon = month;
boundary->week = week;
boundary->wday = day;
return TRUE;
}
/* Different implementations of tzset interpret the Julian day field
differently. For example, Linux specifies that it should be 1-based
(1 Jan is JD 1) for both Jn and n formats, while zOS and BSD
specify that a Jn JD is 1-based while an n JD is 0-based. Rather
than trying to follow different specs, we will follow GDate's
practice thatIn order to keep it simple, we will follow Linux's
practice. */
static gboolean
parse_julian_boundary (gchar** pos, TimeZoneDate *boundary,
gboolean ignore_leap)
{
gint day = 0;
GDate date;
while (**pos >= '0' && '9' >= **pos)
{
day *= 10;
day += *(*pos)++ - '0';
}
if (day < 1 || 365 < day)
return FALSE;
g_date_clear (&date, 1);
g_date_set_julian (&date, day);
boundary->year = 0;
boundary->mon = (int) g_date_get_month (&date);
boundary->mday = (int) g_date_get_day (&date);
boundary->wday = 0;
if (!ignore_leap && day >= 59)
boundary->mday++;
return TRUE;
}
static gboolean
parse_tz_boundary (const gchar *identifier,
TimeZoneDate *boundary)
{
gchar *pos;
pos = (gchar*)identifier;
/* Month-week-weekday */
if (*pos == 'M')
{
++pos;
if (!parse_mwd_boundary (&pos, boundary))
return FALSE;
}
/* Julian date which ignores Feb 29 in leap years */
else if (*pos == 'J')
{
++pos;
if (!parse_julian_boundary (&pos, boundary, FALSE))
return FALSE ;
}
/* Julian date which counts Feb 29 in leap years */
else if (*pos >= '0' && '9' >= *pos)
{
if (!parse_julian_boundary (&pos, boundary, TRUE))
return FALSE;
}
else
return FALSE;
/* Time */
if (*pos == '/')
{
gint32 offset;
if (!parse_time (++pos, &offset))
return FALSE;
boundary->hour = offset / 3600;
boundary->min = (offset / 60) % 60;
boundary->sec = offset % 3600;
return TRUE;
}
else
{
boundary->hour = 2;
boundary->min = 0;
boundary->sec = 0;
return *pos == '\0';
}
}
static gint
create_ruleset_from_rule (TimeZoneRule **rules, TimeZoneRule *rule)
{
*rules = g_new0 (TimeZoneRule, 2);
(*rules)[0].start_year = MIN_TZYEAR;
(*rules)[1].start_year = MAX_TZYEAR;
(*rules)[0].std_offset = -rule->std_offset;
(*rules)[0].dlt_offset = -rule->dlt_offset;
(*rules)[0].dlt_start = rule->dlt_start;
(*rules)[0].dlt_end = rule->dlt_end;
strcpy ((*rules)[0].std_name, rule->std_name);
strcpy ((*rules)[0].dlt_name, rule->dlt_name);
return 2;
}
static gboolean
parse_offset (gchar **pos, gint32 *target)
{
gchar *buffer;
gchar *target_pos = *pos;
gboolean ret;
while (**pos == '+' || **pos == '-' || **pos == ':' ||
(**pos >= '0' && '9' >= **pos))
++(*pos);
buffer = g_strndup (target_pos, *pos - target_pos);
ret = parse_constant_offset (buffer, target);
g_free (buffer);
return ret;
}
static gboolean
parse_identifier_boundary (gchar **pos, TimeZoneDate *target)
{
gchar *buffer;
gchar *target_pos = *pos;
gboolean ret;
while (**pos != ',' && **pos != '\0')
++(*pos);
buffer = g_strndup (target_pos, *pos - target_pos);
ret = parse_tz_boundary (buffer, target);
g_free (buffer);
return ret;
}
static gboolean
set_tz_name (gchar **pos, gchar *buffer, guint size)
{
gchar *name_pos = *pos;
guint len;
/* Name is ASCII alpha (Is this necessarily true?) */
while (g_ascii_isalpha (**pos))
++(*pos);
/* Name should be three or more alphabetic characters */
if (*pos - name_pos < 3)
return FALSE;
memset (buffer, 0, NAME_SIZE);
/* name_pos isn't 0-terminated, so we have to limit the length expressly */
len = *pos - name_pos > size - 1 ? size - 1 : *pos - name_pos;
strncpy (buffer, name_pos, len);
return TRUE;
}
static gboolean
parse_identifier_boundaries (gchar **pos, TimeZoneRule *tzr)
{
if (*(*pos)++ != ',')
return FALSE;
/* Start date */
if (!parse_identifier_boundary (pos, &(tzr->dlt_start)) || *(*pos)++ != ',')
return FALSE;
/* End date */
if (!parse_identifier_boundary (pos, &(tzr->dlt_end)))
return FALSE;
return TRUE;
}
/*
* Creates an array of TimeZoneRule from a TZ environment variable
* type of identifier. Should free rules afterwards
*/
static gint
rules_from_identifier (const gchar *identifier,
TimeZoneRule **rules)
{
gchar *pos;
TimeZoneRule tzr;
if (!identifier)
return 0;
pos = (gchar*)identifier;
memset (&tzr, 0, sizeof (tzr));
/* Standard offset */
if (!(set_tz_name (&pos, tzr.std_name, NAME_SIZE)) ||
!parse_offset (&pos, &(tzr.std_offset)))
return 0;
if (*pos == 0)
return create_ruleset_from_rule (rules, &tzr);
/* Format 2 */
if (!(set_tz_name (&pos, tzr.dlt_name, NAME_SIZE)))
return 0;
parse_offset (&pos, &(tzr.dlt_offset));
if (tzr.dlt_offset == 0) /* No daylight offset given, assume it's 1
hour earlier that standard */
tzr.dlt_offset = tzr.std_offset - 3600;
if (*pos == '\0')
#ifdef G_OS_WIN32
/* Windows allows us to use the US DST boundaries if they're not given */
{
int i;
guint rules_num = 0;
/* Use US rules, Windows' default is Pacific Standard Time */
if ((rules_num = rules_from_windows_time_zone ("Pacific Standard Time",
rules)))
{
for (i = 0; i < rules_num - 1; i++)
{
(*rules)[i].std_offset = - tzr.std_offset;
(*rules)[i].dlt_offset = - tzr.dlt_offset;
strcpy ((*rules)[i].std_name, tzr.std_name);
strcpy ((*rules)[i].dlt_name, tzr.dlt_name);
}
return rules_num;
}
else
return 0;
}
#else
return 0;
#endif
/* Start and end required (format 2) */
if (!parse_identifier_boundaries (&pos, &tzr))
return 0;
return create_ruleset_from_rule (rules, &tzr);
}
/* Construction {{{1 */
/**
* g_time_zone_new:
* @identifier: (allow-none): a timezone identifier
*
* Creates a #GTimeZone corresponding to @identifier.
*
* @identifier can either be an RFC3339/ISO 8601 time offset or
* something that would pass as a valid value for the
* TZ environment variable (including %NULL).
*
* In Windows, @identifier can also be the unlocalized name of a time
* zone for standard time, for example "Pacific Standard Time".
*
* Valid RFC3339 time offsets are "Z" (for UTC) or
* "±hh:mm". ISO 8601 additionally specifies
* "±hhmm" and "±hh". Offsets are
* time values to be added to Coordinated Universal Time (UTC) to get
* the local time.
*
* In Unix, the TZ environment variable typically
* corresponds to the name of a file in the zoneinfo database, or
* string in "std offset [dst [offset],start[/time],end[/time]]"
* (POSIX) format. There are no spaces in the specification. The
* name of standard and daylight savings time zone must be three or more
* alphabetic characters. Offsets are time values to be added to local
* time to get Coordinated Universal Time (UTC) and should be
* "[±]hh[[:]mm[:ss]]". Dates are either
* "Jn" (Julian day with n between 1 and 365, leap
* years not counted), "n" (zero-based Julian day
* with n between 0 and 365) or "Mm.w.d" (day d
* (0 <= d <= 6) of week w (1 <= w <= 5) of month m (1 <= m <= 12), day
* 0 is a Sunday). Times are in local wall clock time, the default is
* 02:00:00.
*
* In Windows, the "tzn[+|–]hh[:mm[:ss]][dzn]" format is used, but also
* accepts POSIX format. The Windows format uses US rules for all time
* zones; daylight savings time is 60 minutes behind the standard time
* with date and time of change taken from Pacific Standard Time.
* Offsets are time values to be added to the local time to get
* Coordinated Universal Time (UTC).
*
* g_time_zone_new_local() calls this function with the value of the
* TZ environment variable. This function itself is
* independent of the value of TZ, but if @identifier
* is %NULL then /etc/localtime will be consulted
* to discover the correct time zone on Unix and the registry will be
* consulted or GetTimeZoneInformation() will be used to get the local
* time zone on Windows.
*
* If intervals are not available, only time zone rules from
* TZ environment variable or other means, then they
* will be computed from year 1900 to 2037. If the maximum year for the
* rules is available and it is greater than 2037, then it will followed
* instead.
*
* See RFC3339
* §5.6 for a precise definition of valid RFC3339 time offsets
* (the time-offset expansion) and ISO 8601 for the
* full list of valid time offsets. See The
* GNU C Library manual for an explanation of the possible
* values of the TZ environment variable. See
* Microsoft Time Zone Index Values for the list of time zones
* on Windows.
*
* You should release the return value by calling g_time_zone_unref()
* when you are done with it.
*
* Returns: the requested timezone
*
* Since: 2.26
**/
GTimeZone *
g_time_zone_new (const gchar *identifier)
{
GTimeZone *tz = NULL;
TimeZoneRule *rules;
gint rules_num;
G_LOCK (time_zones);
if (time_zones == NULL)
time_zones = g_hash_table_new (g_str_hash, g_str_equal);
if (identifier)
{
tz = g_hash_table_lookup (time_zones, identifier);
if (tz)
{
g_atomic_int_inc (&tz->ref_count);
G_UNLOCK (time_zones);
return tz;
}
}
tz = g_slice_new0 (GTimeZone);
tz->name = g_strdup (identifier);
tz->ref_count = 0;
zone_for_constant_offset (tz, identifier);
if (tz->t_info == NULL &&
(rules_num = rules_from_identifier (identifier, &rules)))
{
init_zone_from_rules (tz, rules, rules_num);
g_free (rules);
}
if (tz->t_info == NULL)
{
#ifdef G_OS_UNIX
GBytes *zoneinfo = zone_info_unix (identifier);
if (!zoneinfo)
zone_for_constant_offset (tz, "UTC");
else
{
init_zone_from_iana_info (tz, zoneinfo);
g_bytes_unref (zoneinfo);
}
#elif defined (G_OS_WIN32)
if ((rules_num = rules_from_windows_time_zone (identifier, &rules)))
{
init_zone_from_rules (tz, rules, rules_num);
g_free (rules);
}
}
if (tz->t_info == NULL)
{
if (identifier)
zone_for_constant_offset (tz, "UTC");
else
{
TIME_ZONE_INFORMATION tzi;
if (GetTimeZoneInformation (&tzi) != TIME_ZONE_ID_INVALID)
{
rules = g_new0 (TimeZoneRule, 2);
rule_from_windows_time_zone_info (&rules[0], &tzi);
memset (rules[0].std_name, 0, NAME_SIZE);
memset (rules[0].dlt_name, 0, NAME_SIZE);
rules[0].start_year = MIN_TZYEAR;
rules[1].start_year = MAX_TZYEAR;
init_zone_from_rules (tz, rules, 2);
g_free (rules);
}
}
#endif
}
if (tz->t_info != NULL)
{
if (identifier)
g_hash_table_insert (time_zones, tz->name, tz);
}
g_atomic_int_inc (&tz->ref_count);
G_UNLOCK (time_zones);
return tz;
}
/**
* g_time_zone_new_utc:
*
* Creates a #GTimeZone corresponding to UTC.
*
* This is equivalent to calling g_time_zone_new() with a value like
* "Z", "UTC", "+00", etc.
*
* You should release the return value by calling g_time_zone_unref()
* when you are done with it.
*
* Returns: the universal timezone
*
* Since: 2.26
**/
GTimeZone *
g_time_zone_new_utc (void)
{
return g_time_zone_new ("UTC");
}
/**
* g_time_zone_new_local:
*
* Creates a #GTimeZone corresponding to local time. The local time
* zone may change between invocations to this function; for example,
* if the system administrator changes it.
*
* This is equivalent to calling g_time_zone_new() with the value of the
* TZ environment variable (including the possibility
* of %NULL).
*
* You should release the return value by calling g_time_zone_unref()
* when you are done with it.
*
* Returns: the local timezone
*
* Since: 2.26
**/
GTimeZone *
g_time_zone_new_local (void)
{
return g_time_zone_new (getenv ("TZ"));
}
#define TRANSITION(n) g_array_index (tz->transitions, Transition, n)
#define TRANSITION_INFO(n) g_array_index (tz->t_info, TransitionInfo, n)
/* Internal helpers {{{1 */
/* NB: Interval 0 is before the first transition, so there's no
* transition structure to point to which TransitionInfo to
* use. Rule-based zones are set up so that TI 0 is always standard
* time (which is what's in effect before Daylight time got started
* in the early 20th century), but IANA tzfiles don't follow that
* convention. The tzfile documentation says to use the first
* standard-time (i.e., non-DST) tinfo, so that's what we do.
*/
inline static const TransitionInfo*
interval_info (GTimeZone *tz,
guint interval)
{
guint index;
g_return_val_if_fail (tz->t_info != NULL, NULL);
if (interval && tz->transitions && interval <= tz->transitions->len)
index = (TRANSITION(interval - 1)).info_index;
else
{
for (index = 0; index < tz->t_info->len; index++)
{
TransitionInfo *tzinfo = &(TRANSITION_INFO(index));
if (!tzinfo->is_dst)
return tzinfo;
}
index = 0;
}
return &(TRANSITION_INFO(index));
}
inline static gint64
interval_start (GTimeZone *tz,
guint interval)
{
if (!interval || tz->transitions == NULL || tz->transitions->len == 0)
return G_MININT64;
if (interval > tz->transitions->len)
interval = tz->transitions->len;
return (TRANSITION(interval - 1)).time;
}
inline static gint64
interval_end (GTimeZone *tz,
guint interval)
{
if (tz->transitions && interval < tz->transitions->len)
return (TRANSITION(interval)).time - 1;
return G_MAXINT64;
}
inline static gint32
interval_offset (GTimeZone *tz,
guint interval)
{
g_return_val_if_fail (tz->t_info != NULL, 0);
return interval_info (tz, interval)->gmt_offset;
}
inline static gboolean
interval_isdst (GTimeZone *tz,
guint interval)
{
g_return_val_if_fail (tz->t_info != NULL, 0);
return interval_info (tz, interval)->is_dst;
}
inline static gboolean
interval_isgmt (GTimeZone *tz,
guint interval)
{
g_return_val_if_fail (tz->t_info != NULL, 0);
return interval_info (tz, interval)->is_gmt;
}
inline static gboolean
interval_isstandard (GTimeZone *tz,
guint interval)
{
return interval_info (tz, interval)->is_standard;
}
inline static gchar*
interval_abbrev (GTimeZone *tz,
guint interval)
{
g_return_val_if_fail (tz->t_info != NULL, 0);
return interval_info (tz, interval)->abbrev;
}
inline static gint64
interval_local_start (GTimeZone *tz,
guint interval)
{
if (interval)
return interval_start (tz, interval) + interval_offset (tz, interval);
return G_MININT64;
}
inline static gint64
interval_local_end (GTimeZone *tz,
guint interval)
{
if (tz->transitions && interval < tz->transitions->len)
return interval_end (tz, interval) + interval_offset (tz, interval);
return G_MAXINT64;
}
static gboolean
interval_valid (GTimeZone *tz,
guint interval)
{
if ( tz->transitions == NULL)
return interval == 0;
return interval <= tz->transitions->len;
}
/* g_time_zone_find_interval() {{{1 */
/**
* g_time_zone_adjust_time:
* @tz: a #GTimeZone
* @type: the #GTimeType of @time_
* @time_: a pointer to a number of seconds since January 1, 1970
*
* Finds an interval within @tz that corresponds to the given @time_,
* possibly adjusting @time_ if required to fit into an interval.
* The meaning of @time_ depends on @type.
*
* This function is similar to g_time_zone_find_interval(), with the
* difference that it always succeeds (by making the adjustments
* described below).
*
* In any of the cases where g_time_zone_find_interval() succeeds then
* this function returns the same value, without modifying @time_.
*
* This function may, however, modify @time_ in order to deal with
* non-existent times. If the non-existent local @time_ of 02:30 were
* requested on March 14th 2010 in Toronto then this function would
* adjust @time_ to be 03:00 and return the interval containing the
* adjusted time.
*
* Returns: the interval containing @time_, never -1
*
* Since: 2.26
**/
gint
g_time_zone_adjust_time (GTimeZone *tz,
GTimeType type,
gint64 *time_)
{
gint i;
guint intervals;
if (tz->transitions == NULL)
return 0;
intervals = tz->transitions->len;
/* find the interval containing *time UTC
* TODO: this could be binary searched (or better) */
for (i = 0; i <= intervals; i++)
if (*time_ <= interval_end (tz, i))
break;
g_assert (interval_start (tz, i) <= *time_ && *time_ <= interval_end (tz, i));
if (type != G_TIME_TYPE_UNIVERSAL)
{
if (*time_ < interval_local_start (tz, i))
/* if time came before the start of this interval... */
{
i--;
/* if it's not in the previous interval... */
if (*time_ > interval_local_end (tz, i))
{
/* it doesn't exist. fast-forward it. */
i++;
*time_ = interval_local_start (tz, i);
}
}
else if (*time_ > interval_local_end (tz, i))
/* if time came after the end of this interval... */
{
i++;
/* if it's not in the next interval... */
if (*time_ < interval_local_start (tz, i))
/* it doesn't exist. fast-forward it. */
*time_ = interval_local_start (tz, i);
}
else if (interval_isdst (tz, i) != type)
/* it's in this interval, but dst flag doesn't match.
* check neighbours for a better fit. */
{
if (i && *time_ <= interval_local_end (tz, i - 1))
i--;
else if (i < intervals &&
*time_ >= interval_local_start (tz, i + 1))
i++;
}
}
return i;
}
/**
* g_time_zone_find_interval:
* @tz: a #GTimeZone
* @type: the #GTimeType of @time_
* @time_: a number of seconds since January 1, 1970
*
* Finds an the interval within @tz that corresponds to the given @time_.
* The meaning of @time_ depends on @type.
*
* If @type is %G_TIME_TYPE_UNIVERSAL then this function will always
* succeed (since universal time is monotonic and continuous).
*
* Otherwise @time_ is treated is local time. The distinction between
* %G_TIME_TYPE_STANDARD and %G_TIME_TYPE_DAYLIGHT is ignored except in
* the case that the given @time_ is ambiguous. In Toronto, for example,
* 01:30 on November 7th 2010 occurred twice (once inside of daylight
* savings time and the next, an hour later, outside of daylight savings
* time). In this case, the different value of @type would result in a
* different interval being returned.
*
* It is still possible for this function to fail. In Toronto, for
* example, 02:00 on March 14th 2010 does not exist (due to the leap
* forward to begin daylight savings time). -1 is returned in that
* case.
*
* Returns: the interval containing @time_, or -1 in case of failure
*
* Since: 2.26
*/
gint
g_time_zone_find_interval (GTimeZone *tz,
GTimeType type,
gint64 time_)
{
gint i;
guint intervals;
if (tz->transitions == NULL)
return 0;
intervals = tz->transitions->len;
for (i = 0; i <= intervals; i++)
if (time_ <= interval_end (tz, i))
break;
if (type == G_TIME_TYPE_UNIVERSAL)
return i;
if (time_ < interval_local_start (tz, i))
{
if (time_ > interval_local_end (tz, --i))
return -1;
}
else if (time_ > interval_local_end (tz, i))
{
if (time_ < interval_local_start (tz, ++i))
return -1;
}
else if (interval_isdst (tz, i) != type)
{
if (i && time_ <= interval_local_end (tz, i - 1))
i--;
else if (i < intervals && time_ >= interval_local_start (tz, i + 1))
i++;
}
return i;
}
/* Public API accessors {{{1 */
/**
* g_time_zone_get_abbreviation:
* @tz: a #GTimeZone
* @interval: an interval within the timezone
*
* Determines the time zone abbreviation to be used during a particular
* @interval of time in the time zone @tz.
*
* For example, in Toronto this is currently "EST" during the winter
* months and "EDT" during the summer months when daylight savings time
* is in effect.
*
* Returns: the time zone abbreviation, which belongs to @tz
*
* Since: 2.26
**/
const gchar *
g_time_zone_get_abbreviation (GTimeZone *tz,
gint interval)
{
g_return_val_if_fail (interval_valid (tz, (guint)interval), NULL);
return interval_abbrev (tz, (guint)interval);
}
/**
* g_time_zone_get_offset:
* @tz: a #GTimeZone
* @interval: an interval within the timezone
*
* Determines the offset to UTC in effect during a particular @interval
* of time in the time zone @tz.
*
* The offset is the number of seconds that you add to UTC time to
* arrive at local time for @tz (ie: negative numbers for time zones
* west of GMT, positive numbers for east).
*
* Returns: the number of seconds that should be added to UTC to get the
* local time in @tz
*
* Since: 2.26
**/
gint32
g_time_zone_get_offset (GTimeZone *tz,
gint interval)
{
g_return_val_if_fail (interval_valid (tz, (guint)interval), 0);
return interval_offset (tz, (guint)interval);
}
/**
* g_time_zone_is_dst:
* @tz: a #GTimeZone
* @interval: an interval within the timezone
*
* Determines if daylight savings time is in effect during a particular
* @interval of time in the time zone @tz.
*
* Returns: %TRUE if daylight savings time is in effect
*
* Since: 2.26
**/
gboolean
g_time_zone_is_dst (GTimeZone *tz,
gint interval)
{
g_return_val_if_fail (interval_valid (tz, interval), FALSE);
if (tz->transitions == NULL)
return FALSE;
return interval_isdst (tz, (guint)interval);
}
/* Epilogue {{{1 */
/* vim:set foldmethod=marker: */
pkg-config-0.29.1/glib/glib/giochannel.c 0000664 0001750 0001750 00000235602 12651243552 014674 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* giochannel.c: IO Channel abstraction
* Copyright 1998 Owen Taylor
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
/*
* MT safe
*/
#include "config.h"
#include
#include
#ifdef HAVE_UNISTD_H
#include
#endif
#include "giochannel.h"
#include "gstrfuncs.h"
#include "gtestutils.h"
#include "glibintl.h"
/**
* SECTION:iochannels
* @title: IO Channels
* @short_description: portable support for using files, pipes and
* sockets
* @see_also:
* g_io_add_watch(), g_io_add_watch_full(),
* g_source_remove() Convenience
* functions for creating #GIOChannel instances and adding
* them to the main
* event loop.
*
*
* The #GIOChannel data type aims to provide a portable method for
* using file descriptors, pipes, and sockets, and integrating them
* into the main event
* loop. Currently full support is available on UNIX platforms,
* support for Windows is only partially complete.
*
* To create a new #GIOChannel on UNIX systems use
* g_io_channel_unix_new(). This works for plain file descriptors,
* pipes and sockets. Alternatively, a channel can be created for a
* file in a system independent manner using g_io_channel_new_file().
*
* Once a #GIOChannel has been created, it can be used in a generic
* manner with the functions g_io_channel_read_chars(),
* g_io_channel_write_chars(), g_io_channel_seek_position(), and
* g_io_channel_shutdown().
*
* To add a #GIOChannel to the main event loop use
* g_io_add_watch() or g_io_add_watch_full(). Here you specify which
* events you are interested in on the #GIOChannel, and provide a
* function to be called whenever these events occur.
*
* #GIOChannel instances are created with an initial reference count of
* 1. g_io_channel_ref() and g_io_channel_unref() can be used to
* increment or decrement the reference count respectively. When the
* reference count falls to 0, the #GIOChannel is freed. (Though it
* isn't closed automatically, unless it was created using
* g_io_channel_new_file().) Using g_io_add_watch() or
* g_io_add_watch_full() increments a channel's reference count.
*
* The new functions g_io_channel_read_chars(),
* g_io_channel_read_line(), g_io_channel_read_line_string(),
* g_io_channel_read_to_end(), g_io_channel_write_chars(),
* g_io_channel_seek_position(), and g_io_channel_flush() should not be
* mixed with the deprecated functions g_io_channel_read(),
* g_io_channel_write(), and g_io_channel_seek() on the same channel.
**/
/**
* GIOChannel:
*
* A data structure representing an IO Channel. The fields should be
* considered private and should only be accessed with the following
* functions.
**/
/**
* GIOFuncs:
* @io_read: reads raw bytes from the channel. This is called from
* various functions such as g_io_channel_read_chars() to
* read raw bytes from the channel. Encoding and buffering
* issues are dealt with at a higher level.
* @io_write: writes raw bytes to the channel. This is called from
* various functions such as g_io_channel_write_chars() to
* write raw bytes to the channel. Encoding and buffering
* issues are dealt with at a higher level.
* @io_seek: (optional) seeks the channel. This is called from
* g_io_channel_seek() on channels that support it.
* @io_close: closes the channel. This is called from
* g_io_channel_close() after flushing the buffers.
* @io_create_watch: creates a watch on the channel. This call
* corresponds directly to g_io_create_watch().
* @io_free: called from g_io_channel_unref() when the channel needs to
* be freed. This function must free the memory associated
* with the channel, including freeing the #GIOChannel
* structure itself. The channel buffers have been flushed
* and possibly @io_close has been called by the time this
* function is called.
* @io_set_flags: sets the #GIOFlags on the channel. This is called
* from g_io_channel_set_flags() with all flags except
* for %G_IO_FLAG_APPEND and %G_IO_FLAG_NONBLOCK masked
* out.
* @io_get_flags: gets the #GIOFlags for the channel. This function
* need only return the %G_IO_FLAG_APPEND and
* %G_IO_FLAG_NONBLOCK flags; g_io_channel_get_flags()
* automatically adds the others as appropriate.
*
* A table of functions used to handle different types of #GIOChannel
* in a generic way.
**/
/**
* GIOStatus:
* @G_IO_STATUS_ERROR: An error occurred.
* @G_IO_STATUS_NORMAL: Success.
* @G_IO_STATUS_EOF: End of file.
* @G_IO_STATUS_AGAIN: Resource temporarily unavailable.
*
* Stati returned by most of the #GIOFuncs functions.
**/
/**
* GIOError:
* @G_IO_ERROR_NONE: no error
* @G_IO_ERROR_AGAIN: an EAGAIN error occurred
* @G_IO_ERROR_INVAL: an EINVAL error occurred
* @G_IO_ERROR_UNKNOWN: another error occurred
*
* #GIOError is only used by the deprecated functions
* g_io_channel_read(), g_io_channel_write(), and g_io_channel_seek().
**/
#define G_IO_NICE_BUF_SIZE 1024
/* This needs to be as wide as the largest character in any possible encoding */
#define MAX_CHAR_SIZE 10
/* Some simplifying macros, which reduce the need to worry whether the
* buffers have been allocated. These also make USE_BUF () an lvalue,
* which is used in g_io_channel_read_to_end ().
*/
#define USE_BUF(channel) ((channel)->encoding ? (channel)->encoded_read_buf \
: (channel)->read_buf)
#define BUF_LEN(string) ((string) ? (string)->len : 0)
static GIOError g_io_error_get_from_g_error (GIOStatus status,
GError *err);
static void g_io_channel_purge (GIOChannel *channel);
static GIOStatus g_io_channel_fill_buffer (GIOChannel *channel,
GError **err);
static GIOStatus g_io_channel_read_line_backend (GIOChannel *channel,
gsize *length,
gsize *terminator_pos,
GError **error);
/**
* g_io_channel_init:
* @channel: a #GIOChannel
*
* Initializes a #GIOChannel struct.
*
* This is called by each of the above functions when creating a
* #GIOChannel, and so is not often needed by the application
* programmer (unless you are creating a new type of #GIOChannel).
*/
void
g_io_channel_init (GIOChannel *channel)
{
channel->ref_count = 1;
channel->encoding = g_strdup ("UTF-8");
channel->line_term = NULL;
channel->line_term_len = 0;
channel->buf_size = G_IO_NICE_BUF_SIZE;
channel->read_cd = (GIConv) -1;
channel->write_cd = (GIConv) -1;
channel->read_buf = NULL; /* Lazy allocate buffers */
channel->encoded_read_buf = NULL;
channel->write_buf = NULL;
channel->partial_write_buf[0] = '\0';
channel->use_buffer = TRUE;
channel->do_encode = FALSE;
channel->close_on_unref = FALSE;
}
/**
* g_io_channel_ref:
* @channel: a #GIOChannel
*
* Increments the reference count of a #GIOChannel.
*
* Returns: the @channel that was passed in (since 2.6)
*/
GIOChannel *
g_io_channel_ref (GIOChannel *channel)
{
g_return_val_if_fail (channel != NULL, NULL);
g_atomic_int_inc (&channel->ref_count);
return channel;
}
/**
* g_io_channel_unref:
* @channel: a #GIOChannel
*
* Decrements the reference count of a #GIOChannel.
*/
void
g_io_channel_unref (GIOChannel *channel)
{
gboolean is_zero;
g_return_if_fail (channel != NULL);
is_zero = g_atomic_int_dec_and_test (&channel->ref_count);
if (G_UNLIKELY (is_zero))
{
if (channel->close_on_unref)
g_io_channel_shutdown (channel, TRUE, NULL);
else
g_io_channel_purge (channel);
g_free (channel->encoding);
if (channel->read_cd != (GIConv) -1)
g_iconv_close (channel->read_cd);
if (channel->write_cd != (GIConv) -1)
g_iconv_close (channel->write_cd);
g_free (channel->line_term);
if (channel->read_buf)
g_string_free (channel->read_buf, TRUE);
if (channel->write_buf)
g_string_free (channel->write_buf, TRUE);
if (channel->encoded_read_buf)
g_string_free (channel->encoded_read_buf, TRUE);
channel->funcs->io_free (channel);
}
}
static GIOError
g_io_error_get_from_g_error (GIOStatus status,
GError *err)
{
switch (status)
{
case G_IO_STATUS_NORMAL:
case G_IO_STATUS_EOF:
return G_IO_ERROR_NONE;
case G_IO_STATUS_AGAIN:
return G_IO_ERROR_AGAIN;
case G_IO_STATUS_ERROR:
g_return_val_if_fail (err != NULL, G_IO_ERROR_UNKNOWN);
if (err->domain != G_IO_CHANNEL_ERROR)
return G_IO_ERROR_UNKNOWN;
switch (err->code)
{
case G_IO_CHANNEL_ERROR_INVAL:
return G_IO_ERROR_INVAL;
default:
return G_IO_ERROR_UNKNOWN;
}
default:
g_assert_not_reached ();
}
}
/**
* g_io_channel_read:
* @channel: a #GIOChannel
* @buf: a buffer to read the data into (which should be at least
* count bytes long)
* @count: the number of bytes to read from the #GIOChannel
* @bytes_read: returns the number of bytes actually read
*
* Reads data from a #GIOChannel.
*
* Return value: %G_IO_ERROR_NONE if the operation was successful.
*
* Deprecated:2.2: Use g_io_channel_read_chars() instead.
**/
GIOError
g_io_channel_read (GIOChannel *channel,
gchar *buf,
gsize count,
gsize *bytes_read)
{
GError *err = NULL;
GIOError error;
GIOStatus status;
g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN);
g_return_val_if_fail (bytes_read != NULL, G_IO_ERROR_UNKNOWN);
if (count == 0)
{
if (bytes_read)
*bytes_read = 0;
return G_IO_ERROR_NONE;
}
g_return_val_if_fail (buf != NULL, G_IO_ERROR_UNKNOWN);
status = channel->funcs->io_read (channel, buf, count, bytes_read, &err);
error = g_io_error_get_from_g_error (status, err);
if (err)
g_error_free (err);
return error;
}
/**
* g_io_channel_write:
* @channel: a #GIOChannel
* @buf: the buffer containing the data to write
* @count: the number of bytes to write
* @bytes_written: the number of bytes actually written
*
* Writes data to a #GIOChannel.
*
* Return value: %G_IO_ERROR_NONE if the operation was successful.
*
* Deprecated:2.2: Use g_io_channel_write_chars() instead.
**/
GIOError
g_io_channel_write (GIOChannel *channel,
const gchar *buf,
gsize count,
gsize *bytes_written)
{
GError *err = NULL;
GIOError error;
GIOStatus status;
g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN);
g_return_val_if_fail (bytes_written != NULL, G_IO_ERROR_UNKNOWN);
status = channel->funcs->io_write (channel, buf, count, bytes_written, &err);
error = g_io_error_get_from_g_error (status, err);
if (err)
g_error_free (err);
return error;
}
/**
* g_io_channel_seek:
* @channel: a #GIOChannel
* @offset: an offset, in bytes, which is added to the position specified
* by @type
* @type: the position in the file, which can be %G_SEEK_CUR (the current
* position), %G_SEEK_SET (the start of the file), or %G_SEEK_END
* (the end of the file)
*
* Sets the current position in the #GIOChannel, similar to the standard
* library function fseek().
*
* Return value: %G_IO_ERROR_NONE if the operation was successful.
*
* Deprecated:2.2: Use g_io_channel_seek_position() instead.
**/
GIOError
g_io_channel_seek (GIOChannel *channel,
gint64 offset,
GSeekType type)
{
GError *err = NULL;
GIOError error;
GIOStatus status;
g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN);
g_return_val_if_fail (channel->is_seekable, G_IO_ERROR_UNKNOWN);
switch (type)
{
case G_SEEK_CUR:
case G_SEEK_SET:
case G_SEEK_END:
break;
default:
g_warning ("g_io_channel_seek: unknown seek type");
return G_IO_ERROR_UNKNOWN;
}
status = channel->funcs->io_seek (channel, offset, type, &err);
error = g_io_error_get_from_g_error (status, err);
if (err)
g_error_free (err);
return error;
}
/* The function g_io_channel_new_file() is prototyped in both
* giounix.c and giowin32.c, so we stick its documentation here.
*/
/**
* g_io_channel_new_file:
* @filename: A string containing the name of a file
* @mode: One of "r", "w", "a", "r+", "w+", "a+". These have
* the same meaning as in fopen()
* @error: A location to return an error of type %G_FILE_ERROR
*
* Open a file @filename as a #GIOChannel using mode @mode. This
* channel will be closed when the last reference to it is dropped,
* so there is no need to call g_io_channel_close() (though doing
* so will not cause problems, as long as no attempt is made to
* access the channel after it is closed).
*
* Return value: A #GIOChannel on success, %NULL on failure.
**/
/**
* g_io_channel_close:
* @channel: A #GIOChannel
*
* Close an IO channel. Any pending data to be written will be
* flushed, ignoring errors. The channel will not be freed until the
* last reference is dropped using g_io_channel_unref().
*
* Deprecated:2.2: Use g_io_channel_shutdown() instead.
**/
void
g_io_channel_close (GIOChannel *channel)
{
GError *err = NULL;
g_return_if_fail (channel != NULL);
g_io_channel_purge (channel);
channel->funcs->io_close (channel, &err);
if (err)
{ /* No way to return the error */
g_warning ("Error closing channel: %s", err->message);
g_error_free (err);
}
channel->close_on_unref = FALSE; /* Because we already did */
channel->is_readable = FALSE;
channel->is_writeable = FALSE;
channel->is_seekable = FALSE;
}
/**
* g_io_channel_shutdown:
* @channel: a #GIOChannel
* @flush: if %TRUE, flush pending
* @err: location to store a #GIOChannelError
*
* Close an IO channel. Any pending data to be written will be
* flushed if @flush is %TRUE. The channel will not be freed until the
* last reference is dropped using g_io_channel_unref().
*
* Return value: the status of the operation.
**/
GIOStatus
g_io_channel_shutdown (GIOChannel *channel,
gboolean flush,
GError **err)
{
GIOStatus status, result;
GError *tmperr = NULL;
g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail (err == NULL || *err == NULL, G_IO_STATUS_ERROR);
if (channel->write_buf && channel->write_buf->len > 0)
{
if (flush)
{
GIOFlags flags;
/* Set the channel to blocking, to avoid a busy loop
*/
flags = g_io_channel_get_flags (channel);
/* Ignore any errors here, they're irrelevant */
g_io_channel_set_flags (channel, flags & ~G_IO_FLAG_NONBLOCK, NULL);
result = g_io_channel_flush (channel, &tmperr);
}
else
result = G_IO_STATUS_NORMAL;
g_string_truncate(channel->write_buf, 0);
}
else
result = G_IO_STATUS_NORMAL;
if (channel->partial_write_buf[0] != '\0')
{
if (flush)
g_warning ("Partial character at end of write buffer not flushed.\n");
channel->partial_write_buf[0] = '\0';
}
status = channel->funcs->io_close (channel, err);
channel->close_on_unref = FALSE; /* Because we already did */
channel->is_readable = FALSE;
channel->is_writeable = FALSE;
channel->is_seekable = FALSE;
if (status != G_IO_STATUS_NORMAL)
{
g_clear_error (&tmperr);
return status;
}
else if (result != G_IO_STATUS_NORMAL)
{
g_propagate_error (err, tmperr);
return result;
}
else
return G_IO_STATUS_NORMAL;
}
/* This function is used for the final flush on close or unref */
static void
g_io_channel_purge (GIOChannel *channel)
{
GError *err = NULL;
GIOStatus status G_GNUC_UNUSED;
g_return_if_fail (channel != NULL);
if (channel->write_buf && channel->write_buf->len > 0)
{
GIOFlags flags;
/* Set the channel to blocking, to avoid a busy loop
*/
flags = g_io_channel_get_flags (channel);
g_io_channel_set_flags (channel, flags & ~G_IO_FLAG_NONBLOCK, NULL);
status = g_io_channel_flush (channel, &err);
if (err)
{ /* No way to return the error */
g_warning ("Error flushing string: %s", err->message);
g_error_free (err);
}
}
/* Flush these in case anyone tries to close without unrefing */
if (channel->read_buf)
g_string_truncate (channel->read_buf, 0);
if (channel->write_buf)
g_string_truncate (channel->write_buf, 0);
if (channel->encoding)
{
if (channel->encoded_read_buf)
g_string_truncate (channel->encoded_read_buf, 0);
if (channel->partial_write_buf[0] != '\0')
{
g_warning ("Partial character at end of write buffer not flushed.\n");
channel->partial_write_buf[0] = '\0';
}
}
}
/**
* g_io_create_watch:
* @channel: a #GIOChannel to watch
* @condition: conditions to watch for
*
* Creates a #GSource that's dispatched when @condition is met for the
* given @channel. For example, if condition is #G_IO_IN, the source will
* be dispatched when there's data available for reading.
*
* g_io_add_watch() is a simpler interface to this same functionality, for
* the case where you want to add the source to the default main loop context
* at the default priority.
*
* On Windows, polling a #GSource created to watch a channel for a socket
* puts the socket in non-blocking mode. This is a side-effect of the
* implementation and unavoidable.
*
* Returns: a new #GSource
*/
GSource *
g_io_create_watch (GIOChannel *channel,
GIOCondition condition)
{
g_return_val_if_fail (channel != NULL, NULL);
return channel->funcs->io_create_watch (channel, condition);
}
/**
* g_io_add_watch_full:
* @channel: a #GIOChannel
* @priority: the priority of the #GIOChannel source
* @condition: the condition to watch for
* @func: the function to call when the condition is satisfied
* @user_data: user data to pass to @func
* @notify: the function to call when the source is removed
*
* Adds the #GIOChannel into the default main loop context
* with the given priority.
*
* This internally creates a main loop source using g_io_create_watch()
* and attaches it to the main loop context with g_source_attach().
* You can do these steps manually if you need greater control.
*
* Returns: the event source id
* Rename to: g_io_add_watch
*/
guint
g_io_add_watch_full (GIOChannel *channel,
gint priority,
GIOCondition condition,
GIOFunc func,
gpointer user_data,
GDestroyNotify notify)
{
GSource *source;
guint id;
g_return_val_if_fail (channel != NULL, 0);
source = g_io_create_watch (channel, condition);
if (priority != G_PRIORITY_DEFAULT)
g_source_set_priority (source, priority);
g_source_set_callback (source, (GSourceFunc)func, user_data, notify);
id = g_source_attach (source, NULL);
g_source_unref (source);
return id;
}
/**
* g_io_add_watch:
* @channel: a #GIOChannel
* @condition: the condition to watch for
* @func: the function to call when the condition is satisfied
* @user_data: user data to pass to @func
*
* Adds the #GIOChannel into the default main loop context
* with the default priority.
*
* Returns: the event source id
*/
/**
* GIOFunc:
* @source: the #GIOChannel event source
* @condition: the condition which has been satisfied
* @data: user data set in g_io_add_watch() or g_io_add_watch_full()
*
* Specifies the type of function passed to g_io_add_watch() or
* g_io_add_watch_full(), which is called when the requested condition
* on a #GIOChannel is satisfied.
*
* Returns: the function should return %FALSE if the event source
* should be removed
**/
/**
* GIOCondition:
* @G_IO_IN: There is data to read.
* @G_IO_OUT: Data can be written (without blocking).
* @G_IO_PRI: There is urgent data to read.
* @G_IO_ERR: Error condition.
* @G_IO_HUP: Hung up (the connection has been broken, usually for
* pipes and sockets).
* @G_IO_NVAL: Invalid request. The file descriptor is not open.
*
* A bitwise combination representing a condition to watch for on an
* event source.
**/
guint
g_io_add_watch (GIOChannel *channel,
GIOCondition condition,
GIOFunc func,
gpointer user_data)
{
return g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, condition, func, user_data, NULL);
}
/**
* g_io_channel_get_buffer_condition:
* @channel: A #GIOChannel
*
* This function returns a #GIOCondition depending on whether there
* is data to be read/space to write data in the internal buffers in
* the #GIOChannel. Only the flags %G_IO_IN and %G_IO_OUT may be set.
*
* Return value: A #GIOCondition
**/
GIOCondition
g_io_channel_get_buffer_condition (GIOChannel *channel)
{
GIOCondition condition = 0;
if (channel->encoding)
{
if (channel->encoded_read_buf && (channel->encoded_read_buf->len > 0))
condition |= G_IO_IN; /* Only return if we have full characters */
}
else
{
if (channel->read_buf && (channel->read_buf->len > 0))
condition |= G_IO_IN;
}
if (channel->write_buf && (channel->write_buf->len < channel->buf_size))
condition |= G_IO_OUT;
return condition;
}
/**
* g_io_channel_error_from_errno:
* @en: an errno error number, e.g. EINVAL
*
* Converts an errno error number to a #GIOChannelError.
*
* Return value: a #GIOChannelError error number, e.g.
* %G_IO_CHANNEL_ERROR_INVAL.
**/
GIOChannelError
g_io_channel_error_from_errno (gint en)
{
#ifdef EAGAIN
g_return_val_if_fail (en != EAGAIN, G_IO_CHANNEL_ERROR_FAILED);
#endif
switch (en)
{
#ifdef EBADF
case EBADF:
g_warning("Invalid file descriptor.\n");
return G_IO_CHANNEL_ERROR_FAILED;
#endif
#ifdef EFAULT
case EFAULT:
g_warning("Buffer outside valid address space.\n");
return G_IO_CHANNEL_ERROR_FAILED;
#endif
#ifdef EFBIG
case EFBIG:
return G_IO_CHANNEL_ERROR_FBIG;
#endif
#ifdef EINTR
/* In general, we should catch EINTR before we get here,
* but close() is allowed to return EINTR by POSIX, so
* we need to catch it here; EINTR from close() is
* unrecoverable, because it's undefined whether
* the fd was actually closed or not, so we just return
* a generic error code.
*/
case EINTR:
return G_IO_CHANNEL_ERROR_FAILED;
#endif
#ifdef EINVAL
case EINVAL:
return G_IO_CHANNEL_ERROR_INVAL;
#endif
#ifdef EIO
case EIO:
return G_IO_CHANNEL_ERROR_IO;
#endif
#ifdef EISDIR
case EISDIR:
return G_IO_CHANNEL_ERROR_ISDIR;
#endif
#ifdef ENOSPC
case ENOSPC:
return G_IO_CHANNEL_ERROR_NOSPC;
#endif
#ifdef ENXIO
case ENXIO:
return G_IO_CHANNEL_ERROR_NXIO;
#endif
#ifdef EOVERFLOW
#if EOVERFLOW != EFBIG
case EOVERFLOW:
return G_IO_CHANNEL_ERROR_OVERFLOW;
#endif
#endif
#ifdef EPIPE
case EPIPE:
return G_IO_CHANNEL_ERROR_PIPE;
#endif
default:
return G_IO_CHANNEL_ERROR_FAILED;
}
}
/**
* g_io_channel_set_buffer_size:
* @channel: a #GIOChannel
* @size: the size of the buffer, or 0 to let GLib pick a good size
*
* Sets the buffer size.
**/
void
g_io_channel_set_buffer_size (GIOChannel *channel,
gsize size)
{
g_return_if_fail (channel != NULL);
if (size == 0)
size = G_IO_NICE_BUF_SIZE;
if (size < MAX_CHAR_SIZE)
size = MAX_CHAR_SIZE;
channel->buf_size = size;
}
/**
* g_io_channel_get_buffer_size:
* @channel: a #GIOChannel
*
* Gets the buffer size.
*
* Return value: the size of the buffer.
**/
gsize
g_io_channel_get_buffer_size (GIOChannel *channel)
{
g_return_val_if_fail (channel != NULL, 0);
return channel->buf_size;
}
/**
* g_io_channel_set_line_term:
* @channel: a #GIOChannel
* @line_term: (allow-none): The line termination string. Use %NULL for
* autodetect. Autodetection breaks on "\n", "\r\n", "\r", "\0",
* and the Unicode paragraph separator. Autodetection should not be
* used for anything other than file-based channels.
* @length: The length of the termination string. If -1 is passed, the
* string is assumed to be nul-terminated. This option allows
* termination strings with embedded nuls.
*
* This sets the string that #GIOChannel uses to determine
* where in the file a line break occurs.
**/
void
g_io_channel_set_line_term (GIOChannel *channel,
const gchar *line_term,
gint length)
{
g_return_if_fail (channel != NULL);
g_return_if_fail (line_term == NULL || length != 0); /* Disallow "" */
if (line_term == NULL)
length = 0;
else if (length < 0)
length = strlen (line_term);
g_free (channel->line_term);
channel->line_term = line_term ? g_memdup (line_term, length) : NULL;
channel->line_term_len = length;
}
/**
* g_io_channel_get_line_term:
* @channel: a #GIOChannel
* @length: a location to return the length of the line terminator
*
* This returns the string that #GIOChannel uses to determine
* where in the file a line break occurs. A value of %NULL
* indicates autodetection.
*
* Return value: The line termination string. This value
* is owned by GLib and must not be freed.
**/
const gchar *
g_io_channel_get_line_term (GIOChannel *channel,
gint *length)
{
g_return_val_if_fail (channel != NULL, NULL);
if (length)
*length = channel->line_term_len;
return channel->line_term;
}
/**
* g_io_channel_set_flags:
* @channel: a #GIOChannel
* @flags: the flags to set on the IO channel
* @error: A location to return an error of type #GIOChannelError
*
* Sets the (writeable) flags in @channel to (@flags & %G_IO_FLAG_SET_MASK).
*
* Return value: the status of the operation.
**/
/**
* GIOFlags:
* @G_IO_FLAG_APPEND: turns on append mode, corresponds to O_APPEND
* (see the documentation of the UNIX open()
* syscall).
* @G_IO_FLAG_NONBLOCK: turns on nonblocking mode, corresponds to
* O_NONBLOCK/O_NDELAY
* (see the documentation of the UNIX open() syscall).
* @G_IO_FLAG_IS_READABLE: indicates that the io channel is readable.
* This flag cannot be changed.
* @G_IO_FLAG_IS_WRITABLE: indicates that the io channel is writable.
* This flag cannot be changed.
* @G_IO_FLAG_IS_SEEKABLE: indicates that the io channel is seekable,
* i.e. that g_io_channel_seek_position() can
* be used on it. This flag cannot be changed.
* @G_IO_FLAG_MASK: the mask that specifies all the valid flags.
* @G_IO_FLAG_GET_MASK: the mask of the flags that are returned from
* g_io_channel_get_flags().
* @G_IO_FLAG_SET_MASK: the mask of the flags that the user can modify
* with g_io_channel_set_flags().
*
* Specifies properties of a #GIOChannel. Some of the flags can only be
* read with g_io_channel_get_flags(), but not changed with
* g_io_channel_set_flags().
**/
/**
* G_IO_FLAG_IS_WRITEABLE:
*
* This is a misspelled version of G_IO_FLAG_IS_WRITABLE that existed
* before the spelling was fixed in GLib 2.30. It is kept here for
* compatibility reasons.
*
* Deprecated:2.30:Use G_IO_FLAG_IS_WRITABLE instead.
**/
GIOStatus
g_io_channel_set_flags (GIOChannel *channel,
GIOFlags flags,
GError **error)
{
g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail ((error == NULL) || (*error == NULL),
G_IO_STATUS_ERROR);
return (*channel->funcs->io_set_flags) (channel,
flags & G_IO_FLAG_SET_MASK,
error);
}
/**
* g_io_channel_get_flags:
* @channel: a #GIOChannel
*
* Gets the current flags for a #GIOChannel, including read-only
* flags such as %G_IO_FLAG_IS_READABLE.
*
* The values of the flags %G_IO_FLAG_IS_READABLE and %G_IO_FLAG_IS_WRITABLE
* are cached for internal use by the channel when it is created.
* If they should change at some later point (e.g. partial shutdown
* of a socket with the UNIX shutdown() function), the user
* should immediately call g_io_channel_get_flags() to update
* the internal values of these flags.
*
* Return value: the flags which are set on the channel
**/
GIOFlags
g_io_channel_get_flags (GIOChannel *channel)
{
GIOFlags flags;
g_return_val_if_fail (channel != NULL, 0);
flags = (* channel->funcs->io_get_flags) (channel);
/* Cross implementation code */
if (channel->is_seekable)
flags |= G_IO_FLAG_IS_SEEKABLE;
if (channel->is_readable)
flags |= G_IO_FLAG_IS_READABLE;
if (channel->is_writeable)
flags |= G_IO_FLAG_IS_WRITABLE;
return flags;
}
/**
* g_io_channel_set_close_on_unref:
* @channel: a #GIOChannel
* @do_close: Whether to close the channel on the final unref of
* the GIOChannel data structure. The default value of
* this is %TRUE for channels created by g_io_channel_new_file (),
* and %FALSE for all other channels.
*
* Setting this flag to %TRUE for a channel you have already closed
* can cause problems.
**/
void
g_io_channel_set_close_on_unref (GIOChannel *channel,
gboolean do_close)
{
g_return_if_fail (channel != NULL);
channel->close_on_unref = do_close;
}
/**
* g_io_channel_get_close_on_unref:
* @channel: a #GIOChannel.
*
* Returns whether the file/socket/whatever associated with @channel
* will be closed when @channel receives its final unref and is
* destroyed. The default value of this is %TRUE for channels created
* by g_io_channel_new_file (), and %FALSE for all other channels.
*
* Return value: Whether the channel will be closed on the final unref of
* the GIOChannel data structure.
**/
gboolean
g_io_channel_get_close_on_unref (GIOChannel *channel)
{
g_return_val_if_fail (channel != NULL, FALSE);
return channel->close_on_unref;
}
/**
* g_io_channel_seek_position:
* @channel: a #GIOChannel
* @offset: The offset in bytes from the position specified by @type
* @type: a #GSeekType. The type %G_SEEK_CUR is only allowed in those
* cases where a call to g_io_channel_set_encoding ()
* is allowed. See the documentation for
* g_io_channel_set_encoding () for details.
* @error: A location to return an error of type #GIOChannelError
*
* Replacement for g_io_channel_seek() with the new API.
*
* Return value: the status of the operation.
**/
/**
* GSeekType:
* @G_SEEK_CUR: the current position in the file.
* @G_SEEK_SET: the start of the file.
* @G_SEEK_END: the end of the file.
*
* An enumeration specifying the base position for a
* g_io_channel_seek_position() operation.
**/
GIOStatus
g_io_channel_seek_position (GIOChannel *channel,
gint64 offset,
GSeekType type,
GError **error)
{
GIOStatus status;
/* For files, only one of the read and write buffers can contain data.
* For sockets, both can contain data.
*/
g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail ((error == NULL) || (*error == NULL),
G_IO_STATUS_ERROR);
g_return_val_if_fail (channel->is_seekable, G_IO_STATUS_ERROR);
switch (type)
{
case G_SEEK_CUR: /* The user is seeking relative to the head of the buffer */
if (channel->use_buffer)
{
if (channel->do_encode && channel->encoded_read_buf
&& channel->encoded_read_buf->len > 0)
{
g_warning ("Seek type G_SEEK_CUR not allowed for this"
" channel's encoding.\n");
return G_IO_STATUS_ERROR;
}
if (channel->read_buf)
offset -= channel->read_buf->len;
if (channel->encoded_read_buf)
{
g_assert (channel->encoded_read_buf->len == 0 || !channel->do_encode);
/* If there's anything here, it's because the encoding is UTF-8,
* so we can just subtract the buffer length, the same as for
* the unencoded data.
*/
offset -= channel->encoded_read_buf->len;
}
}
break;
case G_SEEK_SET:
case G_SEEK_END:
break;
default:
g_warning ("g_io_channel_seek_position: unknown seek type");
return G_IO_STATUS_ERROR;
}
if (channel->use_buffer)
{
status = g_io_channel_flush (channel, error);
if (status != G_IO_STATUS_NORMAL)
return status;
}
status = channel->funcs->io_seek (channel, offset, type, error);
if ((status == G_IO_STATUS_NORMAL) && (channel->use_buffer))
{
if (channel->read_buf)
g_string_truncate (channel->read_buf, 0);
/* Conversion state no longer matches position in file */
if (channel->read_cd != (GIConv) -1)
g_iconv (channel->read_cd, NULL, NULL, NULL, NULL);
if (channel->write_cd != (GIConv) -1)
g_iconv (channel->write_cd, NULL, NULL, NULL, NULL);
if (channel->encoded_read_buf)
{
g_assert (channel->encoded_read_buf->len == 0 || !channel->do_encode);
g_string_truncate (channel->encoded_read_buf, 0);
}
if (channel->partial_write_buf[0] != '\0')
{
g_warning ("Partial character at end of write buffer not flushed.\n");
channel->partial_write_buf[0] = '\0';
}
}
return status;
}
/**
* g_io_channel_flush:
* @channel: a #GIOChannel
* @error: location to store an error of type #GIOChannelError
*
* Flushes the write buffer for the GIOChannel.
*
* Return value: the status of the operation: One of
* #G_IO_STATUS_NORMAL, #G_IO_STATUS_AGAIN, or
* #G_IO_STATUS_ERROR.
**/
GIOStatus
g_io_channel_flush (GIOChannel *channel,
GError **error)
{
GIOStatus status;
gsize this_time = 1, bytes_written = 0;
g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR);
if (channel->write_buf == NULL || channel->write_buf->len == 0)
return G_IO_STATUS_NORMAL;
do
{
g_assert (this_time > 0);
status = channel->funcs->io_write (channel,
channel->write_buf->str + bytes_written,
channel->write_buf->len - bytes_written,
&this_time, error);
bytes_written += this_time;
}
while ((bytes_written < channel->write_buf->len)
&& (status == G_IO_STATUS_NORMAL));
g_string_erase (channel->write_buf, 0, bytes_written);
return status;
}
/**
* g_io_channel_set_buffered:
* @channel: a #GIOChannel
* @buffered: whether to set the channel buffered or unbuffered
*
* The buffering state can only be set if the channel's encoding
* is %NULL. For any other encoding, the channel must be buffered.
*
* A buffered channel can only be set unbuffered if the channel's
* internal buffers have been flushed. Newly created channels or
* channels which have returned %G_IO_STATUS_EOF
* not require such a flush. For write-only channels, a call to
* g_io_channel_flush () is sufficient. For all other channels,
* the buffers may be flushed by a call to g_io_channel_seek_position ().
* This includes the possibility of seeking with seek type %G_SEEK_CUR
* and an offset of zero. Note that this means that socket-based
* channels cannot be set unbuffered once they have had data
* read from them.
*
* On unbuffered channels, it is safe to mix read and write
* calls from the new and old APIs, if this is necessary for
* maintaining old code.
*
* The default state of the channel is buffered.
**/
void
g_io_channel_set_buffered (GIOChannel *channel,
gboolean buffered)
{
g_return_if_fail (channel != NULL);
if (channel->encoding != NULL)
{
g_warning ("Need to have NULL encoding to set the buffering state of the "
"channel.\n");
return;
}
g_return_if_fail (!channel->read_buf || channel->read_buf->len == 0);
g_return_if_fail (!channel->write_buf || channel->write_buf->len == 0);
channel->use_buffer = buffered;
}
/**
* g_io_channel_get_buffered:
* @channel: a #GIOChannel
*
* Returns whether @channel is buffered.
*
* Return Value: %TRUE if the @channel is buffered.
**/
gboolean
g_io_channel_get_buffered (GIOChannel *channel)
{
g_return_val_if_fail (channel != NULL, FALSE);
return channel->use_buffer;
}
/**
* g_io_channel_set_encoding:
* @channel: a #GIOChannel
* @encoding: (allow-none): the encoding type
* @error: location to store an error of type #GConvertError
*
* Sets the encoding for the input/output of the channel.
* The internal encoding is always UTF-8. The default encoding
* for the external file is UTF-8.
*
* The encoding %NULL is safe to use with binary data.
*
* The encoding can only be set if one of the following conditions
* is true:
*
*
* The channel was just created, and has not been written to or read
* from yet.
*
*
* The channel is write-only.
*
*
* The channel is a file, and the file pointer was just
* repositioned by a call to g_io_channel_seek_position().
* (This flushes all the internal buffers.)
*
*
* The current encoding is %NULL or UTF-8.
*
*
* One of the (new API) read functions has just returned %G_IO_STATUS_EOF
* (or, in the case of g_io_channel_read_to_end(), %G_IO_STATUS_NORMAL).
*
*
* One of the functions g_io_channel_read_chars() or
* g_io_channel_read_unichar() has returned %G_IO_STATUS_AGAIN or
* %G_IO_STATUS_ERROR. This may be useful in the case of
* %G_CONVERT_ERROR_ILLEGAL_SEQUENCE.
* Returning one of these statuses from g_io_channel_read_line(),
* g_io_channel_read_line_string(), or g_io_channel_read_to_end()
* does not guarantee that the encoding can
* be changed.
*
*
* Channels which do not meet one of the above conditions cannot call
* g_io_channel_seek_position() with an offset of %G_SEEK_CUR, and, if
* they are "seekable", cannot call g_io_channel_write_chars() after
* calling one of the API "read" functions.
*
* Return Value: %G_IO_STATUS_NORMAL if the encoding was successfully set.
**/
GIOStatus
g_io_channel_set_encoding (GIOChannel *channel,
const gchar *encoding,
GError **error)
{
GIConv read_cd, write_cd;
gboolean did_encode;
g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR);
/* Make sure the encoded buffers are empty */
g_return_val_if_fail (!channel->do_encode || !channel->encoded_read_buf ||
channel->encoded_read_buf->len == 0, G_IO_STATUS_ERROR);
if (!channel->use_buffer)
{
g_warning ("Need to set the channel buffered before setting the encoding.\n");
g_warning ("Assuming this is what you meant and acting accordingly.\n");
channel->use_buffer = TRUE;
}
if (channel->partial_write_buf[0] != '\0')
{
g_warning ("Partial character at end of write buffer not flushed.\n");
channel->partial_write_buf[0] = '\0';
}
did_encode = channel->do_encode;
if (!encoding || strcmp (encoding, "UTF8") == 0 || strcmp (encoding, "UTF-8") == 0)
{
channel->do_encode = FALSE;
read_cd = write_cd = (GIConv) -1;
}
else
{
gint err = 0;
const gchar *from_enc = NULL, *to_enc = NULL;
if (channel->is_readable)
{
read_cd = g_iconv_open ("UTF-8", encoding);
if (read_cd == (GIConv) -1)
{
err = errno;
from_enc = encoding;
to_enc = "UTF-8";
}
}
else
read_cd = (GIConv) -1;
if (channel->is_writeable && err == 0)
{
write_cd = g_iconv_open (encoding, "UTF-8");
if (write_cd == (GIConv) -1)
{
err = errno;
from_enc = "UTF-8";
to_enc = encoding;
}
}
else
write_cd = (GIConv) -1;
if (err != 0)
{
g_assert (from_enc);
g_assert (to_enc);
if (err == EINVAL)
g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_NO_CONVERSION,
_("Conversion from character set '%s' to '%s' is not supported"),
from_enc, to_enc);
else
g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
_("Could not open converter from '%s' to '%s': %s"),
from_enc, to_enc, g_strerror (err));
if (read_cd != (GIConv) -1)
g_iconv_close (read_cd);
if (write_cd != (GIConv) -1)
g_iconv_close (write_cd);
return G_IO_STATUS_ERROR;
}
channel->do_encode = TRUE;
}
/* The encoding is ok, so set the fields in channel */
if (channel->read_cd != (GIConv) -1)
g_iconv_close (channel->read_cd);
if (channel->write_cd != (GIConv) -1)
g_iconv_close (channel->write_cd);
if (channel->encoded_read_buf && channel->encoded_read_buf->len > 0)
{
g_assert (!did_encode); /* Encoding UTF-8, NULL doesn't use encoded_read_buf */
/* This is just validated UTF-8, so we can copy it back into read_buf
* so it can be encoded in whatever the new encoding is.
*/
g_string_prepend_len (channel->read_buf, channel->encoded_read_buf->str,
channel->encoded_read_buf->len);
g_string_truncate (channel->encoded_read_buf, 0);
}
channel->read_cd = read_cd;
channel->write_cd = write_cd;
g_free (channel->encoding);
channel->encoding = g_strdup (encoding);
return G_IO_STATUS_NORMAL;
}
/**
* g_io_channel_get_encoding:
* @channel: a #GIOChannel
*
* Gets the encoding for the input/output of the channel.
* The internal encoding is always UTF-8. The encoding %NULL
* makes the channel safe for binary data.
*
* Return value: A string containing the encoding, this string is
* owned by GLib and must not be freed.
**/
const gchar *
g_io_channel_get_encoding (GIOChannel *channel)
{
g_return_val_if_fail (channel != NULL, NULL);
return channel->encoding;
}
static GIOStatus
g_io_channel_fill_buffer (GIOChannel *channel,
GError **err)
{
gsize read_size, cur_len, oldlen;
GIOStatus status;
if (channel->is_seekable && channel->write_buf && channel->write_buf->len > 0)
{
status = g_io_channel_flush (channel, err);
if (status != G_IO_STATUS_NORMAL)
return status;
}
if (channel->is_seekable && channel->partial_write_buf[0] != '\0')
{
g_warning ("Partial character at end of write buffer not flushed.\n");
channel->partial_write_buf[0] = '\0';
}
if (!channel->read_buf)
channel->read_buf = g_string_sized_new (channel->buf_size);
cur_len = channel->read_buf->len;
g_string_set_size (channel->read_buf, channel->read_buf->len + channel->buf_size);
status = channel->funcs->io_read (channel, channel->read_buf->str + cur_len,
channel->buf_size, &read_size, err);
g_assert ((status == G_IO_STATUS_NORMAL) || (read_size == 0));
g_string_truncate (channel->read_buf, read_size + cur_len);
if ((status != G_IO_STATUS_NORMAL) &&
((status != G_IO_STATUS_EOF) || (channel->read_buf->len == 0)))
return status;
g_assert (channel->read_buf->len > 0);
if (channel->encoded_read_buf)
oldlen = channel->encoded_read_buf->len;
else
{
oldlen = 0;
if (channel->encoding)
channel->encoded_read_buf = g_string_sized_new (channel->buf_size);
}
if (channel->do_encode)
{
gsize errnum, inbytes_left, outbytes_left;
gchar *inbuf, *outbuf;
int errval;
g_assert (channel->encoded_read_buf);
reencode:
inbytes_left = channel->read_buf->len;
outbytes_left = MAX (channel->read_buf->len,
channel->encoded_read_buf->allocated_len
- channel->encoded_read_buf->len - 1); /* 1 for NULL */
outbytes_left = MAX (outbytes_left, 6);
inbuf = channel->read_buf->str;
g_string_set_size (channel->encoded_read_buf,
channel->encoded_read_buf->len + outbytes_left);
outbuf = channel->encoded_read_buf->str + channel->encoded_read_buf->len
- outbytes_left;
errnum = g_iconv (channel->read_cd, &inbuf, &inbytes_left,
&outbuf, &outbytes_left);
errval = errno;
g_assert (inbuf + inbytes_left == channel->read_buf->str
+ channel->read_buf->len);
g_assert (outbuf + outbytes_left == channel->encoded_read_buf->str
+ channel->encoded_read_buf->len);
g_string_erase (channel->read_buf, 0,
channel->read_buf->len - inbytes_left);
g_string_truncate (channel->encoded_read_buf,
channel->encoded_read_buf->len - outbytes_left);
if (errnum == (gsize) -1)
{
switch (errval)
{
case EINVAL:
if ((oldlen == channel->encoded_read_buf->len)
&& (status == G_IO_STATUS_EOF))
status = G_IO_STATUS_EOF;
else
status = G_IO_STATUS_NORMAL;
break;
case E2BIG:
/* Buffer size at least 6, wrote at least on character */
g_assert (inbuf != channel->read_buf->str);
goto reencode;
case EILSEQ:
if (oldlen < channel->encoded_read_buf->len)
status = G_IO_STATUS_NORMAL;
else
{
g_set_error_literal (err, G_CONVERT_ERROR,
G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
_("Invalid byte sequence in conversion input"));
return G_IO_STATUS_ERROR;
}
break;
default:
g_assert (errval != EBADF); /* The converter should be open */
g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
_("Error during conversion: %s"), g_strerror (errval));
return G_IO_STATUS_ERROR;
}
}
g_assert ((status != G_IO_STATUS_NORMAL)
|| (channel->encoded_read_buf->len > 0));
}
else if (channel->encoding) /* UTF-8 */
{
gchar *nextchar, *lastchar;
g_assert (channel->encoded_read_buf);
nextchar = channel->read_buf->str;
lastchar = channel->read_buf->str + channel->read_buf->len;
while (nextchar < lastchar)
{
gunichar val_char;
val_char = g_utf8_get_char_validated (nextchar, lastchar - nextchar);
switch (val_char)
{
case -2:
/* stop, leave partial character in buffer */
lastchar = nextchar;
break;
case -1:
if (oldlen < channel->encoded_read_buf->len)
status = G_IO_STATUS_NORMAL;
else
{
g_set_error_literal (err, G_CONVERT_ERROR,
G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
_("Invalid byte sequence in conversion input"));
status = G_IO_STATUS_ERROR;
}
lastchar = nextchar;
break;
default:
nextchar = g_utf8_next_char (nextchar);
break;
}
}
if (lastchar > channel->read_buf->str)
{
gint copy_len = lastchar - channel->read_buf->str;
g_string_append_len (channel->encoded_read_buf, channel->read_buf->str,
copy_len);
g_string_erase (channel->read_buf, 0, copy_len);
}
}
return status;
}
/**
* g_io_channel_read_line:
* @channel: a #GIOChannel
* @str_return: (out): The line read from the #GIOChannel, including the
* line terminator. This data should be freed with g_free()
* when no longer needed. This is a nul-terminated string.
* If a @length of zero is returned, this will be %NULL instead.
* @length: (allow-none) (out): location to store length of the read data, or %NULL
* @terminator_pos: (allow-none) (out): location to store position of line terminator, or %NULL
* @error: A location to return an error of type #GConvertError
* or #GIOChannelError
*
* Reads a line, including the terminating character(s),
* from a #GIOChannel into a newly-allocated string.
* @str_return will contain allocated memory if the return
* is %G_IO_STATUS_NORMAL.
*
* Return value: the status of the operation.
**/
GIOStatus
g_io_channel_read_line (GIOChannel *channel,
gchar **str_return,
gsize *length,
gsize *terminator_pos,
GError **error)
{
GIOStatus status;
gsize got_length;
g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail (str_return != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail ((error == NULL) || (*error == NULL),
G_IO_STATUS_ERROR);
g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
status = g_io_channel_read_line_backend (channel, &got_length, terminator_pos, error);
if (length)
*length = got_length;
if (status == G_IO_STATUS_NORMAL)
{
g_assert (USE_BUF (channel));
*str_return = g_strndup (USE_BUF (channel)->str, got_length);
g_string_erase (USE_BUF (channel), 0, got_length);
}
else
*str_return = NULL;
return status;
}
/**
* g_io_channel_read_line_string:
* @channel: a #GIOChannel
* @buffer: a #GString into which the line will be written.
* If @buffer already contains data, the old data will
* be overwritten.
* @terminator_pos: (allow-none): location to store position of line terminator, or %NULL
* @error: a location to store an error of type #GConvertError
* or #GIOChannelError
*
* Reads a line from a #GIOChannel, using a #GString as a buffer.
*
* Return value: the status of the operation.
**/
GIOStatus
g_io_channel_read_line_string (GIOChannel *channel,
GString *buffer,
gsize *terminator_pos,
GError **error)
{
gsize length;
GIOStatus status;
g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail (buffer != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail ((error == NULL) || (*error == NULL),
G_IO_STATUS_ERROR);
g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
if (buffer->len > 0)
g_string_truncate (buffer, 0); /* clear out the buffer */
status = g_io_channel_read_line_backend (channel, &length, terminator_pos, error);
if (status == G_IO_STATUS_NORMAL)
{
g_assert (USE_BUF (channel));
g_string_append_len (buffer, USE_BUF (channel)->str, length);
g_string_erase (USE_BUF (channel), 0, length);
}
return status;
}
static GIOStatus
g_io_channel_read_line_backend (GIOChannel *channel,
gsize *length,
gsize *terminator_pos,
GError **error)
{
GIOStatus status;
gsize checked_to, line_term_len, line_length, got_term_len;
gboolean first_time = TRUE;
if (!channel->use_buffer)
{
/* Can't do a raw read in read_line */
g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
_("Can't do a raw read in g_io_channel_read_line_string"));
return G_IO_STATUS_ERROR;
}
status = G_IO_STATUS_NORMAL;
if (channel->line_term)
line_term_len = channel->line_term_len;
else
line_term_len = 3;
/* This value used for setting checked_to, it's the longest of the four
* we autodetect for.
*/
checked_to = 0;
while (TRUE)
{
gchar *nextchar, *lastchar;
GString *use_buf;
if (!first_time || (BUF_LEN (USE_BUF (channel)) == 0))
{
read_again:
status = g_io_channel_fill_buffer (channel, error);
switch (status)
{
case G_IO_STATUS_NORMAL:
if (BUF_LEN (USE_BUF (channel)) == 0)
/* Can happen when using conversion and only read
* part of a character
*/
{
first_time = FALSE;
continue;
}
break;
case G_IO_STATUS_EOF:
if (BUF_LEN (USE_BUF (channel)) == 0)
{
if (length)
*length = 0;
if (channel->encoding && channel->read_buf->len != 0)
{
g_set_error_literal (error, G_CONVERT_ERROR,
G_CONVERT_ERROR_PARTIAL_INPUT,
_("Leftover unconverted data in "
"read buffer"));
return G_IO_STATUS_ERROR;
}
else
return G_IO_STATUS_EOF;
}
break;
default:
if (length)
*length = 0;
return status;
}
}
g_assert (BUF_LEN (USE_BUF (channel)) != 0);
use_buf = USE_BUF (channel); /* The buffer has been created by this point */
first_time = FALSE;
lastchar = use_buf->str + use_buf->len;
for (nextchar = use_buf->str + checked_to; nextchar < lastchar;
channel->encoding ? nextchar = g_utf8_next_char (nextchar) : nextchar++)
{
if (channel->line_term)
{
if (memcmp (channel->line_term, nextchar, line_term_len) == 0)
{
line_length = nextchar - use_buf->str;
got_term_len = line_term_len;
goto done;
}
}
else /* auto detect */
{
switch (*nextchar)
{
case '\n': /* unix */
line_length = nextchar - use_buf->str;
got_term_len = 1;
goto done;
case '\r': /* Warning: do not use with sockets */
line_length = nextchar - use_buf->str;
if ((nextchar == lastchar - 1) && (status != G_IO_STATUS_EOF)
&& (lastchar == use_buf->str + use_buf->len))
goto read_again; /* Try to read more data */
if ((nextchar < lastchar - 1) && (*(nextchar + 1) == '\n')) /* dos */
got_term_len = 2;
else /* mac */
got_term_len = 1;
goto done;
case '\xe2': /* Unicode paragraph separator */
if (strncmp ("\xe2\x80\xa9", nextchar, 3) == 0)
{
line_length = nextchar - use_buf->str;
got_term_len = 3;
goto done;
}
break;
case '\0': /* Embeded null in input */
line_length = nextchar - use_buf->str;
got_term_len = 1;
goto done;
default: /* no match */
break;
}
}
}
/* If encoding != NULL, valid UTF-8, didn't overshoot */
g_assert (nextchar == lastchar);
/* Check for EOF */
if (status == G_IO_STATUS_EOF)
{
if (channel->encoding && channel->read_buf->len > 0)
{
g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
_("Channel terminates in a partial character"));
return G_IO_STATUS_ERROR;
}
line_length = use_buf->len;
got_term_len = 0;
break;
}
if (use_buf->len > line_term_len - 1)
checked_to = use_buf->len - (line_term_len - 1);
else
checked_to = 0;
}
done:
if (terminator_pos)
*terminator_pos = line_length;
if (length)
*length = line_length + got_term_len;
return G_IO_STATUS_NORMAL;
}
/**
* g_io_channel_read_to_end:
* @channel: a #GIOChannel
* @str_return: (out) (array length=length) (element-type guint8): Location to
* store a pointer to a string holding the remaining data in the
* #GIOChannel. This data should be freed with g_free() when no
* longer needed. This data is terminated by an extra nul
* character, but there may be other nuls in the intervening data.
* @length: (out): location to store length of the data
* @error: location to return an error of type #GConvertError
* or #GIOChannelError
*
* Reads all the remaining data from the file.
*
* Return value: %G_IO_STATUS_NORMAL on success.
* This function never returns %G_IO_STATUS_EOF.
**/
GIOStatus
g_io_channel_read_to_end (GIOChannel *channel,
gchar **str_return,
gsize *length,
GError **error)
{
GIOStatus status;
g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail ((error == NULL) || (*error == NULL),
G_IO_STATUS_ERROR);
g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
if (str_return)
*str_return = NULL;
if (length)
*length = 0;
if (!channel->use_buffer)
{
g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
_("Can't do a raw read in g_io_channel_read_to_end"));
return G_IO_STATUS_ERROR;
}
do
status = g_io_channel_fill_buffer (channel, error);
while (status == G_IO_STATUS_NORMAL);
if (status != G_IO_STATUS_EOF)
return status;
if (channel->encoding && channel->read_buf->len > 0)
{
g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
_("Channel terminates in a partial character"));
return G_IO_STATUS_ERROR;
}
if (USE_BUF (channel) == NULL)
{
/* length is already set to zero */
if (str_return)
*str_return = g_strdup ("");
}
else
{
if (length)
*length = USE_BUF (channel)->len;
if (str_return)
*str_return = g_string_free (USE_BUF (channel), FALSE);
else
g_string_free (USE_BUF (channel), TRUE);
if (channel->encoding)
channel->encoded_read_buf = NULL;
else
channel->read_buf = NULL;
}
return G_IO_STATUS_NORMAL;
}
/**
* g_io_channel_read_chars:
* @channel: a #GIOChannel
* @buf: (out caller-allocates) (array length=count) (element-type guint8):
* a buffer to read data into
* @count: (in): the size of the buffer. Note that the buffer may not be
* complelely filled even if there is data in the buffer if the
* remaining data is not a complete character.
* @bytes_read: (allow-none) (out): The number of bytes read. This may be
* zero even on success if count < 6 and the channel's encoding
* is non-%NULL. This indicates that the next UTF-8 character is
* too wide for the buffer.
* @error: a location to return an error of type #GConvertError
* or #GIOChannelError.
*
* Replacement for g_io_channel_read() with the new API.
*
* Return value: the status of the operation.
*/
GIOStatus
g_io_channel_read_chars (GIOChannel *channel,
gchar *buf,
gsize count,
gsize *bytes_read,
GError **error)
{
GIOStatus status;
gsize got_bytes;
g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR);
g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
if (count == 0)
{
if (bytes_read)
*bytes_read = 0;
return G_IO_STATUS_NORMAL;
}
g_return_val_if_fail (buf != NULL, G_IO_STATUS_ERROR);
if (!channel->use_buffer)
{
gsize tmp_bytes;
g_assert (!channel->read_buf || channel->read_buf->len == 0);
status = channel->funcs->io_read (channel, buf, count, &tmp_bytes, error);
if (bytes_read)
*bytes_read = tmp_bytes;
return status;
}
status = G_IO_STATUS_NORMAL;
while (BUF_LEN (USE_BUF (channel)) < count && status == G_IO_STATUS_NORMAL)
status = g_io_channel_fill_buffer (channel, error);
/* Only return an error if we have no data */
if (BUF_LEN (USE_BUF (channel)) == 0)
{
g_assert (status != G_IO_STATUS_NORMAL);
if (status == G_IO_STATUS_EOF && channel->encoding
&& BUF_LEN (channel->read_buf) > 0)
{
g_set_error_literal (error, G_CONVERT_ERROR,
G_CONVERT_ERROR_PARTIAL_INPUT,
_("Leftover unconverted data in read buffer"));
status = G_IO_STATUS_ERROR;
}
if (bytes_read)
*bytes_read = 0;
return status;
}
if (status == G_IO_STATUS_ERROR)
g_clear_error (error);
got_bytes = MIN (count, BUF_LEN (USE_BUF (channel)));
g_assert (got_bytes > 0);
if (channel->encoding)
/* Don't validate for NULL encoding, binary safe */
{
gchar *nextchar, *prevchar;
g_assert (USE_BUF (channel) == channel->encoded_read_buf);
nextchar = channel->encoded_read_buf->str;
do
{
prevchar = nextchar;
nextchar = g_utf8_next_char (nextchar);
g_assert (nextchar != prevchar); /* Possible for *prevchar of -1 or -2 */
}
while (nextchar < channel->encoded_read_buf->str + got_bytes);
if (nextchar > channel->encoded_read_buf->str + got_bytes)
got_bytes = prevchar - channel->encoded_read_buf->str;
g_assert (got_bytes > 0 || count < 6);
}
memcpy (buf, USE_BUF (channel)->str, got_bytes);
g_string_erase (USE_BUF (channel), 0, got_bytes);
if (bytes_read)
*bytes_read = got_bytes;
return G_IO_STATUS_NORMAL;
}
/**
* g_io_channel_read_unichar:
* @channel: a #GIOChannel
* @thechar: (out): a location to return a character
* @error: a location to return an error of type #GConvertError
* or #GIOChannelError
*
* Reads a Unicode character from @channel.
* This function cannot be called on a channel with %NULL encoding.
*
* Return value: a #GIOStatus
**/
GIOStatus
g_io_channel_read_unichar (GIOChannel *channel,
gunichar *thechar,
GError **error)
{
GIOStatus status = G_IO_STATUS_NORMAL;
g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail (channel->encoding != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail ((error == NULL) || (*error == NULL),
G_IO_STATUS_ERROR);
g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
while (BUF_LEN (channel->encoded_read_buf) == 0 && status == G_IO_STATUS_NORMAL)
status = g_io_channel_fill_buffer (channel, error);
/* Only return an error if we have no data */
if (BUF_LEN (USE_BUF (channel)) == 0)
{
g_assert (status != G_IO_STATUS_NORMAL);
if (status == G_IO_STATUS_EOF && BUF_LEN (channel->read_buf) > 0)
{
g_set_error_literal (error, G_CONVERT_ERROR,
G_CONVERT_ERROR_PARTIAL_INPUT,
_("Leftover unconverted data in read buffer"));
status = G_IO_STATUS_ERROR;
}
if (thechar)
*thechar = (gunichar) -1;
return status;
}
if (status == G_IO_STATUS_ERROR)
g_clear_error (error);
if (thechar)
*thechar = g_utf8_get_char (channel->encoded_read_buf->str);
g_string_erase (channel->encoded_read_buf, 0,
g_utf8_next_char (channel->encoded_read_buf->str)
- channel->encoded_read_buf->str);
return G_IO_STATUS_NORMAL;
}
/**
* g_io_channel_write_chars:
* @channel: a #GIOChannel
* @buf: (array) (element-type guint8): a buffer to write data from
* @count: the size of the buffer. If -1, the buffer
* is taken to be a nul-terminated string.
* @bytes_written: (out): The number of bytes written. This can be nonzero
* even if the return value is not %G_IO_STATUS_NORMAL.
* If the return value is %G_IO_STATUS_NORMAL and the
* channel is blocking, this will always be equal
* to @count if @count >= 0.
* @error: a location to return an error of type #GConvertError
* or #GIOChannelError
*
* Replacement for g_io_channel_write() with the new API.
*
* On seekable channels with encodings other than %NULL or UTF-8, generic
* mixing of reading and writing is not allowed. A call to g_io_channel_write_chars ()
* may only be made on a channel from which data has been read in the
* cases described in the documentation for g_io_channel_set_encoding ().
*
* Return value: the status of the operation.
**/
GIOStatus
g_io_channel_write_chars (GIOChannel *channel,
const gchar *buf,
gssize count,
gsize *bytes_written,
GError **error)
{
GIOStatus status;
gssize wrote_bytes = 0;
g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail ((error == NULL) || (*error == NULL),
G_IO_STATUS_ERROR);
g_return_val_if_fail (channel->is_writeable, G_IO_STATUS_ERROR);
if ((count < 0) && buf)
count = strlen (buf);
if (count == 0)
{
if (bytes_written)
*bytes_written = 0;
return G_IO_STATUS_NORMAL;
}
g_return_val_if_fail (buf != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail (count > 0, G_IO_STATUS_ERROR);
/* Raw write case */
if (!channel->use_buffer)
{
gsize tmp_bytes;
g_assert (!channel->write_buf || channel->write_buf->len == 0);
g_assert (channel->partial_write_buf[0] == '\0');
status = channel->funcs->io_write (channel, buf, count, &tmp_bytes, error);
if (bytes_written)
*bytes_written = tmp_bytes;
return status;
}
/* General case */
if (channel->is_seekable && (( BUF_LEN (channel->read_buf) > 0)
|| (BUF_LEN (channel->encoded_read_buf) > 0)))
{
if (channel->do_encode && BUF_LEN (channel->encoded_read_buf) > 0)
{
g_warning("Mixed reading and writing not allowed on encoded files");
return G_IO_STATUS_ERROR;
}
status = g_io_channel_seek_position (channel, 0, G_SEEK_CUR, error);
if (status != G_IO_STATUS_NORMAL)
{
if (bytes_written)
*bytes_written = 0;
return status;
}
}
if (!channel->write_buf)
channel->write_buf = g_string_sized_new (channel->buf_size);
while (wrote_bytes < count)
{
gsize space_in_buf;
/* If the buffer is full, try a write immediately. In
* the nonblocking case, this prevents the user from
* writing just a little bit to the buffer every time
* and never receiving an EAGAIN.
*/
if (channel->write_buf->len >= channel->buf_size - MAX_CHAR_SIZE)
{
gsize did_write = 0, this_time;
do
{
status = channel->funcs->io_write (channel, channel->write_buf->str
+ did_write, channel->write_buf->len
- did_write, &this_time, error);
did_write += this_time;
}
while (status == G_IO_STATUS_NORMAL &&
did_write < MIN (channel->write_buf->len, MAX_CHAR_SIZE));
g_string_erase (channel->write_buf, 0, did_write);
if (status != G_IO_STATUS_NORMAL)
{
if (status == G_IO_STATUS_AGAIN && wrote_bytes > 0)
status = G_IO_STATUS_NORMAL;
if (bytes_written)
*bytes_written = wrote_bytes;
return status;
}
}
space_in_buf = MAX (channel->buf_size, channel->write_buf->allocated_len - 1)
- channel->write_buf->len; /* 1 for NULL */
/* This is only true because g_io_channel_set_buffer_size ()
* ensures that channel->buf_size >= MAX_CHAR_SIZE.
*/
g_assert (space_in_buf >= MAX_CHAR_SIZE);
if (!channel->encoding)
{
gssize write_this = MIN (space_in_buf, count - wrote_bytes);
g_string_append_len (channel->write_buf, buf, write_this);
buf += write_this;
wrote_bytes += write_this;
}
else
{
const gchar *from_buf;
gsize from_buf_len, from_buf_old_len, left_len;
gsize err;
gint errnum;
if (channel->partial_write_buf[0] != '\0')
{
g_assert (wrote_bytes == 0);
from_buf = channel->partial_write_buf;
from_buf_old_len = strlen (channel->partial_write_buf);
g_assert (from_buf_old_len > 0);
from_buf_len = MIN (6, from_buf_old_len + count);
memcpy (channel->partial_write_buf + from_buf_old_len, buf,
from_buf_len - from_buf_old_len);
}
else
{
from_buf = buf;
from_buf_len = count - wrote_bytes;
from_buf_old_len = 0;
}
reconvert:
if (!channel->do_encode) /* UTF-8 encoding */
{
const gchar *badchar;
gsize try_len = MIN (from_buf_len, space_in_buf);
/* UTF-8, just validate, emulate g_iconv */
if (!g_utf8_validate (from_buf, try_len, &badchar))
{
gunichar try_char;
gsize incomplete_len = from_buf + try_len - badchar;
left_len = from_buf + from_buf_len - badchar;
try_char = g_utf8_get_char_validated (badchar, incomplete_len);
switch (try_char)
{
case -2:
g_assert (incomplete_len < 6);
if (try_len == from_buf_len)
{
errnum = EINVAL;
err = (gsize) -1;
}
else
{
errnum = 0;
err = (gsize) 0;
}
break;
case -1:
g_warning ("Invalid UTF-8 passed to g_io_channel_write_chars().");
/* FIXME bail here? */
errnum = EILSEQ;
err = (gsize) -1;
break;
default:
g_assert_not_reached ();
err = (gsize) -1;
errnum = 0; /* Don't confunse the compiler */
}
}
else
{
err = (gsize) 0;
errnum = 0;
left_len = from_buf_len - try_len;
}
g_string_append_len (channel->write_buf, from_buf,
from_buf_len - left_len);
from_buf += from_buf_len - left_len;
}
else
{
gchar *outbuf;
left_len = from_buf_len;
g_string_set_size (channel->write_buf, channel->write_buf->len
+ space_in_buf);
outbuf = channel->write_buf->str + channel->write_buf->len
- space_in_buf;
err = g_iconv (channel->write_cd, (gchar **) &from_buf, &left_len,
&outbuf, &space_in_buf);
errnum = errno;
g_string_truncate (channel->write_buf, channel->write_buf->len
- space_in_buf);
}
if (err == (gsize) -1)
{
switch (errnum)
{
case EINVAL:
g_assert (left_len < 6);
if (from_buf_old_len == 0)
{
/* Not from partial_write_buf */
memcpy (channel->partial_write_buf, from_buf, left_len);
channel->partial_write_buf[left_len] = '\0';
if (bytes_written)
*bytes_written = count;
return G_IO_STATUS_NORMAL;
}
/* Working in partial_write_buf */
if (left_len == from_buf_len)
{
/* Didn't convert anything, must still have
* less than a full character
*/
g_assert (count == from_buf_len - from_buf_old_len);
channel->partial_write_buf[from_buf_len] = '\0';
if (bytes_written)
*bytes_written = count;
return G_IO_STATUS_NORMAL;
}
g_assert (from_buf_len - left_len >= from_buf_old_len);
/* We converted all the old data. This is fine */
break;
case E2BIG:
if (from_buf_len == left_len)
{
/* Nothing was written, add enough space for
* at least one character.
*/
space_in_buf += MAX_CHAR_SIZE;
goto reconvert;
}
break;
case EILSEQ:
g_set_error_literal (error, G_CONVERT_ERROR,
G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
_("Invalid byte sequence in conversion input"));
if (from_buf_old_len > 0 && from_buf_len == left_len)
g_warning ("Illegal sequence due to partial character "
"at the end of a previous write.\n");
else
wrote_bytes += from_buf_len - left_len - from_buf_old_len;
if (bytes_written)
*bytes_written = wrote_bytes;
channel->partial_write_buf[0] = '\0';
return G_IO_STATUS_ERROR;
default:
g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
_("Error during conversion: %s"), g_strerror (errnum));
if (from_buf_len >= left_len + from_buf_old_len)
wrote_bytes += from_buf_len - left_len - from_buf_old_len;
if (bytes_written)
*bytes_written = wrote_bytes;
channel->partial_write_buf[0] = '\0';
return G_IO_STATUS_ERROR;
}
}
g_assert (from_buf_len - left_len >= from_buf_old_len);
wrote_bytes += from_buf_len - left_len - from_buf_old_len;
if (from_buf_old_len > 0)
{
/* We were working in partial_write_buf */
buf += from_buf_len - left_len - from_buf_old_len;
channel->partial_write_buf[0] = '\0';
}
else
buf = from_buf;
}
}
if (bytes_written)
*bytes_written = count;
return G_IO_STATUS_NORMAL;
}
/**
* g_io_channel_write_unichar:
* @channel: a #GIOChannel
* @thechar: a character
* @error: location to return an error of type #GConvertError
* or #GIOChannelError
*
* Writes a Unicode character to @channel.
* This function cannot be called on a channel with %NULL encoding.
*
* Return value: a #GIOStatus
**/
GIOStatus
g_io_channel_write_unichar (GIOChannel *channel,
gunichar thechar,
GError **error)
{
GIOStatus status;
gchar static_buf[6];
gsize char_len, wrote_len;
g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail (channel->encoding != NULL, G_IO_STATUS_ERROR);
g_return_val_if_fail ((error == NULL) || (*error == NULL),
G_IO_STATUS_ERROR);
g_return_val_if_fail (channel->is_writeable, G_IO_STATUS_ERROR);
char_len = g_unichar_to_utf8 (thechar, static_buf);
if (channel->partial_write_buf[0] != '\0')
{
g_warning ("Partial charater written before writing unichar.\n");
channel->partial_write_buf[0] = '\0';
}
status = g_io_channel_write_chars (channel, static_buf,
char_len, &wrote_len, error);
/* We validate UTF-8, so we can't get a partial write */
g_assert (wrote_len == char_len || status != G_IO_STATUS_NORMAL);
return status;
}
/**
* g_io_channel_error_quark:
*
* Return value: the quark used as %G_IO_CHANNEL_ERROR
**/
/**
* G_IO_CHANNEL_ERROR:
*
* Error domain for #GIOChannel operations. Errors in this domain will
* be from the #GIOChannelError enumeration. See #GError for
* information on error domains.
**/
/**
* GIOChannelError:
* @G_IO_CHANNEL_ERROR_FBIG: File too large.
* @G_IO_CHANNEL_ERROR_INVAL: Invalid argument.
* @G_IO_CHANNEL_ERROR_IO: IO error.
* @G_IO_CHANNEL_ERROR_ISDIR: File is a directory.
* @G_IO_CHANNEL_ERROR_NOSPC: No space left on device.
* @G_IO_CHANNEL_ERROR_NXIO: No such device or address.
* @G_IO_CHANNEL_ERROR_OVERFLOW: Value too large for defined datatype.
* @G_IO_CHANNEL_ERROR_PIPE: Broken pipe.
* @G_IO_CHANNEL_ERROR_FAILED: Some other error.
*
* Error codes returned by #GIOChannel operations.
**/
G_DEFINE_QUARK (g-io-channel-error-quark, g_io_channel_error)
pkg-config-0.29.1/glib/glib/gfileutils.c 0000664 0001750 0001750 00000210315 12651243552 014726 0000000 0000000 /* gfileutils.c - File utility functions
*
* Copyright 2000 Red Hat, Inc.
*
* GLib 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 of the
* License, or (at your option) any later version.
*
* GLib 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 GLib; see the file COPYING.LIB. If not,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "glibconfig.h"
#include
#ifdef HAVE_UNISTD_H
#include
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef G_OS_WIN32
#include
#include
#endif /* G_OS_WIN32 */
#ifndef S_ISLNK
#define S_ISLNK(x) 0
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#include "gfileutils.h"
#include "gstdio.h"
#include "glibintl.h"
#ifdef HAVE_LINUX_MAGIC_H /* for btrfs check */
#include
#include
#endif
/**
* SECTION:fileutils
* @title: File Utilities
* @short_description: various file-related functions
*
* There is a group of functions which wrap the common POSIX functions
* dealing with filenames (g_open(), g_rename(), g_mkdir(), g_stat(),
* g_unlink(), g_remove(), g_fopen(), g_freopen()). The point of these
* wrappers is to make it possible to handle file names with any Unicode
* characters in them on Windows without having to use ifdefs and the
* wide character API in the application code.
*
* The pathname argument should be in the GLib file name encoding.
* On POSIX this is the actual on-disk encoding which might correspond
* to the locale settings of the process (or the
* G_FILENAME_ENCODING environment variable), or not.
*
* On Windows the GLib file name encoding is UTF-8. Note that the
* Microsoft C library does not use UTF-8, but has separate APIs for
* current system code page and wide characters (UTF-16). The GLib
* wrappers call the wide character API if present (on modern Windows
* systems), otherwise convert to/from the system code page.
*
* Another group of functions allows to open and read directories
* in the GLib file name encoding. These are g_dir_open(),
* g_dir_read_name(), g_dir_rewind(), g_dir_close().
*/
/**
* GFileError:
* @G_FILE_ERROR_EXIST: Operation not permitted; only the owner of
* the file (or other resource) or processes with special privileges
* can perform the operation.
* @G_FILE_ERROR_ISDIR: File is a directory; you cannot open a directory
* for writing, or create or remove hard links to it.
* @G_FILE_ERROR_ACCES: Permission denied; the file permissions do not
* allow the attempted operation.
* @G_FILE_ERROR_NAMETOOLONG: Filename too long.
* @G_FILE_ERROR_NOENT: No such file or directory. This is a "file
* doesn't exist" error for ordinary files that are referenced in
* contexts where they are expected to already exist.
* @G_FILE_ERROR_NOTDIR: A file that isn't a directory was specified when
* a directory is required.
* @G_FILE_ERROR_NXIO: No such device or address. The system tried to
* use the device represented by a file you specified, and it
* couldn't find the device. This can mean that the device file was
* installed incorrectly, or that the physical device is missing or
* not correctly attached to the computer.
* @G_FILE_ERROR_NODEV: The underlying file system of the specified file
* does not support memory mapping.
* @G_FILE_ERROR_ROFS: The directory containing the new link can't be
* modified because it's on a read-only file system.
* @G_FILE_ERROR_TXTBSY: Text file busy.
* @G_FILE_ERROR_FAULT: You passed in a pointer to bad memory.
* (GLib won't reliably return this, don't pass in pointers to bad
* memory.)
* @G_FILE_ERROR_LOOP: Too many levels of symbolic links were encountered
* in looking up a file name. This often indicates a cycle of symbolic
* links.
* @G_FILE_ERROR_NOSPC: No space left on device; write operation on a
* file failed because the disk is full.
* @G_FILE_ERROR_NOMEM: No memory available. The system cannot allocate
* more virtual memory because its capacity is full.
* @G_FILE_ERROR_MFILE: The current process has too many files open and
* can't open any more. Duplicate descriptors do count toward this
* limit.
* @G_FILE_ERROR_NFILE: There are too many distinct file openings in the
* entire system.
* @G_FILE_ERROR_BADF: Bad file descriptor; for example, I/O on a
* descriptor that has been closed or reading from a descriptor open
* only for writing (or vice versa).
* @G_FILE_ERROR_INVAL: Invalid argument. This is used to indicate
* various kinds of problems with passing the wrong argument to a
* library function.
* @G_FILE_ERROR_PIPE: Broken pipe; there is no process reading from the
* other end of a pipe. Every library function that returns this
* error code also generates a 'SIGPIPE' signal; this signal
* terminates the program if not handled or blocked. Thus, your
* program will never actually see this code unless it has handled
* or blocked 'SIGPIPE'.
* @G_FILE_ERROR_AGAIN: Resource temporarily unavailable; the call might
* work if you try again later.
* @G_FILE_ERROR_INTR: Interrupted function call; an asynchronous signal
* occurred and prevented completion of the call. When this
* happens, you should try the call again.
* @G_FILE_ERROR_IO: Input/output error; usually used for physical read
* or write errors. i.e. the disk or other physical device hardware
* is returning errors.
* @G_FILE_ERROR_PERM: Operation not permitted; only the owner of the
* file (or other resource) or processes with special privileges can
* perform the operation.
* @G_FILE_ERROR_NOSYS: Function not implemented; this indicates that
* the system is missing some functionality.
* @G_FILE_ERROR_FAILED: Does not correspond to a UNIX error code; this
* is the standard "failed for unspecified reason" error code present
* in all #GError error code enumerations. Returned if no specific
* code applies.
*
* Values corresponding to @errno codes returned from file operations
* on UNIX. Unlike @errno codes, GFileError values are available on
* all systems, even Windows. The exact meaning of each code depends
* on what sort of file operation you were performing; the UNIX
* documentation gives more details. The following error code descriptions
* come from the GNU C Library manual, and are under the copyright
* of that manual.
*
* It's not very portable to make detailed assumptions about exactly
* which errors will be returned from a given operation. Some errors
* don't occur on some systems, etc., sometimes there are subtle
* differences in when a system will report a given error, etc.
*/
/**
* G_FILE_ERROR:
*
* Error domain for file operations. Errors in this domain will
* be from the #GFileError enumeration. See #GError for information
* on error domains.
*/
/**
* GFileTest:
* @G_FILE_TEST_IS_REGULAR: %TRUE if the file is a regular file
* (not a directory). Note that this test will also return %TRUE
* if the tested file is a symlink to a regular file.
* @G_FILE_TEST_IS_SYMLINK: %TRUE if the file is a symlink.
* @G_FILE_TEST_IS_DIR: %TRUE if the file is a directory.
* @G_FILE_TEST_IS_EXECUTABLE: %TRUE if the file is executable.
* @G_FILE_TEST_EXISTS: %TRUE if the file exists. It may or may not
* be a regular file.
*
* A test to perform on a file using g_file_test().
*/
/**
* g_mkdir_with_parents:
* @pathname: a pathname in the GLib file name encoding
* @mode: permissions to use for newly created directories
*
* Create a directory if it doesn't already exist. Create intermediate
* parent directories as needed, too.
*
* Returns: 0 if the directory already exists, or was successfully
* created. Returns -1 if an error occurred, with errno set.
*
* Since: 2.8
*/
int
g_mkdir_with_parents (const gchar *pathname,
int mode)
{
gchar *fn, *p;
if (pathname == NULL || *pathname == '\0')
{
errno = EINVAL;
return -1;
}
fn = g_strdup (pathname);
if (g_path_is_absolute (fn))
p = (gchar *) g_path_skip_root (fn);
else
p = fn;
do
{
while (*p && !G_IS_DIR_SEPARATOR (*p))
p++;
if (!*p)
p = NULL;
else
*p = '\0';
if (!g_file_test (fn, G_FILE_TEST_EXISTS))
{
if (g_mkdir (fn, mode) == -1 && errno != EEXIST)
{
int errno_save = errno;
g_free (fn);
errno = errno_save;
return -1;
}
}
else if (!g_file_test (fn, G_FILE_TEST_IS_DIR))
{
g_free (fn);
errno = ENOTDIR;
return -1;
}
if (p)
{
*p++ = G_DIR_SEPARATOR;
while (*p && G_IS_DIR_SEPARATOR (*p))
p++;
}
}
while (p);
g_free (fn);
return 0;
}
/**
* g_file_test:
* @filename: a filename to test in the GLib file name encoding
* @test: bitfield of #GFileTest flags
*
* Returns %TRUE if any of the tests in the bitfield @test are
* %TRUE. For example, (G_FILE_TEST_EXISTS |
* G_FILE_TEST_IS_DIR) will return %TRUE if the file exists;
* the check whether it's a directory doesn't matter since the existence
* test is %TRUE. With the current set of available tests, there's no point
* passing in more than one test at a time.
*
* Apart from %G_FILE_TEST_IS_SYMLINK all tests follow symbolic links,
* so for a symbolic link to a regular file g_file_test() will return
* %TRUE for both %G_FILE_TEST_IS_SYMLINK and %G_FILE_TEST_IS_REGULAR.
*
* Note, that for a dangling symbolic link g_file_test() will return
* %TRUE for %G_FILE_TEST_IS_SYMLINK and %FALSE for all other flags.
*
* You should never use g_file_test() to test whether it is safe
* to perform an operation, because there is always the possibility
* of the condition changing before you actually perform the operation.
* For example, you might think you could use %G_FILE_TEST_IS_SYMLINK
* to know whether it is safe to write to a file without being
* tricked into writing into a different location. It doesn't work!
* |[
* /* DON'T DO THIS */
* if (!g_file_test (filename, G_FILE_TEST_IS_SYMLINK))
* {
* fd = g_open (filename, O_WRONLY);
* /* write to fd */
* }
* ]|
*
* Another thing to note is that %G_FILE_TEST_EXISTS and
* %G_FILE_TEST_IS_EXECUTABLE are implemented using the access()
* system call. This usually doesn't matter, but if your program
* is setuid or setgid it means that these tests will give you
* the answer for the real user ID and group ID, rather than the
* effective user ID and group ID.
*
* On Windows, there are no symlinks, so testing for
* %G_FILE_TEST_IS_SYMLINK will always return %FALSE. Testing for
* %G_FILE_TEST_IS_EXECUTABLE will just check that the file exists and
* its name indicates that it is executable, checking for well-known
* extensions and those listed in the PATHEXT environment variable.
*
* Return value: whether a test was %TRUE
**/
gboolean
g_file_test (const gchar *filename,
GFileTest test)
{
#ifdef G_OS_WIN32
/* stuff missing in std vc6 api */
# ifndef INVALID_FILE_ATTRIBUTES
# define INVALID_FILE_ATTRIBUTES -1
# endif
# ifndef FILE_ATTRIBUTE_DEVICE
# define FILE_ATTRIBUTE_DEVICE 64
# endif
int attributes;
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
if (wfilename == NULL)
return FALSE;
attributes = GetFileAttributesW (wfilename);
g_free (wfilename);
if (attributes == INVALID_FILE_ATTRIBUTES)
return FALSE;
if (test & G_FILE_TEST_EXISTS)
return TRUE;
if (test & G_FILE_TEST_IS_REGULAR)
{
if ((attributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0)
return TRUE;
}
if (test & G_FILE_TEST_IS_DIR)
{
if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
return TRUE;
}
/* "while" so that we can exit this "loop" with a simple "break" */
while (test & G_FILE_TEST_IS_EXECUTABLE)
{
const gchar *lastdot = strrchr (filename, '.');
const gchar *pathext = NULL, *p;
int extlen;
if (lastdot == NULL)
break;
if (_stricmp (lastdot, ".exe") == 0 ||
_stricmp (lastdot, ".cmd") == 0 ||
_stricmp (lastdot, ".bat") == 0 ||
_stricmp (lastdot, ".com") == 0)
return TRUE;
/* Check if it is one of the types listed in %PATHEXT% */
pathext = g_getenv ("PATHEXT");
if (pathext == NULL)
break;
pathext = g_utf8_casefold (pathext, -1);
lastdot = g_utf8_casefold (lastdot, -1);
extlen = strlen (lastdot);
p = pathext;
while (TRUE)
{
const gchar *q = strchr (p, ';');
if (q == NULL)
q = p + strlen (p);
if (extlen == q - p &&
memcmp (lastdot, p, extlen) == 0)
{
g_free ((gchar *) pathext);
g_free ((gchar *) lastdot);
return TRUE;
}
if (*q)
p = q + 1;
else
break;
}
g_free ((gchar *) pathext);
g_free ((gchar *) lastdot);
break;
}
return FALSE;
#else
if ((test & G_FILE_TEST_EXISTS) && (access (filename, F_OK) == 0))
return TRUE;
if ((test & G_FILE_TEST_IS_EXECUTABLE) && (access (filename, X_OK) == 0))
{
if (getuid () != 0)
return TRUE;
/* For root, on some POSIX systems, access (filename, X_OK)
* will succeed even if no executable bits are set on the
* file. We fall through to a stat test to avoid that.
*/
}
else
test &= ~G_FILE_TEST_IS_EXECUTABLE;
if (test & G_FILE_TEST_IS_SYMLINK)
{
struct stat s;
if ((lstat (filename, &s) == 0) && S_ISLNK (s.st_mode))
return TRUE;
}
if (test & (G_FILE_TEST_IS_REGULAR |
G_FILE_TEST_IS_DIR |
G_FILE_TEST_IS_EXECUTABLE))
{
struct stat s;
if (stat (filename, &s) == 0)
{
if ((test & G_FILE_TEST_IS_REGULAR) && S_ISREG (s.st_mode))
return TRUE;
if ((test & G_FILE_TEST_IS_DIR) && S_ISDIR (s.st_mode))
return TRUE;
/* The extra test for root when access (file, X_OK) succeeds.
*/
if ((test & G_FILE_TEST_IS_EXECUTABLE) &&
((s.st_mode & S_IXOTH) ||
(s.st_mode & S_IXUSR) ||
(s.st_mode & S_IXGRP)))
return TRUE;
}
}
return FALSE;
#endif
}
G_DEFINE_QUARK (g-file-error-quark, g_file_error)
/**
* g_file_error_from_errno:
* @err_no: an "errno" value
*
* Gets a #GFileError constant based on the passed-in @err_no.
* For example, if you pass in EEXIST this function returns
* #G_FILE_ERROR_EXIST. Unlike errno values, you can portably
* assume that all #GFileError values will exist.
*
* Normally a #GFileError value goes into a #GError returned
* from a function that manipulates files. So you would use
* g_file_error_from_errno() when constructing a #GError.
*
* Return value: #GFileError corresponding to the given @errno
**/
GFileError
g_file_error_from_errno (gint err_no)
{
switch (err_no)
{
#ifdef EEXIST
case EEXIST:
return G_FILE_ERROR_EXIST;
break;
#endif
#ifdef EISDIR
case EISDIR:
return G_FILE_ERROR_ISDIR;
break;
#endif
#ifdef EACCES
case EACCES:
return G_FILE_ERROR_ACCES;
break;
#endif
#ifdef ENAMETOOLONG
case ENAMETOOLONG:
return G_FILE_ERROR_NAMETOOLONG;
break;
#endif
#ifdef ENOENT
case ENOENT:
return G_FILE_ERROR_NOENT;
break;
#endif
#ifdef ENOTDIR
case ENOTDIR:
return G_FILE_ERROR_NOTDIR;
break;
#endif
#ifdef ENXIO
case ENXIO:
return G_FILE_ERROR_NXIO;
break;
#endif
#ifdef ENODEV
case ENODEV:
return G_FILE_ERROR_NODEV;
break;
#endif
#ifdef EROFS
case EROFS:
return G_FILE_ERROR_ROFS;
break;
#endif
#ifdef ETXTBSY
case ETXTBSY:
return G_FILE_ERROR_TXTBSY;
break;
#endif
#ifdef EFAULT
case EFAULT:
return G_FILE_ERROR_FAULT;
break;
#endif
#ifdef ELOOP
case ELOOP:
return G_FILE_ERROR_LOOP;
break;
#endif
#ifdef ENOSPC
case ENOSPC:
return G_FILE_ERROR_NOSPC;
break;
#endif
#ifdef ENOMEM
case ENOMEM:
return G_FILE_ERROR_NOMEM;
break;
#endif
#ifdef EMFILE
case EMFILE:
return G_FILE_ERROR_MFILE;
break;
#endif
#ifdef ENFILE
case ENFILE:
return G_FILE_ERROR_NFILE;
break;
#endif
#ifdef EBADF
case EBADF:
return G_FILE_ERROR_BADF;
break;
#endif
#ifdef EINVAL
case EINVAL:
return G_FILE_ERROR_INVAL;
break;
#endif
#ifdef EPIPE
case EPIPE:
return G_FILE_ERROR_PIPE;
break;
#endif
#ifdef EAGAIN
case EAGAIN:
return G_FILE_ERROR_AGAIN;
break;
#endif
#ifdef EINTR
case EINTR:
return G_FILE_ERROR_INTR;
break;
#endif
#ifdef EIO
case EIO:
return G_FILE_ERROR_IO;
break;
#endif
#ifdef EPERM
case EPERM:
return G_FILE_ERROR_PERM;
break;
#endif
#ifdef ENOSYS
case ENOSYS:
return G_FILE_ERROR_NOSYS;
break;
#endif
default:
return G_FILE_ERROR_FAILED;
break;
}
}
static gboolean
get_contents_stdio (const gchar *display_filename,
FILE *f,
gchar **contents,
gsize *length,
GError **error)
{
gchar buf[4096];
gsize bytes;
gchar *str = NULL;
gsize total_bytes = 0;
gsize total_allocated = 0;
gchar *tmp;
g_assert (f != NULL);
while (!feof (f))
{
gint save_errno;
bytes = fread (buf, 1, sizeof (buf), f);
save_errno = errno;
while ((total_bytes + bytes + 1) > total_allocated)
{
if (str)
total_allocated *= 2;
else
total_allocated = MIN (bytes + 1, sizeof (buf));
tmp = g_try_realloc (str, total_allocated);
if (tmp == NULL)
{
g_set_error (error,
G_FILE_ERROR,
G_FILE_ERROR_NOMEM,
g_dngettext (GETTEXT_PACKAGE, "Could not allocate %lu byte to read file \"%s\"", "Could not allocate %lu bytes to read file \"%s\"", (gulong)total_allocated),
(gulong) total_allocated,
display_filename);
goto error;
}
str = tmp;
}
if (ferror (f))
{
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (save_errno),
_("Error reading file '%s': %s"),
display_filename,
g_strerror (save_errno));
goto error;
}
memcpy (str + total_bytes, buf, bytes);
if (total_bytes + bytes < total_bytes)
{
g_set_error (error,
G_FILE_ERROR,
G_FILE_ERROR_FAILED,
_("File \"%s\" is too large"),
display_filename);
goto error;
}
total_bytes += bytes;
}
fclose (f);
if (total_allocated == 0)
{
str = g_new (gchar, 1);
total_bytes = 0;
}
str[total_bytes] = '\0';
if (length)
*length = total_bytes;
*contents = str;
return TRUE;
error:
g_free (str);
fclose (f);
return FALSE;
}
#ifndef G_OS_WIN32
static gboolean
get_contents_regfile (const gchar *display_filename,
struct stat *stat_buf,
gint fd,
gchar **contents,
gsize *length,
GError **error)
{
gchar *buf;
gsize bytes_read;
gsize size;
gsize alloc_size;
size = stat_buf->st_size;
alloc_size = size + 1;
buf = g_try_malloc (alloc_size);
if (buf == NULL)
{
g_set_error (error,
G_FILE_ERROR,
G_FILE_ERROR_NOMEM,
g_dngettext (GETTEXT_PACKAGE, "Could not allocate %lu byte to read file \"%s\"", "Could not allocate %lu bytes to read file \"%s\"", (gulong)alloc_size),
(gulong) alloc_size,
display_filename);
goto error;
}
bytes_read = 0;
while (bytes_read < size)
{
gssize rc;
rc = read (fd, buf + bytes_read, size - bytes_read);
if (rc < 0)
{
if (errno != EINTR)
{
int save_errno = errno;
g_free (buf);
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (save_errno),
_("Failed to read from file '%s': %s"),
display_filename,
g_strerror (save_errno));
goto error;
}
}
else if (rc == 0)
break;
else
bytes_read += rc;
}
buf[bytes_read] = '\0';
if (length)
*length = bytes_read;
*contents = buf;
close (fd);
return TRUE;
error:
close (fd);
return FALSE;
}
static gboolean
get_contents_posix (const gchar *filename,
gchar **contents,
gsize *length,
GError **error)
{
struct stat stat_buf;
gint fd;
gchar *display_filename = g_filename_display_name (filename);
/* O_BINARY useful on Cygwin */
fd = open (filename, O_RDONLY|O_BINARY);
if (fd < 0)
{
int save_errno = errno;
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (save_errno),
_("Failed to open file '%s': %s"),
display_filename,
g_strerror (save_errno));
g_free (display_filename);
return FALSE;
}
/* I don't think this will ever fail, aside from ENOMEM, but. */
if (fstat (fd, &stat_buf) < 0)
{
int save_errno = errno;
close (fd);
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (save_errno),
_("Failed to get attributes of file '%s': fstat() failed: %s"),
display_filename,
g_strerror (save_errno));
g_free (display_filename);
return FALSE;
}
if (stat_buf.st_size > 0 && S_ISREG (stat_buf.st_mode))
{
gboolean retval = get_contents_regfile (display_filename,
&stat_buf,
fd,
contents,
length,
error);
g_free (display_filename);
return retval;
}
else
{
FILE *f;
gboolean retval;
f = fdopen (fd, "r");
if (f == NULL)
{
int save_errno = errno;
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (save_errno),
_("Failed to open file '%s': fdopen() failed: %s"),
display_filename,
g_strerror (save_errno));
g_free (display_filename);
return FALSE;
}
retval = get_contents_stdio (display_filename, f, contents, length, error);
g_free (display_filename);
return retval;
}
}
#else /* G_OS_WIN32 */
static gboolean
get_contents_win32 (const gchar *filename,
gchar **contents,
gsize *length,
GError **error)
{
FILE *f;
gboolean retval;
gchar *display_filename = g_filename_display_name (filename);
int save_errno;
f = g_fopen (filename, "rb");
save_errno = errno;
if (f == NULL)
{
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (save_errno),
_("Failed to open file '%s': %s"),
display_filename,
g_strerror (save_errno));
g_free (display_filename);
return FALSE;
}
retval = get_contents_stdio (display_filename, f, contents, length, error);
g_free (display_filename);
return retval;
}
#endif
/**
* g_file_get_contents:
* @filename: (type filename): name of a file to read contents from, in the GLib file name encoding
* @contents: (out) (array length=length) (element-type guint8): location to store an allocated string, use g_free() to free
* the returned string
* @length: (allow-none): location to store length in bytes of the contents, or %NULL
* @error: return location for a #GError, or %NULL
*
* Reads an entire file into allocated memory, with good error
* checking.
*
* If the call was successful, it returns %TRUE and sets @contents to the file
* contents and @length to the length of the file contents in bytes. The string
* stored in @contents will be nul-terminated, so for text files you can pass
* %NULL for the @length argument. If the call was not successful, it returns
* %FALSE and sets @error. The error domain is #G_FILE_ERROR. Possible error
* codes are those in the #GFileError enumeration. In the error case,
* @contents is set to %NULL and @length is set to zero.
*
* Return value: %TRUE on success, %FALSE if an error occurred
**/
gboolean
g_file_get_contents (const gchar *filename,
gchar **contents,
gsize *length,
GError **error)
{
g_return_val_if_fail (filename != NULL, FALSE);
g_return_val_if_fail (contents != NULL, FALSE);
*contents = NULL;
if (length)
*length = 0;
#ifdef G_OS_WIN32
return get_contents_win32 (filename, contents, length, error);
#else
return get_contents_posix (filename, contents, length, error);
#endif
}
static gboolean
rename_file (const char *old_name,
const char *new_name,
GError **err)
{
errno = 0;
if (g_rename (old_name, new_name) == -1)
{
int save_errno = errno;
gchar *display_old_name = g_filename_display_name (old_name);
gchar *display_new_name = g_filename_display_name (new_name);
g_set_error (err,
G_FILE_ERROR,
g_file_error_from_errno (save_errno),
_("Failed to rename file '%s' to '%s': g_rename() failed: %s"),
display_old_name,
display_new_name,
g_strerror (save_errno));
g_free (display_old_name);
g_free (display_new_name);
return FALSE;
}
return TRUE;
}
static char *
format_error_message (const gchar *filename,
const gchar *format_string) G_GNUC_FORMAT(2);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
static char *
format_error_message (const gchar *filename,
const gchar *format_string)
{
gint saved_errno = errno;
gchar *display_name;
gchar *msg;
display_name = g_filename_display_name (filename);
msg = g_strdup_printf (format_string, display_name, g_strerror (saved_errno));
g_free (display_name);
return msg;
}
#pragma GCC diagnostic pop
/* format string must have two '%s':
*
* - the place for the filename
* - the place for the strerror
*/
static void
set_file_error (GError **error,
const gchar *filename,
const gchar *format_string)
{
int saved_errno = errno;
char *msg = format_error_message (filename, format_string);
g_set_error_literal (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno),
msg);
g_free (msg);
}
static gchar *
write_to_temp_file (const gchar *contents,
gssize length,
const gchar *dest_file,
GError **err)
{
gchar *tmp_name;
gchar *retval;
gint fd;
retval = NULL;
tmp_name = g_strdup_printf ("%s.XXXXXX", dest_file);
errno = 0;
fd = g_mkstemp_full (tmp_name, O_RDWR | O_BINARY, 0666);
if (fd == -1)
{
set_file_error (err, tmp_name, _("Failed to create file '%s': %s"));
goto out;
}
#ifdef HAVE_FALLOCATE
if (length > 0)
{
/* We do this on a 'best effort' basis... It may not be supported
* on the underlying filesystem.
*/
(void) fallocate (fd, 0, 0, length);
}
#endif
while (length > 0)
{
gssize s;
s = write (fd, contents, length);
if (s < 0)
{
if (errno == EINTR)
continue;
set_file_error (err, tmp_name, _("Failed to write file '%s': write() failed: %s"));
close (fd);
g_unlink (tmp_name);
goto out;
}
g_assert (s <= length);
contents += s;
length -= s;
}
#ifdef BTRFS_SUPER_MAGIC
{
struct statfs buf;
/* On Linux, on btrfs, skip the fsync since rename-over-existing is
* guaranteed to be atomic and this is the only case in which we
* would fsync() anyway.
*/
if (fstatfs (fd, &buf) == 0 && buf.f_type == BTRFS_SUPER_MAGIC)
goto no_fsync;
}
#endif
#ifdef HAVE_FSYNC
{
struct stat statbuf;
errno = 0;
/* If the final destination exists and is > 0 bytes, we want to sync the
* newly written file to ensure the data is on disk when we rename over
* the destination. Otherwise if we get a system crash we can lose both
* the new and the old file on some filesystems. (I.E. those that don't
* guarantee the data is written to the disk before the metadata.)
*/
if (g_lstat (dest_file, &statbuf) == 0 && statbuf.st_size > 0 && fsync (fd) != 0)
{
set_file_error (err, tmp_name, _("Failed to write file '%s': fsync() failed: %s"));
close (fd);
g_unlink (tmp_name);
goto out;
}
}
#endif
#ifdef BTRFS_SUPER_MAGIC
no_fsync:
#endif
errno = 0;
if (!g_close (fd, err))
{
g_unlink (tmp_name);
goto out;
}
retval = g_strdup (tmp_name);
out:
g_free (tmp_name);
return retval;
}
/**
* g_file_set_contents:
* @filename: (type filename): name of a file to write @contents to, in the GLib file name
* encoding
* @contents: (array length=length) (element-type guint8): string to write to the file
* @length: length of @contents, or -1 if @contents is a nul-terminated string
* @error: return location for a #GError, or %NULL
*
* Writes all of @contents to a file named @filename, with good error checking.
* If a file called @filename already exists it will be overwritten.
*
* This write is atomic in the sense that it is first written to a temporary
* file which is then renamed to the final name. Notes:
*
*
* On Unix, if @filename already exists hard links to @filename will break.
* Also since the file is recreated, existing permissions, access control
* lists, metadata etc. may be lost. If @filename is a symbolic link,
* the link itself will be replaced, not the linked file.
*
*
* On Windows renaming a file will not remove an existing file with the
* new name, so on Windows there is a race condition between the existing
* file being removed and the temporary file being renamed.
*
*
* On Windows there is no way to remove a file that is open to some
* process, or mapped into memory. Thus, this function will fail if
* @filename already exists and is open.
*
*
*
* If the call was successful, it returns %TRUE. If the call was not successful,
* it returns %FALSE and sets @error. The error domain is #G_FILE_ERROR.
* Possible error codes are those in the #GFileError enumeration.
*
* Note that the name for the temporary file is constructed by appending up
* to 7 characters to @filename.
*
* Return value: %TRUE on success, %FALSE if an error occurred
*
* Since: 2.8
**/
gboolean
g_file_set_contents (const gchar *filename,
const gchar *contents,
gssize length,
GError **error)
{
gchar *tmp_filename;
gboolean retval;
GError *rename_error = NULL;
g_return_val_if_fail (filename != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
g_return_val_if_fail (contents != NULL || length == 0, FALSE);
g_return_val_if_fail (length >= -1, FALSE);
if (length == -1)
length = strlen (contents);
tmp_filename = write_to_temp_file (contents, length, filename, error);
if (!tmp_filename)
{
retval = FALSE;
goto out;
}
if (!rename_file (tmp_filename, filename, &rename_error))
{
#ifndef G_OS_WIN32
g_unlink (tmp_filename);
g_propagate_error (error, rename_error);
retval = FALSE;
goto out;
#else /* G_OS_WIN32 */
/* Renaming failed, but on Windows this may just mean
* the file already exists. So if the target file
* exists, try deleting it and do the rename again.
*/
if (!g_file_test (filename, G_FILE_TEST_EXISTS))
{
g_unlink (tmp_filename);
g_propagate_error (error, rename_error);
retval = FALSE;
goto out;
}
g_error_free (rename_error);
if (g_unlink (filename) == -1)
{
gchar *display_filename = g_filename_display_name (filename);
int save_errno = errno;
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (save_errno),
_("Existing file '%s' could not be removed: g_unlink() failed: %s"),
display_filename,
g_strerror (save_errno));
g_free (display_filename);
g_unlink (tmp_filename);
retval = FALSE;
goto out;
}
if (!rename_file (tmp_filename, filename, error))
{
g_unlink (tmp_filename);
retval = FALSE;
goto out;
}
#endif
}
retval = TRUE;
out:
g_free (tmp_filename);
return retval;
}
/*
* get_tmp_file based on the mkstemp implementation from the GNU C library.
* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
*/
typedef gint (*GTmpFileCallback) (const gchar *, gint, gint);
static gint
get_tmp_file (gchar *tmpl,
GTmpFileCallback f,
int flags,
int mode)
{
char *XXXXXX;
int count, fd;
static const char letters[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static const int NLETTERS = sizeof (letters) - 1;
glong value;
GTimeVal tv;
static int counter = 0;
g_return_val_if_fail (tmpl != NULL, -1);
/* find the last occurrence of "XXXXXX" */
XXXXXX = g_strrstr (tmpl, "XXXXXX");
if (!XXXXXX || strncmp (XXXXXX, "XXXXXX", 6))
{
errno = EINVAL;
return -1;
}
/* Get some more or less random data. */
g_get_current_time (&tv);
value = (tv.tv_usec ^ tv.tv_sec) + counter++;
for (count = 0; count < 100; value += 7777, ++count)
{
glong v = value;
/* Fill in the random bits. */
XXXXXX[0] = letters[v % NLETTERS];
v /= NLETTERS;
XXXXXX[1] = letters[v % NLETTERS];
v /= NLETTERS;
XXXXXX[2] = letters[v % NLETTERS];
v /= NLETTERS;
XXXXXX[3] = letters[v % NLETTERS];
v /= NLETTERS;
XXXXXX[4] = letters[v % NLETTERS];
v /= NLETTERS;
XXXXXX[5] = letters[v % NLETTERS];
fd = f (tmpl, flags, mode);
if (fd >= 0)
return fd;
else if (errno != EEXIST)
/* Any other error will apply also to other names we might
* try, and there are 2^32 or so of them, so give up now.
*/
return -1;
}
/* We got out of the loop because we ran out of combinations to try. */
errno = EEXIST;
return -1;
}
/* Some GTmpFileCallback implementations.
*
* Note: we cannot use open() or g_open() directly because even though
* they appear compatible, they may be vararg functions and calling
* varargs functions through a non-varargs type is undefined.
*/
static gint
wrap_g_mkdir (const gchar *filename,
int flags G_GNUC_UNUSED,
int mode)
{
/* tmpl is in UTF-8 on Windows, thus use g_mkdir() */
return g_mkdir (filename, mode);
}
static gint
wrap_g_open (const gchar *filename,
int flags,
int mode)
{
return g_open (filename, flags, mode);
}
/**
* g_mkdtemp_full:
* @tmpl: (type filename): template directory name
* @mode: permissions to create the temporary directory with
*
* Creates a temporary directory. See the mkdtemp() documentation
* on most UNIX-like systems.
*
* The parameter is a string that should follow the rules for
* mkdtemp() templates, i.e. contain the string "XXXXXX".
* g_mkdtemp() is slightly more flexible than mkdtemp() in that the
* sequence does not have to occur at the very end of the template
* and you can pass a @mode. The X string will be modified to form
* the name of a directory that didn't exist. The string should be
* in the GLib file name encoding. Most importantly, on Windows it
* should be in UTF-8.
*
* Return value: A pointer to @tmpl, which has been modified
* to hold the directory name. In case of errors, %NULL is
* returned, and %errno will be set.
*
* Since: 2.30
*/
gchar *
g_mkdtemp_full (gchar *tmpl,
gint mode)
{
if (get_tmp_file (tmpl, wrap_g_mkdir, 0, mode) == -1)
return NULL;
else
return tmpl;
}
/**
* g_mkdtemp:
* @tmpl: (type filename): template directory name
*
* Creates a temporary directory. See the mkdtemp() documentation
* on most UNIX-like systems.
*
* The parameter is a string that should follow the rules for
* mkdtemp() templates, i.e. contain the string "XXXXXX".
* g_mkdtemp() is slightly more flexible than mkdtemp() in that the
* sequence does not have to occur at the very end of the template
* and you can pass a @mode and additional @flags. The X string will
* be modified to form the name of a directory that didn't exist.
* The string should be in the GLib file name encoding. Most importantly,
* on Windows it should be in UTF-8.
*
* Return value: A pointer to @tmpl, which has been modified
* to hold the directory name. In case of errors, %NULL is
* returned and %errno will be set.
*
* Since: 2.30
*/
gchar *
g_mkdtemp (gchar *tmpl)
{
return g_mkdtemp_full (tmpl, 0700);
}
/**
* g_mkstemp_full:
* @tmpl: (type filename): template filename
* @flags: flags to pass to an open() call in addition to O_EXCL
* and O_CREAT, which are passed automatically
* @mode: permissions to create the temporary file with
*
* Opens a temporary file. See the mkstemp() documentation
* on most UNIX-like systems.
*
* The parameter is a string that should follow the rules for
* mkstemp() templates, i.e. contain the string "XXXXXX".
* g_mkstemp_full() is slightly more flexible than mkstemp()
* in that the sequence does not have to occur at the very end of the
* template and you can pass a @mode and additional @flags. The X
* string will be modified to form the name of a file that didn't exist.
* The string should be in the GLib file name encoding. Most importantly,
* on Windows it should be in UTF-8.
*
* Return value: A file handle (as from open()) to the file
* opened for reading and writing. The file handle should be
* closed with close(). In case of errors, -1 is returned
* and %errno will be set.
*
* Since: 2.22
*/
gint
g_mkstemp_full (gchar *tmpl,
gint flags,
gint mode)
{
/* tmpl is in UTF-8 on Windows, thus use g_open() */
return get_tmp_file (tmpl, wrap_g_open,
flags | O_CREAT | O_EXCL, mode);
}
/**
* g_mkstemp:
* @tmpl: (type filename): template filename
*
* Opens a temporary file. See the mkstemp() documentation
* on most UNIX-like systems.
*
* The parameter is a string that should follow the rules for
* mkstemp() templates, i.e. contain the string "XXXXXX".
* g_mkstemp() is slightly more flexible than mkstemp() in that the
* sequence does not have to occur at the very end of the template.
* The X string will be modified to form the name of a file that
* didn't exist. The string should be in the GLib file name encoding.
* Most importantly, on Windows it should be in UTF-8.
*
* Return value: A file handle (as from open()) to the file
* opened for reading and writing. The file is opened in binary
* mode on platforms where there is a difference. The file handle
* should be closed with close(). In case of errors, -1 is
* returned and %errno will be set.
*/
gint
g_mkstemp (gchar *tmpl)
{
return g_mkstemp_full (tmpl, O_RDWR | O_BINARY, 0600);
}
static gint
g_get_tmp_name (const gchar *tmpl,
gchar **name_used,
GTmpFileCallback f,
gint flags,
gint mode,
GError **error)
{
int retval;
const char *tmpdir;
const char *sep;
char *fulltemplate;
const char *slash;
if (tmpl == NULL)
tmpl = ".XXXXXX";
if ((slash = strchr (tmpl, G_DIR_SEPARATOR)) != NULL
#ifdef G_OS_WIN32
|| (strchr (tmpl, '/') != NULL && (slash = "/"))
#endif
)
{
gchar *display_tmpl = g_filename_display_name (tmpl);
char c[2];
c[0] = *slash;
c[1] = '\0';
g_set_error (error,
G_FILE_ERROR,
G_FILE_ERROR_FAILED,
_("Template '%s' invalid, should not contain a '%s'"),
display_tmpl, c);
g_free (display_tmpl);
return -1;
}
if (strstr (tmpl, "XXXXXX") == NULL)
{
gchar *display_tmpl = g_filename_display_name (tmpl);
g_set_error (error,
G_FILE_ERROR,
G_FILE_ERROR_FAILED,
_("Template '%s' doesn't contain XXXXXX"),
display_tmpl);
g_free (display_tmpl);
return -1;
}
tmpdir = g_get_tmp_dir ();
if (G_IS_DIR_SEPARATOR (tmpdir [strlen (tmpdir) - 1]))
sep = "";
else
sep = G_DIR_SEPARATOR_S;
fulltemplate = g_strconcat (tmpdir, sep, tmpl, NULL);
retval = get_tmp_file (fulltemplate, f, flags, mode);
if (retval == -1)
{
int save_errno = errno;
gchar *display_fulltemplate = g_filename_display_name (fulltemplate);
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (save_errno),
_("Failed to create file '%s': %s"),
display_fulltemplate, g_strerror (save_errno));
g_free (display_fulltemplate);
g_free (fulltemplate);
return -1;
}
*name_used = fulltemplate;
return retval;
}
/**
* g_file_open_tmp:
* @tmpl: (type filename) (allow-none): Template for file name, as in
* g_mkstemp(), basename only, or %NULL for a default template
* @name_used: (out) (type filename): location to store actual name used,
* or %NULL
* @error: return location for a #GError
*
* Opens a file for writing in the preferred directory for temporary
* files (as returned by g_get_tmp_dir()).
*
* @tmpl should be a string in the GLib file name encoding containing
* a sequence of six 'X' characters, as the parameter to g_mkstemp().
* However, unlike these functions, the template should only be a
* basename, no directory components are allowed. If template is
* %NULL, a default template is used.
*
* Note that in contrast to g_mkstemp() (and mkstemp()) @tmpl is not
* modified, and might thus be a read-only literal string.
*
* Upon success, and if @name_used is non-%NULL, the actual name used
* is returned in @name_used. This string should be freed with g_free()
* when not needed any longer. The returned name is in the GLib file
* name encoding.
*
* Return value: A file handle (as from open()) to the file opened for
* reading and writing. The file is opened in binary mode on platforms
* where there is a difference. The file handle should be closed with
* close(). In case of errors, -1 is returned and @error will be set.
*/
gint
g_file_open_tmp (const gchar *tmpl,
gchar **name_used,
GError **error)
{
gchar *fulltemplate;
gint result;
result = g_get_tmp_name (tmpl, &fulltemplate,
wrap_g_open,
O_CREAT | O_EXCL | O_RDWR | O_BINARY,
0600,
error);
if (result != -1)
{
if (name_used)
*name_used = fulltemplate;
else
g_free (fulltemplate);
}
return result;
}
/**
* g_dir_make_tmp:
* @tmpl: (type filename) (allow-none): Template for directory name,
* as in g_mkdtemp(), basename only, or %NULL for a default template
* @error: return location for a #GError
*
* Creates a subdirectory in the preferred directory for temporary
* files (as returned by g_get_tmp_dir()).
*
* @tmpl should be a string in the GLib file name encoding containing
* a sequence of six 'X' characters, as the parameter to g_mkstemp().
* However, unlike these functions, the template should only be a
* basename, no directory components are allowed. If template is
* %NULL, a default template is used.
*
* Note that in contrast to g_mkdtemp() (and mkdtemp()) @tmpl is not
* modified, and might thus be a read-only literal string.
*
* Return value: (type filename): The actual name used. This string
* should be freed with g_free() when not needed any longer and is
* is in the GLib file name encoding. In case of errors, %NULL is
* returned and @error will be set.
*
* Since: 2.30
*/
gchar *
g_dir_make_tmp (const gchar *tmpl,
GError **error)
{
gchar *fulltemplate;
if (g_get_tmp_name (tmpl, &fulltemplate, wrap_g_mkdir, 0, 0700, error) == -1)
return NULL;
else
return fulltemplate;
}
static gchar *
g_build_path_va (const gchar *separator,
const gchar *first_element,
va_list *args,
gchar **str_array)
{
GString *result;
gint separator_len = strlen (separator);
gboolean is_first = TRUE;
gboolean have_leading = FALSE;
const gchar *single_element = NULL;
const gchar *next_element;
const gchar *last_trailing = NULL;
gint i = 0;
result = g_string_new (NULL);
if (str_array)
next_element = str_array[i++];
else
next_element = first_element;
while (TRUE)
{
const gchar *element;
const gchar *start;
const gchar *end;
if (next_element)
{
element = next_element;
if (str_array)
next_element = str_array[i++];
else
next_element = va_arg (*args, gchar *);
}
else
break;
/* Ignore empty elements */
if (!*element)
continue;
start = element;
if (separator_len)
{
while (strncmp (start, separator, separator_len) == 0)
start += separator_len;
}
end = start + strlen (start);
if (separator_len)
{
while (end >= start + separator_len &&
strncmp (end - separator_len, separator, separator_len) == 0)
end -= separator_len;
last_trailing = end;
while (last_trailing >= element + separator_len &&
strncmp (last_trailing - separator_len, separator, separator_len) == 0)
last_trailing -= separator_len;
if (!have_leading)
{
/* If the leading and trailing separator strings are in the
* same element and overlap, the result is exactly that element
*/
if (last_trailing <= start)
single_element = element;
g_string_append_len (result, element, start - element);
have_leading = TRUE;
}
else
single_element = NULL;
}
if (end == start)
continue;
if (!is_first)
g_string_append (result, separator);
g_string_append_len (result, start, end - start);
is_first = FALSE;
}
if (single_element)
{
g_string_free (result, TRUE);
return g_strdup (single_element);
}
else
{
if (last_trailing)
g_string_append (result, last_trailing);
return g_string_free (result, FALSE);
}
}
/**
* g_build_pathv:
* @separator: a string used to separator the elements of the path.
* @args: (array zero-terminated=1): %NULL-terminated array of strings containing the path elements.
*
* Behaves exactly like g_build_path(), but takes the path elements
* as a string array, instead of varargs. This function is mainly
* meant for language bindings.
*
* Return value: a newly-allocated string that must be freed with g_free().
*
* Since: 2.8
*/
gchar *
g_build_pathv (const gchar *separator,
gchar **args)
{
if (!args)
return NULL;
return g_build_path_va (separator, NULL, NULL, args);
}
/**
* g_build_path:
* @separator: a string used to separator the elements of the path.
* @first_element: the first element in the path
* @...: remaining elements in path, terminated by %NULL
*
* Creates a path from a series of elements using @separator as the
* separator between elements. At the boundary between two elements,
* any trailing occurrences of separator in the first element, or
* leading occurrences of separator in the second element are removed
* and exactly one copy of the separator is inserted.
*
* Empty elements are ignored.
*
* The number of leading copies of the separator on the result is
* the same as the number of leading copies of the separator on
* the first non-empty element.
*
* The number of trailing copies of the separator on the result is
* the same as the number of trailing copies of the separator on
* the last non-empty element. (Determination of the number of
* trailing copies is done without stripping leading copies, so
* if the separator is ABA, ABABA
* has 1 trailing copy.)
*
* However, if there is only a single non-empty element, and there
* are no characters in that element not part of the leading or
* trailing separators, then the result is exactly the original value
* of that element.
*
* Other than for determination of the number of leading and trailing
* copies of the separator, elements consisting only of copies
* of the separator are ignored.
*
* Return value: a newly-allocated string that must be freed with g_free().
**/
gchar *
g_build_path (const gchar *separator,
const gchar *first_element,
...)
{
gchar *str;
va_list args;
g_return_val_if_fail (separator != NULL, NULL);
va_start (args, first_element);
str = g_build_path_va (separator, first_element, &args, NULL);
va_end (args);
return str;
}
#ifdef G_OS_WIN32
static gchar *
g_build_pathname_va (const gchar *first_element,
va_list *args,
gchar **str_array)
{
/* Code copied from g_build_pathv(), and modified to use two
* alternative single-character separators.
*/
GString *result;
gboolean is_first = TRUE;
gboolean have_leading = FALSE;
const gchar *single_element = NULL;
const gchar *next_element;
const gchar *last_trailing = NULL;
gchar current_separator = '\\';
gint i = 0;
result = g_string_new (NULL);
if (str_array)
next_element = str_array[i++];
else
next_element = first_element;
while (TRUE)
{
const gchar *element;
const gchar *start;
const gchar *end;
if (next_element)
{
element = next_element;
if (str_array)
next_element = str_array[i++];
else
next_element = va_arg (*args, gchar *);
}
else
break;
/* Ignore empty elements */
if (!*element)
continue;
start = element;
if (TRUE)
{
while (start &&
(*start == '\\' || *start == '/'))
{
current_separator = *start;
start++;
}
}
end = start + strlen (start);
if (TRUE)
{
while (end >= start + 1 &&
(end[-1] == '\\' || end[-1] == '/'))
{
current_separator = end[-1];
end--;
}
last_trailing = end;
while (last_trailing >= element + 1 &&
(last_trailing[-1] == '\\' || last_trailing[-1] == '/'))
last_trailing--;
if (!have_leading)
{
/* If the leading and trailing separator strings are in the
* same element and overlap, the result is exactly that element
*/
if (last_trailing <= start)
single_element = element;
g_string_append_len (result, element, start - element);
have_leading = TRUE;
}
else
single_element = NULL;
}
if (end == start)
continue;
if (!is_first)
g_string_append_len (result, ¤t_separator, 1);
g_string_append_len (result, start, end - start);
is_first = FALSE;
}
if (single_element)
{
g_string_free (result, TRUE);
return g_strdup (single_element);
}
else
{
if (last_trailing)
g_string_append (result, last_trailing);
return g_string_free (result, FALSE);
}
}
#endif
/**
* g_build_filenamev:
* @args: (array zero-terminated=1): %NULL-terminated array of strings containing the path elements.
*
* Behaves exactly like g_build_filename(), but takes the path elements
* as a string array, instead of varargs. This function is mainly
* meant for language bindings.
*
* Return value: a newly-allocated string that must be freed with g_free().
*
* Since: 2.8
*/
gchar *
g_build_filenamev (gchar **args)
{
gchar *str;
#ifndef G_OS_WIN32
str = g_build_path_va (G_DIR_SEPARATOR_S, NULL, NULL, args);
#else
str = g_build_pathname_va (NULL, NULL, args);
#endif
return str;
}
/**
* g_build_filename:
* @first_element: the first element in the path
* @...: remaining elements in path, terminated by %NULL
*
* Creates a filename from a series of elements using the correct
* separator for filenames.
*
* On Unix, this function behaves identically to g_build_path
* (G_DIR_SEPARATOR_S, first_element, ....).
*
* On Windows, it takes into account that either the backslash
* (\ or slash (/) can be used
* as separator in filenames, but otherwise behaves as on Unix. When
* file pathname separators need to be inserted, the one that last
* previously occurred in the parameters (reading from left to right)
* is used.
*
* No attempt is made to force the resulting filename to be an absolute
* path. If the first element is a relative path, the result will
* be a relative path.
*
* Return value: a newly-allocated string that must be freed with g_free().
**/
gchar *
g_build_filename (const gchar *first_element,
...)
{
gchar *str;
va_list args;
va_start (args, first_element);
#ifndef G_OS_WIN32
str = g_build_path_va (G_DIR_SEPARATOR_S, first_element, &args, NULL);
#else
str = g_build_pathname_va (first_element, &args, NULL);
#endif
va_end (args);
return str;
}
/**
* g_file_read_link:
* @filename: the symbolic link
* @error: return location for a #GError
*
* Reads the contents of the symbolic link @filename like the POSIX
* readlink() function. The returned string is in the encoding used
* for filenames. Use g_filename_to_utf8() to convert it to UTF-8.
*
* Returns: A newly-allocated string with the contents of the symbolic link,
* or %NULL if an error occurred.
*
* Since: 2.4
*/
gchar *
g_file_read_link (const gchar *filename,
GError **error)
{
#ifdef HAVE_READLINK
gchar *buffer;
guint size;
gint read_size;
size = 256;
buffer = g_malloc (size);
while (TRUE)
{
read_size = readlink (filename, buffer, size);
if (read_size < 0) {
int save_errno = errno;
gchar *display_filename = g_filename_display_name (filename);
g_free (buffer);
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (save_errno),
_("Failed to read the symbolic link '%s': %s"),
display_filename,
g_strerror (save_errno));
g_free (display_filename);
return NULL;
}
if (read_size < size)
{
buffer[read_size] = 0;
return buffer;
}
size *= 2;
buffer = g_realloc (buffer, size);
}
#else
g_set_error_literal (error,
G_FILE_ERROR,
G_FILE_ERROR_INVAL,
_("Symbolic links not supported"));
return NULL;
#endif
}
/**
* g_path_is_absolute:
* @file_name: a file name
*
* Returns %TRUE if the given @file_name is an absolute file name.
* Note that this is a somewhat vague concept on Windows.
*
* On POSIX systems, an absolute file name is well-defined. It always
* starts from the single root directory. For example "/usr/local".
*
* On Windows, the concepts of current drive and drive-specific
* current directory introduce vagueness. This function interprets as
* an absolute file name one that either begins with a directory
* separator such as "\Users\tml" or begins with the root on a drive,
* for example "C:\Windows". The first case also includes UNC paths
* such as "\\myserver\docs\foo". In all cases, either slashes or
* backslashes are accepted.
*
* Note that a file name relative to the current drive root does not
* truly specify a file uniquely over time and across processes, as
* the current drive is a per-process value and can be changed.
*
* File names relative the current directory on some specific drive,
* such as "D:foo/bar", are not interpreted as absolute by this
* function, but they obviously are not relative to the normal current
* directory as returned by getcwd() or g_get_current_dir()
* either. Such paths should be avoided, or need to be handled using
* Windows-specific code.
*
* Returns: %TRUE if @file_name is absolute
*/
gboolean
g_path_is_absolute (const gchar *file_name)
{
g_return_val_if_fail (file_name != NULL, FALSE);
if (G_IS_DIR_SEPARATOR (file_name[0]))
return TRUE;
#ifdef G_OS_WIN32
/* Recognize drive letter on native Windows */
if (g_ascii_isalpha (file_name[0]) &&
file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
return TRUE;
#endif
return FALSE;
}
/**
* g_path_skip_root:
* @file_name: a file name
*
* Returns a pointer into @file_name after the root component,
* i.e. after the "/" in UNIX or "C:\" under Windows. If @file_name
* is not an absolute path it returns %NULL.
*
* Returns: a pointer into @file_name after the root component
*/
const gchar *
g_path_skip_root (const gchar *file_name)
{
g_return_val_if_fail (file_name != NULL, NULL);
#ifdef G_PLATFORM_WIN32
/* Skip \\server\share or //server/share */
if (G_IS_DIR_SEPARATOR (file_name[0]) &&
G_IS_DIR_SEPARATOR (file_name[1]) &&
file_name[2] &&
!G_IS_DIR_SEPARATOR (file_name[2]))
{
gchar *p;
p = strchr (file_name + 2, G_DIR_SEPARATOR);
#ifdef G_OS_WIN32
{
gchar *q;
q = strchr (file_name + 2, '/');
if (p == NULL || (q != NULL && q < p))
p = q;
}
#endif
if (p && p > file_name + 2 && p[1])
{
file_name = p + 1;
while (file_name[0] && !G_IS_DIR_SEPARATOR (file_name[0]))
file_name++;
/* Possibly skip a backslash after the share name */
if (G_IS_DIR_SEPARATOR (file_name[0]))
file_name++;
return (gchar *)file_name;
}
}
#endif
/* Skip initial slashes */
if (G_IS_DIR_SEPARATOR (file_name[0]))
{
while (G_IS_DIR_SEPARATOR (file_name[0]))
file_name++;
return (gchar *)file_name;
}
#ifdef G_OS_WIN32
/* Skip X:\ */
if (g_ascii_isalpha (file_name[0]) &&
file_name[1] == ':' &&
G_IS_DIR_SEPARATOR (file_name[2]))
return (gchar *)file_name + 3;
#endif
return NULL;
}
/**
* g_basename:
* @file_name: the name of the file
*
* Gets the name of the file without any leading directory
* components. It returns a pointer into the given file name
* string.
*
* Return value: the name of the file without any leading
* directory components
*
* Deprecated:2.2: Use g_path_get_basename() instead, but notice
* that g_path_get_basename() allocates new memory for the
* returned string, unlike this function which returns a pointer
* into the argument.
*/
const gchar *
g_basename (const gchar *file_name)
{
gchar *base;
g_return_val_if_fail (file_name != NULL, NULL);
base = strrchr (file_name, G_DIR_SEPARATOR);
#ifdef G_OS_WIN32
{
gchar *q;
q = strrchr (file_name, '/');
if (base == NULL || (q != NULL && q > base))
base = q;
}
#endif
if (base)
return base + 1;
#ifdef G_OS_WIN32
if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
return (gchar*) file_name + 2;
#endif
return (gchar*) file_name;
}
/**
* g_path_get_basename:
* @file_name: the name of the file
*
* Gets the last component of the filename.
*
* If @file_name ends with a directory separator it gets the component
* before the last slash. If @file_name consists only of directory
* separators (and on Windows, possibly a drive letter), a single
* separator is returned. If @file_name is empty, it gets ".".
*
* Return value: a newly allocated string containing the last
* component of the filename
*/
gchar *
g_path_get_basename (const gchar *file_name)
{
gssize base;
gssize last_nonslash;
gsize len;
gchar *retval;
g_return_val_if_fail (file_name != NULL, NULL);
if (file_name[0] == '\0')
return g_strdup (".");
last_nonslash = strlen (file_name) - 1;
while (last_nonslash >= 0 && G_IS_DIR_SEPARATOR (file_name [last_nonslash]))
last_nonslash--;
if (last_nonslash == -1)
/* string only containing slashes */
return g_strdup (G_DIR_SEPARATOR_S);
#ifdef G_OS_WIN32
if (last_nonslash == 1 &&
g_ascii_isalpha (file_name[0]) &&
file_name[1] == ':')
/* string only containing slashes and a drive */
return g_strdup (G_DIR_SEPARATOR_S);
#endif
base = last_nonslash;
while (base >=0 && !G_IS_DIR_SEPARATOR (file_name [base]))
base--;
#ifdef G_OS_WIN32
if (base == -1 &&
g_ascii_isalpha (file_name[0]) &&
file_name[1] == ':')
base = 1;
#endif /* G_OS_WIN32 */
len = last_nonslash - base;
retval = g_malloc (len + 1);
memcpy (retval, file_name + base + 1, len);
retval [len] = '\0';
return retval;
}
/**
* g_dirname:
* @file_name: the name of the file
*
* Gets the directory components of a file name.
*
* If the file name has no directory components "." is returned.
* The returned string should be freed when no longer needed.
*
* Returns: the directory components of the file
*
* Deprecated: use g_path_get_dirname() instead
*/
/**
* g_path_get_dirname:
* @file_name: the name of the file
*
* Gets the directory components of a file name.
*
* If the file name has no directory components "." is returned.
* The returned string should be freed when no longer needed.
*
* Returns: the directory components of the file
*/
gchar *
g_path_get_dirname (const gchar *file_name)
{
gchar *base;
gsize len;
g_return_val_if_fail (file_name != NULL, NULL);
base = strrchr (file_name, G_DIR_SEPARATOR);
#ifdef G_OS_WIN32
{
gchar *q;
q = strrchr (file_name, '/');
if (base == NULL || (q != NULL && q > base))
base = q;
}
#endif
if (!base)
{
#ifdef G_OS_WIN32
if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
{
gchar drive_colon_dot[4];
drive_colon_dot[0] = file_name[0];
drive_colon_dot[1] = ':';
drive_colon_dot[2] = '.';
drive_colon_dot[3] = '\0';
return g_strdup (drive_colon_dot);
}
#endif
return g_strdup (".");
}
while (base > file_name && G_IS_DIR_SEPARATOR (*base))
base--;
#ifdef G_OS_WIN32
/* base points to the char before the last slash.
*
* In case file_name is the root of a drive (X:\) or a child of the
* root of a drive (X:\foo), include the slash.
*
* In case file_name is the root share of an UNC path
* (\\server\share), add a slash, returning \\server\share\ .
*
* In case file_name is a direct child of a share in an UNC path
* (\\server\share\foo), include the slash after the share name,
* returning \\server\share\ .
*/
if (base == file_name + 1 &&
g_ascii_isalpha (file_name[0]) &&
file_name[1] == ':')
base++;
else if (G_IS_DIR_SEPARATOR (file_name[0]) &&
G_IS_DIR_SEPARATOR (file_name[1]) &&
file_name[2] &&
!G_IS_DIR_SEPARATOR (file_name[2]) &&
base >= file_name + 2)
{
const gchar *p = file_name + 2;
while (*p && !G_IS_DIR_SEPARATOR (*p))
p++;
if (p == base + 1)
{
len = (guint) strlen (file_name) + 1;
base = g_new (gchar, len + 1);
strcpy (base, file_name);
base[len-1] = G_DIR_SEPARATOR;
base[len] = 0;
return base;
}
if (G_IS_DIR_SEPARATOR (*p))
{
p++;
while (*p && !G_IS_DIR_SEPARATOR (*p))
p++;
if (p == base + 1)
base++;
}
}
#endif
len = (guint) 1 + base - file_name;
base = g_new (gchar, len + 1);
g_memmove (base, file_name, len);
base[len] = 0;
return base;
}
#if defined(MAXPATHLEN)
#define G_PATH_LENGTH MAXPATHLEN
#elif defined(PATH_MAX)
#define G_PATH_LENGTH PATH_MAX
#elif defined(_PC_PATH_MAX)
#define G_PATH_LENGTH sysconf(_PC_PATH_MAX)
#else
#define G_PATH_LENGTH 2048
#endif
/**
* g_get_current_dir:
*
* Gets the current directory.
*
* The returned string should be freed when no longer needed.
* The encoding of the returned string is system defined.
* On Windows, it is always UTF-8.
*
* Returns: the current directory
*/
gchar *
g_get_current_dir (void)
{
#ifdef G_OS_WIN32
gchar *dir = NULL;
wchar_t dummy[2], *wdir;
int len;
len = GetCurrentDirectoryW (2, dummy);
wdir = g_new (wchar_t, len);
if (GetCurrentDirectoryW (len, wdir) == len - 1)
dir = g_utf16_to_utf8 (wdir, -1, NULL, NULL, NULL);
g_free (wdir);
if (dir == NULL)
dir = g_strdup ("\\");
return dir;
#else
gchar *buffer = NULL;
gchar *dir = NULL;
static gulong max_len = 0;
if (max_len == 0)
max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
/* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
* and, if that wasn't bad enough, hangs in doing so.
*/
#if (defined (sun) && !defined (__SVR4)) || !defined(HAVE_GETCWD)
buffer = g_new (gchar, max_len + 1);
*buffer = 0;
dir = getwd (buffer);
#else
while (max_len < G_MAXULONG / 2)
{
g_free (buffer);
buffer = g_new (gchar, max_len + 1);
*buffer = 0;
dir = getcwd (buffer, max_len);
if (dir || errno != ERANGE)
break;
max_len *= 2;
}
#endif /* !sun || !HAVE_GETCWD */
if (!dir || !*buffer)
{
/* hm, should we g_error() out here?
* this can happen if e.g. "./" has mode \0000
*/
buffer[0] = G_DIR_SEPARATOR;
buffer[1] = 0;
}
dir = g_strdup (buffer);
g_free (buffer);
return dir;
#endif /* !G_OS_WIN32 */
}
/* NOTE : Keep this part last to ensure nothing in this file uses thn
* below binary compatibility versions.
*/
#if defined (G_OS_WIN32) && !defined (_WIN64)
/* Binary compatibility versions. Will be called by code compiled
* against quite old (pre-2.8, I think) headers only, not from more
* recently compiled code.
*/
#undef g_file_test
gboolean
g_file_test (const gchar *filename,
GFileTest test)
{
gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, NULL);
gboolean retval;
if (utf8_filename == NULL)
return FALSE;
retval = g_file_test_utf8 (utf8_filename, test);
g_free (utf8_filename);
return retval;
}
#undef g_file_get_contents
gboolean
g_file_get_contents (const gchar *filename,
gchar **contents,
gsize *length,
GError **error)
{
gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
gboolean retval;
if (utf8_filename == NULL)
return FALSE;
retval = g_file_get_contents_utf8 (utf8_filename, contents, length, error);
g_free (utf8_filename);
return retval;
}
#undef g_mkstemp
static gint
wrap_libc_open (const gchar *filename,
int flags,
int mode)
{
return open (filename, flags, mode);
}
gint
g_mkstemp (gchar *tmpl)
{
/* This is the backward compatibility system codepage version,
* thus use normal open().
*/
return get_tmp_file (tmpl, wrap_libc_open,
O_RDWR | O_CREAT | O_EXCL, 0600);
}
#undef g_file_open_tmp
gint
g_file_open_tmp (const gchar *tmpl,
gchar **name_used,
GError **error)
{
gchar *utf8_tmpl = g_locale_to_utf8 (tmpl, -1, NULL, NULL, error);
gchar *utf8_name_used;
gint retval;
if (utf8_tmpl == NULL)
return -1;
retval = g_file_open_tmp_utf8 (utf8_tmpl, &utf8_name_used, error);
if (retval == -1)
return -1;
if (name_used)
*name_used = g_locale_from_utf8 (utf8_name_used, -1, NULL, NULL, NULL);
g_free (utf8_name_used);
return retval;
}
#undef g_get_current_dir
gchar *
g_get_current_dir (void)
{
gchar *utf8_dir = g_get_current_dir_utf8 ();
gchar *dir = g_locale_from_utf8 (utf8_dir, -1, NULL, NULL, NULL);
g_free (utf8_dir);
return dir;
}
#endif
pkg-config-0.29.1/glib/glib/gtestutils.h 0000664 0001750 0001750 00000051652 12651243552 015002 0000000 0000000 /* GLib testing utilities
* Copyright (C) 2007 Imendio AB
* Authors: Tim Janik
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __G_TEST_UTILS_H__
#define __G_TEST_UTILS_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
#include
#include
#include
G_BEGIN_DECLS
typedef struct GTestCase GTestCase;
typedef struct GTestSuite GTestSuite;
typedef void (*GTestFunc) (void);
typedef void (*GTestDataFunc) (gconstpointer user_data);
typedef void (*GTestFixtureFunc) (gpointer fixture,
gconstpointer user_data);
/* assertion API */
#define g_assert_cmpstr(s1, cmp, s2) do { const char *__s1 = (s1), *__s2 = (s2); \
if (g_strcmp0 (__s1, __s2) cmp 0) ; else \
g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#s1 " " #cmp " " #s2, __s1, #cmp, __s2); } while (0)
#define g_assert_cmpint(n1, cmp, n2) do { gint64 __n1 = (n1), __n2 = (n2); \
if (__n1 cmp __n2) ; else \
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#n1 " " #cmp " " #n2, __n1, #cmp, __n2, 'i'); } while (0)
#define g_assert_cmpuint(n1, cmp, n2) do { guint64 __n1 = (n1), __n2 = (n2); \
if (__n1 cmp __n2) ; else \
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#n1 " " #cmp " " #n2, __n1, #cmp, __n2, 'i'); } while (0)
#define g_assert_cmphex(n1, cmp, n2) do { guint64 __n1 = (n1), __n2 = (n2); \
if (__n1 cmp __n2) ; else \
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#n1 " " #cmp " " #n2, __n1, #cmp, __n2, 'x'); } while (0)
#define g_assert_cmpfloat(n1,cmp,n2) do { long double __n1 = (n1), __n2 = (n2); \
if (__n1 cmp __n2) ; else \
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#n1 " " #cmp " " #n2, __n1, #cmp, __n2, 'f'); } while (0)
#define g_assert_no_error(err) do { if (err) \
g_assertion_message_error (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#err, err, 0, 0); } while (0)
#define g_assert_error(err, dom, c) do { if (!err || (err)->domain != dom || (err)->code != c) \
g_assertion_message_error (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#err, err, dom, c); } while (0)
#define g_assert_true(expr) do { if G_LIKELY (expr) ; else \
g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#expr); \
} while (0)
#define g_assert_false(expr) do { if G_LIKELY (!(expr)) ; else \
g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#expr); \
} while (0)
#define g_assert_null(expr) do { if G_LIKELY ((expr) == NULL) ; else \
g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#expr); \
} while (0)
#ifdef G_DISABLE_ASSERT
#define g_assert_not_reached() do { (void) 0; } while (0)
#define g_assert(expr) do { (void) 0; } while (0)
#else /* !G_DISABLE_ASSERT */
#define g_assert_not_reached() do { g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, NULL); } while (0)
#define g_assert(expr) do { if G_LIKELY (expr) ; else \
g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#expr); \
} while (0)
#endif /* !G_DISABLE_ASSERT */
GLIB_AVAILABLE_IN_ALL
int g_strcmp0 (const char *str1,
const char *str2);
/* report performance results */
GLIB_AVAILABLE_IN_ALL
void g_test_minimized_result (double minimized_quantity,
const char *format,
...) G_GNUC_PRINTF (2, 3);
GLIB_AVAILABLE_IN_ALL
void g_test_maximized_result (double maximized_quantity,
const char *format,
...) G_GNUC_PRINTF (2, 3);
/* initialize testing framework */
GLIB_AVAILABLE_IN_ALL
void g_test_init (int *argc,
char ***argv,
...);
/* query testing framework config */
#define g_test_initialized() (g_test_config_vars->test_initialized)
#define g_test_quick() (g_test_config_vars->test_quick)
#define g_test_slow() (!g_test_config_vars->test_quick)
#define g_test_thorough() (!g_test_config_vars->test_quick)
#define g_test_perf() (g_test_config_vars->test_perf)
#define g_test_verbose() (g_test_config_vars->test_verbose)
#define g_test_quiet() (g_test_config_vars->test_quiet)
#define g_test_undefined() (g_test_config_vars->test_undefined)
GLIB_AVAILABLE_IN_2_38
gboolean g_test_subprocess (void);
/* run all tests under toplevel suite (path: /) */
GLIB_AVAILABLE_IN_ALL
int g_test_run (void);
/* hook up a test functions under test path */
GLIB_AVAILABLE_IN_ALL
void g_test_add_func (const char *testpath,
GTestFunc test_func);
GLIB_AVAILABLE_IN_ALL
void g_test_add_data_func (const char *testpath,
gconstpointer test_data,
GTestDataFunc test_func);
GLIB_AVAILABLE_IN_2_34
void g_test_add_data_func_full (const char *testpath,
gpointer test_data,
GTestDataFunc test_func,
GDestroyNotify data_free_func);
/* tell about failure */
GLIB_AVAILABLE_IN_2_30
void g_test_fail (void);
GLIB_AVAILABLE_IN_2_38
void g_test_incomplete (const gchar *msg);
GLIB_AVAILABLE_IN_2_38
void g_test_skip (const gchar *msg);
GLIB_AVAILABLE_IN_2_38
gboolean g_test_failed (void);
GLIB_AVAILABLE_IN_2_38
void g_test_set_nonfatal_assertions (void);
/* hook up a test with fixture under test path */
#define g_test_add(testpath, Fixture, tdata, fsetup, ftest, fteardown) \
G_STMT_START { \
void (*add_vtable) (const char*, \
gsize, \
gconstpointer, \
void (*) (Fixture*, gconstpointer), \
void (*) (Fixture*, gconstpointer), \
void (*) (Fixture*, gconstpointer)) = (void (*) (const gchar *, gsize, gconstpointer, void (*) (Fixture*, gconstpointer), void (*) (Fixture*, gconstpointer), void (*) (Fixture*, gconstpointer))) g_test_add_vtable; \
add_vtable \
(testpath, sizeof (Fixture), tdata, fsetup, ftest, fteardown); \
} G_STMT_END
/* add test messages to the test report */
GLIB_AVAILABLE_IN_ALL
void g_test_message (const char *format,
...) G_GNUC_PRINTF (1, 2);
GLIB_AVAILABLE_IN_ALL
void g_test_bug_base (const char *uri_pattern);
GLIB_AVAILABLE_IN_ALL
void g_test_bug (const char *bug_uri_snippet);
/* measure test timings */
GLIB_AVAILABLE_IN_ALL
void g_test_timer_start (void);
GLIB_AVAILABLE_IN_ALL
double g_test_timer_elapsed (void); /* elapsed seconds */
GLIB_AVAILABLE_IN_ALL
double g_test_timer_last (void); /* repeat last elapsed() result */
/* automatically g_free or g_object_unref upon teardown */
GLIB_AVAILABLE_IN_ALL
void g_test_queue_free (gpointer gfree_pointer);
GLIB_AVAILABLE_IN_ALL
void g_test_queue_destroy (GDestroyNotify destroy_func,
gpointer destroy_data);
#define g_test_queue_unref(gobject) g_test_queue_destroy (g_object_unref, gobject)
typedef enum {
G_TEST_TRAP_SILENCE_STDOUT = 1 << 7,
G_TEST_TRAP_SILENCE_STDERR = 1 << 8,
G_TEST_TRAP_INHERIT_STDIN = 1 << 9
} GTestTrapFlags;
GLIB_DEPRECATED_IN_2_38_FOR (g_test_trap_subprocess)
gboolean g_test_trap_fork (guint64 usec_timeout,
GTestTrapFlags test_trap_flags);
typedef enum {
G_TEST_SUBPROCESS_INHERIT_STDIN = 1 << 0,
G_TEST_SUBPROCESS_INHERIT_STDOUT = 1 << 1,
G_TEST_SUBPROCESS_INHERIT_STDERR = 1 << 2
} GTestSubprocessFlags;
GLIB_AVAILABLE_IN_2_38
void g_test_trap_subprocess (const char *test_path,
guint64 usec_timeout,
GTestSubprocessFlags test_flags);
GLIB_AVAILABLE_IN_ALL
gboolean g_test_trap_has_passed (void);
GLIB_AVAILABLE_IN_ALL
gboolean g_test_trap_reached_timeout (void);
#define g_test_trap_assert_passed() g_test_trap_assertions (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 0, 0)
#define g_test_trap_assert_failed() g_test_trap_assertions (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 1, 0)
#define g_test_trap_assert_stdout(soutpattern) g_test_trap_assertions (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 2, soutpattern)
#define g_test_trap_assert_stdout_unmatched(soutpattern) g_test_trap_assertions (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 3, soutpattern)
#define g_test_trap_assert_stderr(serrpattern) g_test_trap_assertions (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 4, serrpattern)
#define g_test_trap_assert_stderr_unmatched(serrpattern) g_test_trap_assertions (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 5, serrpattern)
/* provide seed-able random numbers for tests */
#define g_test_rand_bit() (0 != (g_test_rand_int() & (1 << 15)))
GLIB_AVAILABLE_IN_ALL
gint32 g_test_rand_int (void);
GLIB_AVAILABLE_IN_ALL
gint32 g_test_rand_int_range (gint32 begin,
gint32 end);
GLIB_AVAILABLE_IN_ALL
double g_test_rand_double (void);
GLIB_AVAILABLE_IN_ALL
double g_test_rand_double_range (double range_start,
double range_end);
/* semi-internal API */
GLIB_AVAILABLE_IN_ALL
GTestCase* g_test_create_case (const char *test_name,
gsize data_size,
gconstpointer test_data,
GTestFixtureFunc data_setup,
GTestFixtureFunc data_test,
GTestFixtureFunc data_teardown);
GLIB_AVAILABLE_IN_ALL
GTestSuite* g_test_create_suite (const char *suite_name);
GLIB_AVAILABLE_IN_ALL
GTestSuite* g_test_get_root (void);
GLIB_AVAILABLE_IN_ALL
void g_test_suite_add (GTestSuite *suite,
GTestCase *test_case);
GLIB_AVAILABLE_IN_ALL
void g_test_suite_add_suite (GTestSuite *suite,
GTestSuite *nestedsuite);
GLIB_AVAILABLE_IN_ALL
int g_test_run_suite (GTestSuite *suite);
/* internal ABI */
GLIB_AVAILABLE_IN_ALL
void g_test_trap_assertions (const char *domain,
const char *file,
int line,
const char *func,
guint64 assertion_flags, /* 0-pass, 1-fail, 2-outpattern, 4-errpattern */
const char *pattern);
GLIB_AVAILABLE_IN_ALL
void g_assertion_message (const char *domain,
const char *file,
int line,
const char *func,
const char *message);
GLIB_AVAILABLE_IN_ALL
void g_assertion_message_expr (const char *domain,
const char *file,
int line,
const char *func,
const char *expr) G_GNUC_NORETURN;
GLIB_AVAILABLE_IN_ALL
void g_assertion_message_cmpstr (const char *domain,
const char *file,
int line,
const char *func,
const char *expr,
const char *arg1,
const char *cmp,
const char *arg2);
GLIB_AVAILABLE_IN_ALL
void g_assertion_message_cmpnum (const char *domain,
const char *file,
int line,
const char *func,
const char *expr,
long double arg1,
const char *cmp,
long double arg2,
char numtype);
GLIB_AVAILABLE_IN_ALL
void g_assertion_message_error (const char *domain,
const char *file,
int line,
const char *func,
const char *expr,
const GError *error,
GQuark error_domain,
int error_code);
GLIB_AVAILABLE_IN_ALL
void g_test_add_vtable (const char *testpath,
gsize data_size,
gconstpointer test_data,
GTestFixtureFunc data_setup,
GTestFixtureFunc data_test,
GTestFixtureFunc data_teardown);
typedef struct {
gboolean test_initialized;
gboolean test_quick; /* disable thorough tests */
gboolean test_perf; /* run performance tests */
gboolean test_verbose; /* extra info */
gboolean test_quiet; /* reduce output */
gboolean test_undefined; /* run tests that are meant to assert */
} GTestConfig;
GLIB_VAR const GTestConfig * const g_test_config_vars;
/* internal logging API */
typedef enum {
G_TEST_LOG_NONE,
G_TEST_LOG_ERROR, /* s:msg */
G_TEST_LOG_START_BINARY, /* s:binaryname s:seed */
G_TEST_LOG_LIST_CASE, /* s:testpath */
G_TEST_LOG_SKIP_CASE, /* s:testpath */
G_TEST_LOG_START_CASE, /* s:testpath */
G_TEST_LOG_STOP_CASE, /* d:status d:nforks d:elapsed */
G_TEST_LOG_MIN_RESULT, /* s:blurb d:result */
G_TEST_LOG_MAX_RESULT, /* s:blurb d:result */
G_TEST_LOG_MESSAGE, /* s:blurb */
G_TEST_LOG_START_SUITE,
G_TEST_LOG_STOP_SUITE
} GTestLogType;
typedef struct {
GTestLogType log_type;
guint n_strings;
gchar **strings; /* NULL terminated */
guint n_nums;
long double *nums;
} GTestLogMsg;
typedef struct {
/*< private >*/
GString *data;
GSList *msgs;
} GTestLogBuffer;
GLIB_AVAILABLE_IN_ALL
const char* g_test_log_type_name (GTestLogType log_type);
GLIB_AVAILABLE_IN_ALL
GTestLogBuffer* g_test_log_buffer_new (void);
GLIB_AVAILABLE_IN_ALL
void g_test_log_buffer_free (GTestLogBuffer *tbuffer);
GLIB_AVAILABLE_IN_ALL
void g_test_log_buffer_push (GTestLogBuffer *tbuffer,
guint n_bytes,
const guint8 *bytes);
GLIB_AVAILABLE_IN_ALL
GTestLogMsg* g_test_log_buffer_pop (GTestLogBuffer *tbuffer);
GLIB_AVAILABLE_IN_ALL
void g_test_log_msg_free (GTestLogMsg *tmsg);
/**
* GTestLogFatalFunc:
* @log_domain: the log domain of the message
* @log_level: the log level of the message (including the fatal and recursion flags)
* @message: the message to process
* @user_data: user data, set in g_test_log_set_fatal_handler()
*
* Specifies the prototype of fatal log handler functions.
*
* Return value: %TRUE if the program should abort, %FALSE otherwise
*
* Since: 2.22
*/
typedef gboolean (*GTestLogFatalFunc) (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data);
GLIB_AVAILABLE_IN_ALL
void
g_test_log_set_fatal_handler (GTestLogFatalFunc log_func,
gpointer user_data);
GLIB_AVAILABLE_IN_2_34
void g_test_expect_message (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *pattern);
GLIB_AVAILABLE_IN_2_34
void g_test_assert_expected_messages_internal (const char *domain,
const char *file,
int line,
const char *func);
typedef enum
{
G_TEST_DIST,
G_TEST_BUILT
} GTestFileType;
GLIB_AVAILABLE_IN_2_38
gchar * g_test_build_filename (GTestFileType file_type,
const gchar *first_path,
...) G_GNUC_NULL_TERMINATED;
GLIB_AVAILABLE_IN_2_38
const gchar *g_test_get_dir (GTestFileType file_type);
GLIB_AVAILABLE_IN_2_38
const gchar *g_test_get_filename (GTestFileType file_type,
const gchar *first_path,
...) G_GNUC_NULL_TERMINATED;
#define g_test_assert_expected_messages() g_test_assert_expected_messages_internal (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC)
G_END_DECLS
#endif /* __G_TEST_UTILS_H__ */
pkg-config-0.29.1/glib/glib/gmem.h 0000664 0001750 0001750 00000027005 12651243552 013513 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __G_MEM_H__
#define __G_MEM_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
G_BEGIN_DECLS
/**
* GMemVTable:
* @malloc: function to use for allocating memory.
* @realloc: function to use for reallocating memory.
* @free: function to use to free memory.
* @calloc: function to use for allocating zero-filled memory.
* @try_malloc: function to use for allocating memory without a default error handler.
* @try_realloc: function to use for reallocating memory without a default error handler.
*
* A set of functions used to perform memory allocation. The same #GMemVTable must
* be used for all allocations in the same program; a call to g_mem_set_vtable(),
* if it exists, should be prior to any use of GLib.
*/
typedef struct _GMemVTable GMemVTable;
#if GLIB_SIZEOF_VOID_P > GLIB_SIZEOF_LONG
/**
* G_MEM_ALIGN:
*
* Indicates the number of bytes to which memory will be aligned on the
* current platform.
*/
# define G_MEM_ALIGN GLIB_SIZEOF_VOID_P
#else /* GLIB_SIZEOF_VOID_P <= GLIB_SIZEOF_LONG */
# define G_MEM_ALIGN GLIB_SIZEOF_LONG
#endif /* GLIB_SIZEOF_VOID_P <= GLIB_SIZEOF_LONG */
/* Memory allocation functions
*/
GLIB_AVAILABLE_IN_ALL
void g_free (gpointer mem);
GLIB_AVAILABLE_IN_2_34
void g_clear_pointer (gpointer *pp,
GDestroyNotify destroy);
GLIB_AVAILABLE_IN_ALL
gpointer g_malloc (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
GLIB_AVAILABLE_IN_ALL
gpointer g_malloc0 (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
GLIB_AVAILABLE_IN_ALL
gpointer g_realloc (gpointer mem,
gsize n_bytes) G_GNUC_WARN_UNUSED_RESULT;
GLIB_AVAILABLE_IN_ALL
gpointer g_try_malloc (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
GLIB_AVAILABLE_IN_ALL
gpointer g_try_malloc0 (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
GLIB_AVAILABLE_IN_ALL
gpointer g_try_realloc (gpointer mem,
gsize n_bytes) G_GNUC_WARN_UNUSED_RESULT;
GLIB_AVAILABLE_IN_ALL
gpointer g_malloc_n (gsize n_blocks,
gsize n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2);
GLIB_AVAILABLE_IN_ALL
gpointer g_malloc0_n (gsize n_blocks,
gsize n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2);
GLIB_AVAILABLE_IN_ALL
gpointer g_realloc_n (gpointer mem,
gsize n_blocks,
gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT;
GLIB_AVAILABLE_IN_ALL
gpointer g_try_malloc_n (gsize n_blocks,
gsize n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2);
GLIB_AVAILABLE_IN_ALL
gpointer g_try_malloc0_n (gsize n_blocks,
gsize n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2);
GLIB_AVAILABLE_IN_ALL
gpointer g_try_realloc_n (gpointer mem,
gsize n_blocks,
gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT;
#define g_clear_pointer(pp, destroy) \
G_STMT_START { \
G_STATIC_ASSERT (sizeof *(pp) == sizeof (gpointer)); \
/* Only one access, please */ \
gpointer *_pp = (gpointer *) (pp); \
gpointer _p; \
/* This assignment is needed to avoid a gcc warning */ \
GDestroyNotify _destroy = (GDestroyNotify) (destroy); \
\
(void) (0 ? (gpointer) *(pp) : 0); \
do \
_p = g_atomic_pointer_get (_pp); \
while G_UNLIKELY (!g_atomic_pointer_compare_and_exchange (_pp, _p, NULL)); \
\
if (_p) \
_destroy (_p); \
} G_STMT_END
/* Optimise: avoid the call to the (slower) _n function if we can
* determine at compile-time that no overflow happens.
*/
#if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__)
# define _G_NEW(struct_type, n_structs, func) \
(struct_type *) (G_GNUC_EXTENSION ({ \
gsize __n = (gsize) (n_structs); \
gsize __s = sizeof (struct_type); \
gpointer __p; \
if (__s == 1) \
__p = g_##func (__n); \
else if (__builtin_constant_p (__n) && \
(__s == 0 || __n <= G_MAXSIZE / __s)) \
__p = g_##func (__n * __s); \
else \
__p = g_##func##_n (__n, __s); \
__p; \
}))
# define _G_RENEW(struct_type, mem, n_structs, func) \
(struct_type *) (G_GNUC_EXTENSION ({ \
gsize __n = (gsize) (n_structs); \
gsize __s = sizeof (struct_type); \
gpointer __p = (gpointer) (mem); \
if (__s == 1) \
__p = g_##func (__p, __n); \
else if (__builtin_constant_p (__n) && \
(__s == 0 || __n <= G_MAXSIZE / __s)) \
__p = g_##func (__p, __n * __s); \
else \
__p = g_##func##_n (__p, __n, __s); \
__p; \
}))
#else
/* Unoptimised version: always call the _n() function. */
#define _G_NEW(struct_type, n_structs, func) \
((struct_type *) g_##func##_n ((n_structs), sizeof (struct_type)))
#define _G_RENEW(struct_type, mem, n_structs, func) \
((struct_type *) g_##func##_n (mem, (n_structs), sizeof (struct_type)))
#endif
/**
* g_new:
* @struct_type: the type of the elements to allocate
* @n_structs: the number of elements to allocate
*
* Allocates @n_structs elements of type @struct_type.
* The returned pointer is cast to a pointer to the given type.
* If @n_structs is 0 it returns %NULL.
* Care is taken to avoid overflow when calculating the size of the allocated block.
*
* Since the returned pointer is already casted to the right type,
* it is normally unnecessary to cast it explicitly, and doing
* so might hide memory allocation errors.
*
* Returns: a pointer to the allocated memory, cast to a pointer to @struct_type
*/
#define g_new(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc)
/**
* g_new0:
* @struct_type: the type of the elements to allocate.
* @n_structs: the number of elements to allocate.
*
* Allocates @n_structs elements of type @struct_type, initialized to 0's.
* The returned pointer is cast to a pointer to the given type.
* If @n_structs is 0 it returns %NULL.
* Care is taken to avoid overflow when calculating the size of the allocated block.
*
* Since the returned pointer is already casted to the right type,
* it is normally unnecessary to cast it explicitly, and doing
* so might hide memory allocation errors.
*
* Returns: a pointer to the allocated memory, cast to a pointer to @struct_type.
*/
#define g_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc0)
/**
* g_renew:
* @struct_type: the type of the elements to allocate
* @mem: the currently allocated memory
* @n_structs: the number of elements to allocate
*
* Reallocates the memory pointed to by @mem, so that it now has space for
* @n_structs elements of type @struct_type. It returns the new address of
* the memory, which may have been moved.
* Care is taken to avoid overflow when calculating the size of the allocated block.
*
* Returns: a pointer to the new allocated memory, cast to a pointer to @struct_type
*/
#define g_renew(struct_type, mem, n_structs) _G_RENEW (struct_type, mem, n_structs, realloc)
/**
* g_try_new:
* @struct_type: the type of the elements to allocate
* @n_structs: the number of elements to allocate
*
* Attempts to allocate @n_structs elements of type @struct_type, and returns
* %NULL on failure. Contrast with g_new(), which aborts the program on failure.
* The returned pointer is cast to a pointer to the given type.
* The function returns %NULL when @n_structs is 0 of if an overflow occurs.
*
* Since: 2.8
* Returns: a pointer to the allocated memory, cast to a pointer to @struct_type
*/
#define g_try_new(struct_type, n_structs) _G_NEW (struct_type, n_structs, try_malloc)
/**
* g_try_new0:
* @struct_type: the type of the elements to allocate
* @n_structs: the number of elements to allocate
*
* Attempts to allocate @n_structs elements of type @struct_type, initialized
* to 0's, and returns %NULL on failure. Contrast with g_new0(), which aborts
* the program on failure.
* The returned pointer is cast to a pointer to the given type.
* The function returns %NULL when @n_structs is 0 of if an overflow occurs.
*
* Since: 2.8
* Returns: a pointer to the allocated memory, cast to a pointer to @struct_type
*/
#define g_try_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, try_malloc0)
/**
* g_try_renew:
* @struct_type: the type of the elements to allocate
* @mem: the currently allocated memory
* @n_structs: the number of elements to allocate
*
* Attempts to reallocate the memory pointed to by @mem, so that it now has
* space for @n_structs elements of type @struct_type, and returns %NULL on
* failure. Contrast with g_renew(), which aborts the program on failure.
* It returns the new address of the memory, which may have been moved.
* The function returns %NULL if an overflow occurs.
*
* Since: 2.8
* Returns: a pointer to the new allocated memory, cast to a pointer to @struct_type
*/
#define g_try_renew(struct_type, mem, n_structs) _G_RENEW (struct_type, mem, n_structs, try_realloc)
/* Memory allocation virtualization for debugging purposes
* g_mem_set_vtable() has to be the very first GLib function called
* if being used
*/
struct _GMemVTable {
gpointer (*malloc) (gsize n_bytes);
gpointer (*realloc) (gpointer mem,
gsize n_bytes);
void (*free) (gpointer mem);
/* optional; set to NULL if not used ! */
gpointer (*calloc) (gsize n_blocks,
gsize n_block_bytes);
gpointer (*try_malloc) (gsize n_bytes);
gpointer (*try_realloc) (gpointer mem,
gsize n_bytes);
};
GLIB_AVAILABLE_IN_ALL
void g_mem_set_vtable (GMemVTable *vtable);
GLIB_AVAILABLE_IN_ALL
gboolean g_mem_is_system_malloc (void);
GLIB_VAR gboolean g_mem_gc_friendly;
/* Memory profiler and checker, has to be enabled via g_mem_set_vtable()
*/
GLIB_VAR GMemVTable *glib_mem_profiler_table;
GLIB_AVAILABLE_IN_ALL
void g_mem_profile (void);
G_END_DECLS
#endif /* __G_MEM_H__ */
pkg-config-0.29.1/glib/glib/gasyncqueue.h 0000664 0001750 0001750 00000011667 12651243552 015126 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __G_ASYNCQUEUE_H__
#define __G_ASYNCQUEUE_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
G_BEGIN_DECLS
typedef struct _GAsyncQueue GAsyncQueue;
GLIB_AVAILABLE_IN_ALL
GAsyncQueue *g_async_queue_new (void);
GLIB_AVAILABLE_IN_ALL
GAsyncQueue *g_async_queue_new_full (GDestroyNotify item_free_func);
GLIB_AVAILABLE_IN_ALL
void g_async_queue_lock (GAsyncQueue *queue);
GLIB_AVAILABLE_IN_ALL
void g_async_queue_unlock (GAsyncQueue *queue);
GLIB_AVAILABLE_IN_ALL
GAsyncQueue *g_async_queue_ref (GAsyncQueue *queue);
GLIB_AVAILABLE_IN_ALL
void g_async_queue_unref (GAsyncQueue *queue);
GLIB_DEPRECATED_FOR(g_async_queue_ref)
void g_async_queue_ref_unlocked (GAsyncQueue *queue);
GLIB_DEPRECATED_FOR(g_async_queue_unref)
void g_async_queue_unref_and_unlock (GAsyncQueue *queue);
GLIB_AVAILABLE_IN_ALL
void g_async_queue_push (GAsyncQueue *queue,
gpointer data);
GLIB_AVAILABLE_IN_ALL
void g_async_queue_push_unlocked (GAsyncQueue *queue,
gpointer data);
GLIB_AVAILABLE_IN_ALL
void g_async_queue_push_sorted (GAsyncQueue *queue,
gpointer data,
GCompareDataFunc func,
gpointer user_data);
GLIB_AVAILABLE_IN_ALL
void g_async_queue_push_sorted_unlocked (GAsyncQueue *queue,
gpointer data,
GCompareDataFunc func,
gpointer user_data);
GLIB_AVAILABLE_IN_ALL
gpointer g_async_queue_pop (GAsyncQueue *queue);
GLIB_AVAILABLE_IN_ALL
gpointer g_async_queue_pop_unlocked (GAsyncQueue *queue);
GLIB_AVAILABLE_IN_ALL
gpointer g_async_queue_try_pop (GAsyncQueue *queue);
GLIB_AVAILABLE_IN_ALL
gpointer g_async_queue_try_pop_unlocked (GAsyncQueue *queue);
GLIB_AVAILABLE_IN_ALL
gpointer g_async_queue_timeout_pop (GAsyncQueue *queue,
guint64 timeout);
GLIB_AVAILABLE_IN_ALL
gpointer g_async_queue_timeout_pop_unlocked (GAsyncQueue *queue,
guint64 timeout);
GLIB_AVAILABLE_IN_ALL
gint g_async_queue_length (GAsyncQueue *queue);
GLIB_AVAILABLE_IN_ALL
gint g_async_queue_length_unlocked (GAsyncQueue *queue);
GLIB_AVAILABLE_IN_ALL
void g_async_queue_sort (GAsyncQueue *queue,
GCompareDataFunc func,
gpointer user_data);
GLIB_AVAILABLE_IN_ALL
void g_async_queue_sort_unlocked (GAsyncQueue *queue,
GCompareDataFunc func,
gpointer user_data);
GLIB_DEPRECATED_FOR(g_async_queue_timeout_pop)
gpointer g_async_queue_timed_pop (GAsyncQueue *queue,
GTimeVal *end_time);
GLIB_DEPRECATED_FOR(g_async_queue_timeout_pop_unlocked)
gpointer g_async_queue_timed_pop_unlocked (GAsyncQueue *queue,
GTimeVal *end_time);
G_END_DECLS
#endif /* __G_ASYNCQUEUE_H__ */
pkg-config-0.29.1/glib/glib/gdataset.h 0000664 0001750 0001750 00000014253 12651243552 014363 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __G_DATASET_H__
#define __G_DATASET_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
G_BEGIN_DECLS
typedef struct _GData GData;
typedef void (*GDataForeachFunc) (GQuark key_id,
gpointer data,
gpointer user_data);
/* Keyed Data List
*/
GLIB_AVAILABLE_IN_ALL
void g_datalist_init (GData **datalist);
GLIB_AVAILABLE_IN_ALL
void g_datalist_clear (GData **datalist);
GLIB_AVAILABLE_IN_ALL
gpointer g_datalist_id_get_data (GData **datalist,
GQuark key_id);
GLIB_AVAILABLE_IN_ALL
void g_datalist_id_set_data_full (GData **datalist,
GQuark key_id,
gpointer data,
GDestroyNotify destroy_func);
typedef gpointer (*GDuplicateFunc) (gpointer data, gpointer user_data);
GLIB_AVAILABLE_IN_2_34
gpointer g_datalist_id_dup_data (GData **datalist,
GQuark key_id,
GDuplicateFunc dup_func,
gpointer user_data);
GLIB_AVAILABLE_IN_2_34
gboolean g_datalist_id_replace_data (GData **datalist,
GQuark key_id,
gpointer oldval,
gpointer newval,
GDestroyNotify destroy,
GDestroyNotify *old_destroy);
GLIB_AVAILABLE_IN_ALL
gpointer g_datalist_id_remove_no_notify (GData **datalist,
GQuark key_id);
GLIB_AVAILABLE_IN_ALL
void g_datalist_foreach (GData **datalist,
GDataForeachFunc func,
gpointer user_data);
/**
* G_DATALIST_FLAGS_MASK:
*
* A bitmask that restricts the possible flags passed to
* g_datalist_set_flags(). Passing a flags value where
* flags & ~G_DATALIST_FLAGS_MASK != 0 is an error.
*/
#define G_DATALIST_FLAGS_MASK 0x3
GLIB_AVAILABLE_IN_ALL
void g_datalist_set_flags (GData **datalist,
guint flags);
GLIB_AVAILABLE_IN_ALL
void g_datalist_unset_flags (GData **datalist,
guint flags);
GLIB_AVAILABLE_IN_ALL
guint g_datalist_get_flags (GData **datalist);
#define g_datalist_id_set_data(dl, q, d) \
g_datalist_id_set_data_full ((dl), (q), (d), NULL)
#define g_datalist_id_remove_data(dl, q) \
g_datalist_id_set_data ((dl), (q), NULL)
#define g_datalist_set_data_full(dl, k, d, f) \
g_datalist_id_set_data_full ((dl), g_quark_from_string (k), (d), (f))
#define g_datalist_remove_no_notify(dl, k) \
g_datalist_id_remove_no_notify ((dl), g_quark_try_string (k))
#define g_datalist_set_data(dl, k, d) \
g_datalist_set_data_full ((dl), (k), (d), NULL)
#define g_datalist_remove_data(dl, k) \
g_datalist_id_set_data ((dl), g_quark_try_string (k), NULL)
/* Location Associated Keyed Data
*/
GLIB_AVAILABLE_IN_ALL
void g_dataset_destroy (gconstpointer dataset_location);
GLIB_AVAILABLE_IN_ALL
gpointer g_dataset_id_get_data (gconstpointer dataset_location,
GQuark key_id);
GLIB_AVAILABLE_IN_ALL
gpointer g_datalist_get_data (GData **datalist,
const gchar *key);
GLIB_AVAILABLE_IN_ALL
void g_dataset_id_set_data_full (gconstpointer dataset_location,
GQuark key_id,
gpointer data,
GDestroyNotify destroy_func);
GLIB_AVAILABLE_IN_ALL
gpointer g_dataset_id_remove_no_notify (gconstpointer dataset_location,
GQuark key_id);
GLIB_AVAILABLE_IN_ALL
void g_dataset_foreach (gconstpointer dataset_location,
GDataForeachFunc func,
gpointer user_data);
#define g_dataset_id_set_data(l, k, d) \
g_dataset_id_set_data_full ((l), (k), (d), NULL)
#define g_dataset_id_remove_data(l, k) \
g_dataset_id_set_data ((l), (k), NULL)
#define g_dataset_get_data(l, k) \
(g_dataset_id_get_data ((l), g_quark_try_string (k)))
#define g_dataset_set_data_full(l, k, d, f) \
g_dataset_id_set_data_full ((l), g_quark_from_string (k), (d), (f))
#define g_dataset_remove_no_notify(l, k) \
g_dataset_id_remove_no_notify ((l), g_quark_try_string (k))
#define g_dataset_set_data(l, k, d) \
g_dataset_set_data_full ((l), (k), (d), NULL)
#define g_dataset_remove_data(l, k) \
g_dataset_id_set_data ((l), g_quark_try_string (k), NULL)
G_END_DECLS
#endif /* __G_DATASET_H__ */
pkg-config-0.29.1/glib/glib/gmessages-private.h 0000664 0001750 0001750 00000002112 12651243552 016204 0000000 0000000 /* gmain.h - the GLib Main loop
* Copyright (C) 1998-2000 Red Hat, 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; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __G_MESSAGES_PRIVATE_H__
#define __G_MESSAGES_PRIVATE_H__
#include
G_BEGIN_DECLS
G_GNUC_INTERNAL void
_g_log_set_exit_on_fatal (void);
G_GNUC_INTERNAL void
_g_log_abort (void) G_GNUC_NORETURN;
G_END_DECLS
#endif /* __G_MESSAGES_PRIVATE_H__ */
pkg-config-0.29.1/glib/glib/gdatasetprivate.h 0000664 0001750 0001750 00000003025 12275467762 015766 0000000 0000000 /* GLIB - Library of useful routines for C programming
* gdataset-private.h: Internal macros for accessing dataset values
* Copyright (C) 2005 Red Hat
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __G_DATASETPRIVATE_H__
#define __G_DATASETPRIVATE_H__
#include
G_BEGIN_DECLS
/* GET_FLAGS is implemented via atomic pointer access, to allow memory
* barriers to take effect without acquiring the global dataset mutex.
*/
#define G_DATALIST_GET_FLAGS(datalist) \
((gsize) g_atomic_pointer_get (datalist) & G_DATALIST_FLAGS_MASK)
G_END_DECLS
#endif /* __G_DATASETPRIVATE_H__ */
pkg-config-0.29.1/glib/glib/glib_trace.h 0000664 0001750 0001750 00000002436 12275467762 014677 0000000 0000000 /* GLIB - Library of useful routines for C programming
*
* Copyright (C) 2009,2010 Red Hat, Inc.
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson
*/
#ifndef __GLIBTRACE_H__
#define __GLIBTRACE_H__
#ifndef SIZEOF_CHAR
#error "config.h must be included prior to glib_trace.h"
#endif
#ifdef HAVE_DTRACE
/* include the generated probes header and put markers in code */
#include "glib_probes.h"
#define TRACE(probe) probe
#else
/* Wrap the probe to allow it to be removed when no systemtap available */
#define TRACE(probe)
#endif
#endif /* __GLIBTRACE_H__ */
pkg-config-0.29.1/glib/glib/gstring.c 0000664 0001750 0001750 00000071760 12651243552 014245 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
/*
* MT safe
*/
#include "config.h"
#ifdef HAVE_UNISTD_H
#include
#endif
#include
#include
#include
#include
#include
#include "gstring.h"
#include "gprintf.h"
/**
* SECTION:strings
* @title: Strings
* @short_description: text buffers which grow automatically
* as text is added
*
* A #GString is an object that handles the memory management of a C
* string for you. The emphasis of #GString is on text, typically
* UTF-8. Crucially, the "str" member of a #GString is guaranteed to
* have a trailing nul character, and it is therefore always safe to
* call functions such as strchr() or g_strdup() on it.
*
* However, a #GString can also hold arbitrary binary data, because it
* has a "len" member, which includes any possible embedded nul
* characters in the data. Conceptually then, #GString is like a
* #GByteArray with the addition of many convenience methods for text,
* and a guaranteed nul terminator.
*/
/**
* GString:
* @str: points to the character data. It may move as text is added.
* The @str field is null-terminated and so
* can be used as an ordinary C string.
* @len: contains the length of the string, not including the
* terminating nul byte.
* @allocated_len: the number of bytes that can be stored in the
* string before it needs to be reallocated. May be larger than @len.
*
* The GString struct contains the public fields of a GString.
*/
#define MY_MAXSIZE ((gsize)-1)
static inline gsize
nearest_power (gsize base, gsize num)
{
if (num > MY_MAXSIZE / 2)
{
return MY_MAXSIZE;
}
else
{
gsize n = base;
while (n < num)
n <<= 1;
return n;
}
}
static void
g_string_maybe_expand (GString *string,
gsize len)
{
if (string->len + len >= string->allocated_len)
{
string->allocated_len = nearest_power (1, string->len + len + 1);
string->str = g_realloc (string->str, string->allocated_len);
}
}
/**
* g_string_sized_new:
* @dfl_size: the default size of the space allocated to
* hold the string
*
* Creates a new #GString, with enough space for @dfl_size
* bytes. This is useful if you are going to add a lot of
* text to the string and don't want it to be reallocated
* too often.
*
* Returns: the new #GString
*/
GString *
g_string_sized_new (gsize dfl_size)
{
GString *string = g_slice_new (GString);
string->allocated_len = 0;
string->len = 0;
string->str = NULL;
g_string_maybe_expand (string, MAX (dfl_size, 2));
string->str[0] = 0;
return string;
}
/**
* g_string_new:
* @init: the initial text to copy into the string
*
* Creates a new #GString, initialized with the given string.
*
* Returns: the new #GString
*/
GString *
g_string_new (const gchar *init)
{
GString *string;
if (init == NULL || *init == '\0')
string = g_string_sized_new (2);
else
{
gint len;
len = strlen (init);
string = g_string_sized_new (len + 2);
g_string_append_len (string, init, len);
}
return string;
}
/**
* g_string_new_len:
* @init: initial contents of the string
* @len: length of @init to use
*
* Creates a new #GString with @len bytes of the @init buffer.
* Because a length is provided, @init need not be nul-terminated,
* and can contain embedded nul bytes.
*
* Since this function does not stop at nul bytes, it is the caller's
* responsibility to ensure that @init has at least @len addressable
* bytes.
*
* Returns: a new #GString
*/
GString *
g_string_new_len (const gchar *init,
gssize len)
{
GString *string;
if (len < 0)
return g_string_new (init);
else
{
string = g_string_sized_new (len);
if (init)
g_string_append_len (string, init, len);
return string;
}
}
/**
* g_string_free:
* @string: a #GString
* @free_segment: if %TRUE, the actual character data is freed as well
*
* Frees the memory allocated for the #GString.
* If @free_segment is %TRUE it also frees the character data. If
* it's %FALSE, the caller gains ownership of the buffer and must
* free it after use with g_free().
*
* Returns: the character data of @string
* (i.e. %NULL if @free_segment is %TRUE)
*/
gchar *
g_string_free (GString *string,
gboolean free_segment)
{
gchar *segment;
g_return_val_if_fail (string != NULL, NULL);
if (free_segment)
{
g_free (string->str);
segment = NULL;
}
else
segment = string->str;
g_slice_free (GString, string);
return segment;
}
/**
* g_string_free_to_bytes:
* @string: (transfer full): a #GString
*
* Transfers ownership of the contents of @string to a newly allocated
* #GBytes. The #GString structure itself is deallocated, and it is
* therefore invalid to use @string after invoking this function.
*
* Note that while #GString ensures that its buffer always has a
* trailing nul character (not reflected in its "len"), the returned
* #GBytes does not include this extra nul; i.e. it has length exactly
* equal to the "len" member.
*
* Returns: A newly allocated #GBytes containing contents of @string; @string itself is freed
* Since: 2.34
*/
GBytes*
g_string_free_to_bytes (GString *string)
{
gsize len;
gchar *buf;
g_return_val_if_fail (string != NULL, NULL);
len = string->len;
buf = g_string_free (string, FALSE);
return g_bytes_new_take (buf, len);
}
/**
* g_string_equal:
* @v: a #GString
* @v2: another #GString
*
* Compares two strings for equality, returning %TRUE if they are equal.
* For use with #GHashTable.
*
* Returns: %TRUE if the strings are the same length and contain the
* same bytes
*/
gboolean
g_string_equal (const GString *v,
const GString *v2)
{
gchar *p, *q;
GString *string1 = (GString *) v;
GString *string2 = (GString *) v2;
gsize i = string1->len;
if (i != string2->len)
return FALSE;
p = string1->str;
q = string2->str;
while (i)
{
if (*p != *q)
return FALSE;
p++;
q++;
i--;
}
return TRUE;
}
/**
* g_string_hash:
* @str: a string to hash
*
* Creates a hash code for @str; for use with #GHashTable.
*
* Returns: hash code for @str
*/
guint
g_string_hash (const GString *str)
{
const gchar *p = str->str;
gsize n = str->len;
guint h = 0;
/* 31 bit hash function */
while (n--)
{
h = (h << 5) - h + *p;
p++;
}
return h;
}
/**
* g_string_assign:
* @string: the destination #GString. Its current contents
* are destroyed.
* @rval: the string to copy into @string
*
* Copies the bytes from a string into a #GString,
* destroying any previous contents. It is rather like
* the standard strcpy() function, except that you do not
* have to worry about having enough space to copy the string.
*
* Returns: @string
*/
GString *
g_string_assign (GString *string,
const gchar *rval)
{
g_return_val_if_fail (string != NULL, NULL);
g_return_val_if_fail (rval != NULL, string);
/* Make sure assigning to itself doesn't corrupt the string. */
if (string->str != rval)
{
/* Assigning from substring should be ok, since
* g_string_truncate() does not reallocate.
*/
g_string_truncate (string, 0);
g_string_append (string, rval);
}
return string;
}
/**
* g_string_truncate:
* @string: a #GString
* @len: the new size of @string
*
* Cuts off the end of the GString, leaving the first @len bytes.
*
* Returns: @string
*/
GString *
g_string_truncate (GString *string,
gsize len)
{
g_return_val_if_fail (string != NULL, NULL);
string->len = MIN (len, string->len);
string->str[string->len] = 0;
return string;
}
/**
* g_string_set_size:
* @string: a #GString
* @len: the new length
*
* Sets the length of a #GString. If the length is less than
* the current length, the string will be truncated. If the
* length is greater than the current length, the contents
* of the newly added area are undefined. (However, as
* always, string->str[string->len] will be a nul byte.)
*
* Return value: @string
*/
GString *
g_string_set_size (GString *string,
gsize len)
{
g_return_val_if_fail (string != NULL, NULL);
if (len >= string->allocated_len)
g_string_maybe_expand (string, len - string->len);
string->len = len;
string->str[len] = 0;
return string;
}
/**
* g_string_insert_len:
* @string: a #GString
* @pos: position in @string where insertion should
* happen, or -1 for at the end
* @val: bytes to insert
* @len: number of bytes of @val to insert
*
* Inserts @len bytes of @val into @string at @pos.
* Because @len is provided, @val may contain embedded
* nuls and need not be nul-terminated. If @pos is -1,
* bytes are inserted at the end of the string.
*
* Since this function does not stop at nul bytes, it is
* the caller's responsibility to ensure that @val has at
* least @len addressable bytes.
*
* Returns: @string
*/
GString *
g_string_insert_len (GString *string,
gssize pos,
const gchar *val,
gssize len)
{
g_return_val_if_fail (string != NULL, NULL);
g_return_val_if_fail (len == 0 || val != NULL, string);
if (len == 0)
return string;
if (len < 0)
len = strlen (val);
if (pos < 0)
pos = string->len;
else
g_return_val_if_fail (pos <= string->len, string);
/* Check whether val represents a substring of string.
* This test probably violates chapter and verse of the C standards,
* since ">=" and "<=" are only valid when val really is a substring.
* In practice, it will work on modern archs.
*/
if (val >= string->str && val <= string->str + string->len)
{
gsize offset = val - string->str;
gsize precount = 0;
g_string_maybe_expand (string, len);
val = string->str + offset;
/* At this point, val is valid again. */
/* Open up space where we are going to insert. */
if (pos < string->len)
g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
/* Move the source part before the gap, if any. */
if (offset < pos)
{
precount = MIN (len, pos - offset);
memcpy (string->str + pos, val, precount);
}
/* Move the source part after the gap, if any. */
if (len > precount)
memcpy (string->str + pos + precount,
val + /* Already moved: */ precount + /* Space opened up: */ len,
len - precount);
}
else
{
g_string_maybe_expand (string, len);
/* If we aren't appending at the end, move a hunk
* of the old string to the end, opening up space
*/
if (pos < string->len)
g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
/* insert the new string */
if (len == 1)
string->str[pos] = *val;
else
memcpy (string->str + pos, val, len);
}
string->len += len;
string->str[string->len] = 0;
return string;
}
#define SUB_DELIM_CHARS "!$&'()*+,;="
static gboolean
is_valid (char c,
const char *reserved_chars_allowed)
{
if (g_ascii_isalnum (c) ||
c == '-' ||
c == '.' ||
c == '_' ||
c == '~')
return TRUE;
if (reserved_chars_allowed &&
strchr (reserved_chars_allowed, c) != NULL)
return TRUE;
return FALSE;
}
static gboolean
gunichar_ok (gunichar c)
{
return
(c != (gunichar) -2) &&
(c != (gunichar) -1);
}
/**
* g_string_append_uri_escaped:
* @string: a #GString
* @unescaped: a string
* @reserved_chars_allowed: a string of reserved characters allowed
* to be used, or %NULL
* @allow_utf8: set %TRUE if the escaped string may include UTF8 characters
*
* Appends @unescaped to @string, escaped any characters that
* are reserved in URIs using URI-style escape sequences.
*
* Returns: @string
*
* Since: 2.16
*/
GString *
g_string_append_uri_escaped (GString *string,
const gchar *unescaped,
const gchar *reserved_chars_allowed,
gboolean allow_utf8)
{
unsigned char c;
const gchar *end;
static const gchar hex[16] = "0123456789ABCDEF";
g_return_val_if_fail (string != NULL, NULL);
g_return_val_if_fail (unescaped != NULL, NULL);
end = unescaped + strlen (unescaped);
while ((c = *unescaped) != 0)
{
if (c >= 0x80 && allow_utf8 &&
gunichar_ok (g_utf8_get_char_validated (unescaped, end - unescaped)))
{
int len = g_utf8_skip [c];
g_string_append_len (string, unescaped, len);
unescaped += len;
}
else if (is_valid (c, reserved_chars_allowed))
{
g_string_append_c (string, c);
unescaped++;
}
else
{
g_string_append_c (string, '%');
g_string_append_c (string, hex[((guchar)c) >> 4]);
g_string_append_c (string, hex[((guchar)c) & 0xf]);
unescaped++;
}
}
return string;
}
/**
* g_string_append:
* @string: a #GString
* @val: the string to append onto the end of @string
*
* Adds a string onto the end of a #GString, expanding
* it if necessary.
*
* Returns: @string
*/
GString *
g_string_append (GString *string,
const gchar *val)
{
g_return_val_if_fail (string != NULL, NULL);
g_return_val_if_fail (val != NULL, string);
return g_string_insert_len (string, -1, val, -1);
}
/**
* g_string_append_len:
* @string: a #GString
* @val: bytes to append
* @len: number of bytes of @val to use
*
* Appends @len bytes of @val to @string. Because @len is
* provided, @val may contain embedded nuls and need not
* be nul-terminated.
*
* Since this function does not stop at nul bytes, it is
* the caller's responsibility to ensure that @val has at
* least @len addressable bytes.
*
* Returns: @string
*/
GString *
g_string_append_len (GString *string,
const gchar *val,
gssize len)
{
g_return_val_if_fail (string != NULL, NULL);
g_return_val_if_fail (len == 0 || val != NULL, string);
return g_string_insert_len (string, -1, val, len);
}
/**
* g_string_append_c:
* @string: a #GString
* @c: the byte to append onto the end of @string
*
* Adds a byte onto the end of a #GString, expanding
* it if necessary.
*
* Returns: @string
*/
#undef g_string_append_c
GString *
g_string_append_c (GString *string,
gchar c)
{
g_return_val_if_fail (string != NULL, NULL);
return g_string_insert_c (string, -1, c);
}
/**
* g_string_append_unichar:
* @string: a #GString
* @wc: a Unicode character
*
* Converts a Unicode character into UTF-8, and appends it
* to the string.
*
* Return value: @string
*/
GString *
g_string_append_unichar (GString *string,
gunichar wc)
{
g_return_val_if_fail (string != NULL, NULL);
return g_string_insert_unichar (string, -1, wc);
}
/**
* g_string_prepend:
* @string: a #GString
* @val: the string to prepend on the start of @string
*
* Adds a string on to the start of a #GString,
* expanding it if necessary.
*
* Returns: @string
*/
GString *
g_string_prepend (GString *string,
const gchar *val)
{
g_return_val_if_fail (string != NULL, NULL);
g_return_val_if_fail (val != NULL, string);
return g_string_insert_len (string, 0, val, -1);
}
/**
* g_string_prepend_len:
* @string: a #GString
* @val: bytes to prepend
* @len: number of bytes in @val to prepend
*
* Prepends @len bytes of @val to @string.
* Because @len is provided, @val may contain
* embedded nuls and need not be nul-terminated.
*
* Since this function does not stop at nul bytes,
* it is the caller's responsibility to ensure that
* @val has at least @len addressable bytes.
*
* Returns: @string
*/
GString *
g_string_prepend_len (GString *string,
const gchar *val,
gssize len)
{
g_return_val_if_fail (string != NULL, NULL);
g_return_val_if_fail (val != NULL, string);
return g_string_insert_len (string, 0, val, len);
}
/**
* g_string_prepend_c:
* @string: a #GString
* @c: the byte to prepend on the start of the #GString
*
* Adds a byte onto the start of a #GString,
* expanding it if necessary.
*
* Returns: @string
*/
GString *
g_string_prepend_c (GString *string,
gchar c)
{
g_return_val_if_fail (string != NULL, NULL);
return g_string_insert_c (string, 0, c);
}
/**
* g_string_prepend_unichar:
* @string: a #GString
* @wc: a Unicode character
*
* Converts a Unicode character into UTF-8, and prepends it
* to the string.
*
* Return value: @string
*/
GString *
g_string_prepend_unichar (GString *string,
gunichar wc)
{
g_return_val_if_fail (string != NULL, NULL);
return g_string_insert_unichar (string, 0, wc);
}
/**
* g_string_insert:
* @string: a #GString
* @pos: the position to insert the copy of the string
* @val: the string to insert
*
* Inserts a copy of a string into a #GString,
* expanding it if necessary.
*
* Returns: @string
*/
GString *
g_string_insert (GString *string,
gssize pos,
const gchar *val)
{
g_return_val_if_fail (string != NULL, NULL);
g_return_val_if_fail (val != NULL, string);
if (pos >= 0)
g_return_val_if_fail (pos <= string->len, string);
return g_string_insert_len (string, pos, val, -1);
}
/**
* g_string_insert_c:
* @string: a #GString
* @pos: the position to insert the byte
* @c: the byte to insert
*
* Inserts a byte into a #GString, expanding it if necessary.
*
* Returns: @string
*/
GString *
g_string_insert_c (GString *string,
gssize pos,
gchar c)
{
g_return_val_if_fail (string != NULL, NULL);
g_string_maybe_expand (string, 1);
if (pos < 0)
pos = string->len;
else
g_return_val_if_fail (pos <= string->len, string);
/* If not just an append, move the old stuff */
if (pos < string->len)
g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
string->str[pos] = c;
string->len += 1;
string->str[string->len] = 0;
return string;
}
/**
* g_string_insert_unichar:
* @string: a #GString
* @pos: the position at which to insert character, or -1
* to append at the end of the string
* @wc: a Unicode character
*
* Converts a Unicode character into UTF-8, and insert it
* into the string at the given position.
*
* Return value: @string
*/
GString *
g_string_insert_unichar (GString *string,
gssize pos,
gunichar wc)
{
gint charlen, first, i;
gchar *dest;
g_return_val_if_fail (string != NULL, NULL);
/* Code copied from g_unichar_to_utf() */
if (wc < 0x80)
{
first = 0;
charlen = 1;
}
else if (wc < 0x800)
{
first = 0xc0;
charlen = 2;
}
else if (wc < 0x10000)
{
first = 0xe0;
charlen = 3;
}
else if (wc < 0x200000)
{
first = 0xf0;
charlen = 4;
}
else if (wc < 0x4000000)
{
first = 0xf8;
charlen = 5;
}
else
{
first = 0xfc;
charlen = 6;
}
/* End of copied code */
g_string_maybe_expand (string, charlen);
if (pos < 0)
pos = string->len;
else
g_return_val_if_fail (pos <= string->len, string);
/* If not just an append, move the old stuff */
if (pos < string->len)
g_memmove (string->str + pos + charlen, string->str + pos, string->len - pos);
dest = string->str + pos;
/* Code copied from g_unichar_to_utf() */
for (i = charlen - 1; i > 0; --i)
{
dest[i] = (wc & 0x3f) | 0x80;
wc >>= 6;
}
dest[0] = wc | first;
/* End of copied code */
string->len += charlen;
string->str[string->len] = 0;
return string;
}
/**
* g_string_overwrite:
* @string: a #GString
* @pos: the position at which to start overwriting
* @val: the string that will overwrite the @string starting at @pos
*
* Overwrites part of a string, lengthening it if necessary.
*
* Return value: @string
*
* Since: 2.14
*/
GString *
g_string_overwrite (GString *string,
gsize pos,
const gchar *val)
{
g_return_val_if_fail (val != NULL, string);
return g_string_overwrite_len (string, pos, val, strlen (val));
}
/**
* g_string_overwrite_len:
* @string: a #GString
* @pos: the position at which to start overwriting
* @val: the string that will overwrite the @string starting at @pos
* @len: the number of bytes to write from @val
*
* Overwrites part of a string, lengthening it if necessary.
* This function will work with embedded nuls.
*
* Return value: @string
*
* Since: 2.14
*/
GString *
g_string_overwrite_len (GString *string,
gsize pos,
const gchar *val,
gssize len)
{
gsize end;
g_return_val_if_fail (string != NULL, NULL);
if (!len)
return string;
g_return_val_if_fail (val != NULL, string);
g_return_val_if_fail (pos <= string->len, string);
if (len < 0)
len = strlen (val);
end = pos + len;
if (end > string->len)
g_string_maybe_expand (string, end - string->len);
memcpy (string->str + pos, val, len);
if (end > string->len)
{
string->str[end] = '\0';
string->len = end;
}
return string;
}
/**
* g_string_erase:
* @string: a #GString
* @pos: the position of the content to remove
* @len: the number of bytes to remove, or -1 to remove all
* following bytes
*
* Removes @len bytes from a #GString, starting at position @pos.
* The rest of the #GString is shifted down to fill the gap.
*
* Returns: @string
*/
GString *
g_string_erase (GString *string,
gssize pos,
gssize len)
{
g_return_val_if_fail (string != NULL, NULL);
g_return_val_if_fail (pos >= 0, string);
g_return_val_if_fail (pos <= string->len, string);
if (len < 0)
len = string->len - pos;
else
{
g_return_val_if_fail (pos + len <= string->len, string);
if (pos + len < string->len)
g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
}
string->len -= len;
string->str[string->len] = 0;
return string;
}
/**
* g_string_ascii_down:
* @string: a GString
*
* Converts all uppercase ASCII letters to lowercase ASCII letters.
*
* Return value: passed-in @string pointer, with all the
* uppercase characters converted to lowercase in place,
* with semantics that exactly match g_ascii_tolower().
*/
GString *
g_string_ascii_down (GString *string)
{
gchar *s;
gint n;
g_return_val_if_fail (string != NULL, NULL);
n = string->len;
s = string->str;
while (n)
{
*s = g_ascii_tolower (*s);
s++;
n--;
}
return string;
}
/**
* g_string_ascii_up:
* @string: a GString
*
* Converts all lowercase ASCII letters to uppercase ASCII letters.
*
* Return value: passed-in @string pointer, with all the
* lowercase characters converted to uppercase in place,
* with semantics that exactly match g_ascii_toupper().
*/
GString *
g_string_ascii_up (GString *string)
{
gchar *s;
gint n;
g_return_val_if_fail (string != NULL, NULL);
n = string->len;
s = string->str;
while (n)
{
*s = g_ascii_toupper (*s);
s++;
n--;
}
return string;
}
/**
* g_string_down:
* @string: a #GString
*
* Converts a #GString to lowercase.
*
* Returns: the #GString
*
* Deprecated:2.2: This function uses the locale-specific
* tolower() function, which is almost never the right thing.
* Use g_string_ascii_down() or g_utf8_strdown() instead.
*/
GString *
g_string_down (GString *string)
{
guchar *s;
glong n;
g_return_val_if_fail (string != NULL, NULL);
n = string->len;
s = (guchar *) string->str;
while (n)
{
if (isupper (*s))
*s = tolower (*s);
s++;
n--;
}
return string;
}
/**
* g_string_up:
* @string: a #GString
*
* Converts a #GString to uppercase.
*
* Return value: @string
*
* Deprecated:2.2: This function uses the locale-specific
* toupper() function, which is almost never the right thing.
* Use g_string_ascii_up() or g_utf8_strup() instead.
*/
GString *
g_string_up (GString *string)
{
guchar *s;
glong n;
g_return_val_if_fail (string != NULL, NULL);
n = string->len;
s = (guchar *) string->str;
while (n)
{
if (islower (*s))
*s = toupper (*s);
s++;
n--;
}
return string;
}
/**
* g_string_append_vprintf:
* @string: a #GString
* @format: the string format. See the printf() documentation
* @args: the list of arguments to insert in the output
*
* Appends a formatted string onto the end of a #GString.
* This function is similar to g_string_append_printf()
* except that the arguments to the format string are passed
* as a va_list.
*
* Since: 2.14
*/
void
g_string_append_vprintf (GString *string,
const gchar *format,
va_list args)
{
gchar *buf;
gint len;
g_return_if_fail (string != NULL);
g_return_if_fail (format != NULL);
len = g_vasprintf (&buf, format, args);
if (len >= 0)
{
g_string_maybe_expand (string, len);
memcpy (string->str + string->len, buf, len + 1);
string->len += len;
g_free (buf);
}
}
/**
* g_string_vprintf:
* @string: a #GString
* @format: the string format. See the printf() documentation
* @args: the parameters to insert into the format string
*
* Writes a formatted string into a #GString.
* This function is similar to g_string_printf() except that
* the arguments to the format string are passed as a va_list.
*
* Since: 2.14
*/
void
g_string_vprintf (GString *string,
const gchar *format,
va_list args)
{
g_string_truncate (string, 0);
g_string_append_vprintf (string, format, args);
}
/**
* g_string_sprintf:
* @string: a #GString
* @format: the string format. See the sprintf() documentation
* @...: the parameters to insert into the format string
*
* Writes a formatted string into a #GString.
* This is similar to the standard sprintf() function,
* except that the #GString buffer automatically expands
* to contain the results. The previous contents of the
* #GString are destroyed.
*
* Deprecated: This function has been renamed to g_string_printf().
*/
/**
* g_string_printf:
* @string: a #GString
* @format: the string format. See the printf() documentation
* @...: the parameters to insert into the format string
*
* Writes a formatted string into a #GString.
* This is similar to the standard sprintf() function,
* except that the #GString buffer automatically expands
* to contain the results. The previous contents of the
* #GString are destroyed.
*/
void
g_string_printf (GString *string,
const gchar *format,
...)
{
va_list args;
g_string_truncate (string, 0);
va_start (args, format);
g_string_append_vprintf (string, format, args);
va_end (args);
}
/**
* g_string_sprintfa:
* @string: a #GString
* @format: the string format. See the sprintf() documentation
* @...: the parameters to insert into the format string
*
* Appends a formatted string onto the end of a #GString.
* This function is similar to g_string_sprintf() except that
* the text is appended to the #GString.
*
* Deprecated: This function has been renamed to g_string_append_printf()
*/
/**
* g_string_append_printf:
* @string: a #GString
* @format: the string format. See the printf() documentation
* @...: the parameters to insert into the format string
*
* Appends a formatted string onto the end of a #GString.
* This function is similar to g_string_printf() except
* that the text is appended to the #GString.
*/
void
g_string_append_printf (GString *string,
const gchar *format,
...)
{
va_list args;
va_start (args, format);
g_string_append_vprintf (string, format, args);
va_end (args);
}
pkg-config-0.29.1/glib/glib/gvariant-serialiser.c 0000664 0001750 0001750 00000144750 12651243552 016543 0000000 0000000 /*
* Copyright © 2007, 2008 Ryan Lortie
* Copyright © 2010 Codethink Limited
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ryan Lortie
*/
/* Prologue {{{1 */
#include "config.h"
#include "gvariant-serialiser.h"
#include
#include
#include
#include
/* GVariantSerialiser
*
* After this prologue section, this file has roughly 2 parts.
*
* The first part is split up into sections according to various
* container types. Maybe, Array, Tuple, Variant. The Maybe and Array
* sections are subdivided for element types being fixed or
* variable-sized types.
*
* Each section documents the format of that particular type of
* container and implements 5 functions for dealing with it:
*
* n_children:
* - determines (according to serialised data) how many child values
* are inside a particular container value.
*
* get_child:
* - gets the type of and the serialised data corresponding to a
* given child value within the container value.
*
* needed_size:
* - determines how much space would be required to serialise a
* container of this type, containing the given children so that
* buffers can be preallocated before serialising.
*
* serialise:
* - write the serialised data for a container of this type,
* containing the given children, to a buffer.
*
* is_normal:
* - check the given data to ensure that it is in normal form. For a
* given set of child values, there is exactly one normal form for
* the serialised data of a container. Other forms are possible
* while maintaining the same children (for example, by inserting
* something other than zero bytes as padding) but only one form is
* the normal form.
*
* The second part contains the main entry point for each of the above 5
* functions and logic to dispatch it to the handler for the appropriate
* container type code.
*
* The second part also contains a routine to byteswap serialised
* values. This code makes use of the n_children() and get_child()
* functions above to do its work so no extra support is needed on a
* per-container-type basis.
*
* There is also additional code for checking for normal form. All
* numeric types are always in normal form since the full range of
* values is permitted (eg: 0 to 255 is a valid byte). Special checks
* need to be performed for booleans (only 0 or 1 allowed), strings
* (properly nul-terminated) and object paths and signature strings
* (meeting the D-Bus specification requirements).
*/
/* < private >
* GVariantSerialised:
* @type_info: the #GVariantTypeInfo of this value
* @data: (allow-none): the serialised data of this value, or %NULL
* @size: the size of this value
*
* A structure representing a GVariant in serialised form. This
* structure is used with #GVariantSerialisedFiller functions and as the
* primary interface to the serialiser. See #GVariantSerialisedFiller
* for a description of its use there.
*
* When used with the serialiser API functions, the following invariants
* apply to all #GVariantTypeSerialised structures passed to and
* returned from the serialiser.
*
* @type_info must be non-%NULL.
*
* @data must be properly aligned for the type described by @type_info.
*
* If @type_info describes a fixed-sized type then @size must always be
* equal to the fixed size of that type.
*
* For fixed-sized types (and only fixed-sized types), @data may be
* %NULL even if @size is non-zero. This happens when a framing error
* occurs while attempting to extract a fixed-sized value out of a
* variable-sized container. There is no data to return for the
* fixed-sized type, yet @size must be non-zero. The effect of this
* combination should be as if @data were a pointer to an
* appropriately-sized zero-filled region.
*/
/* < private >
* g_variant_serialised_check:
* @serialised: a #GVariantSerialised struct
*
* Checks @serialised for validity according to the invariants described
* above.
*/
static void
g_variant_serialised_check (GVariantSerialised serialised)
{
gsize fixed_size;
guint alignment;
g_assert (serialised.type_info != NULL);
g_variant_type_info_query (serialised.type_info, &alignment, &fixed_size);
if (fixed_size)
g_assert_cmpint (serialised.size, ==, fixed_size);
else
g_assert (serialised.size == 0 || serialised.data != NULL);
/* Depending on the native alignment requirements of the machine, the
* compiler will insert either 3 or 7 padding bytes after the char.
* This will result in the sizeof() the struct being 12 or 16.
* Subtract 9 to get 3 or 7 which is a nice bitmask to apply to get
* the alignment bits that we "care about" being zero: in the
* 4-aligned case, we care about 2 bits, and in the 8-aligned case, we
* care about 3 bits.
*/
alignment &= sizeof (struct {
char a;
union {
guint64 x;
void *y;
gdouble z;
} b;
}
) - 9;
/* Some OSes (FreeBSD is a known example) have a malloc() that returns
* unaligned memory if you request small sizes. 'malloc (1);', for
* example, has been seen to return pointers aligned to 6 mod 16.
*
* Check if this is a small allocation and return without enforcing
* the alignment assertion if this is the case.
*/
if (serialised.size <= alignment)
return;
g_assert_cmpint (alignment & (gsize) serialised.data, ==, 0);
}
/* < private >
* GVariantSerialisedFiller:
* @serialised: a #GVariantSerialised instance to fill
* @data: data from the children array
*
* This function is called back from g_variant_serialiser_needed_size()
* and g_variant_serialiser_serialise(). It fills in missing details
* from a partially-complete #GVariantSerialised.
*
* The @data parameter passed back to the function is one of the items
* that was passed to the serialiser in the @children array. It
* represents a single child item of the container that is being
* serialised. The information filled in to @serialised is the
* information for this child.
*
* If the @type_info field of @serialised is %NULL then the callback
* function must set it to the type information corresponding to the
* type of the child. No reference should be added. If it is non-%NULL
* then the callback should assert that it is equal to the actual type
* of the child.
*
* If the @size field is zero then the callback must fill it in with the
* required amount of space to store the serialised form of the child.
* If it is non-zero then the callback should assert that it is equal to
* the needed size of the child.
*
* If @data is non-%NULL then it points to a space that is properly
* aligned for and large enough to store the serialised data of the
* child. The callback must store the serialised form of the child at
* @data.
*
* If the child value is another container then the callback will likely
* recurse back into the serialiser by calling
* g_variant_serialiser_needed_size() to determine @size and
* g_variant_serialiser_serialise() to write to @data.
*/
/* PART 1: Container types {{{1
*
* This section contains the serialiser implementation functions for
* each container type.
*/
/* Maybe {{{2
*
* Maybe types are handled depending on if the element type of the maybe
* type is a fixed-sized or variable-sized type. Although all maybe
* types themselves are variable-sized types, herein, a maybe value with
* a fixed-sized element type is called a "fixed-sized maybe" for
* convenience and a maybe value with a variable-sized element type is
* called a "variable-sized maybe".
*/
/* Fixed-sized Maybe {{{3
*
* The size of a maybe value with a fixed-sized element type is either 0
* or equal to the fixed size of its element type. The case where the
* size of the maybe value is zero corresponds to the "Nothing" case and
* the case where the size of the maybe value is equal to the fixed size
* of the element type corresponds to the "Just" case; in that case, the
* serialised data of the child value forms the entire serialised data
* of the maybe value.
*
* In the event that a fixed-sized maybe value is presented with a size
* that is not equal to the fixed size of the element type then the
* value must be taken to be "Nothing".
*/
static gsize
gvs_fixed_sized_maybe_n_children (GVariantSerialised value)
{
gsize element_fixed_size;
g_variant_type_info_query_element (value.type_info, NULL,
&element_fixed_size);
return (element_fixed_size == value.size) ? 1 : 0;
}
static GVariantSerialised
gvs_fixed_sized_maybe_get_child (GVariantSerialised value,
gsize index_)
{
/* the child has the same bounds as the
* container, so just update the type.
*/
value.type_info = g_variant_type_info_element (value.type_info);
g_variant_type_info_ref (value.type_info);
return value;
}
static gsize
gvs_fixed_sized_maybe_needed_size (GVariantTypeInfo *type_info,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
if (n_children)
{
gsize element_fixed_size;
g_variant_type_info_query_element (type_info, NULL,
&element_fixed_size);
return element_fixed_size;
}
else
return 0;
}
static void
gvs_fixed_sized_maybe_serialise (GVariantSerialised value,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
if (n_children)
{
GVariantSerialised child = { NULL, value.data, value.size };
gvs_filler (&child, children[0]);
}
}
static gboolean
gvs_fixed_sized_maybe_is_normal (GVariantSerialised value)
{
if (value.size > 0)
{
gsize element_fixed_size;
g_variant_type_info_query_element (value.type_info,
NULL, &element_fixed_size);
if (value.size != element_fixed_size)
return FALSE;
/* proper element size: "Just". recurse to the child. */
value.type_info = g_variant_type_info_element (value.type_info);
return g_variant_serialised_is_normal (value);
}
/* size of 0: "Nothing" */
return TRUE;
}
/* Variable-sized Maybe
*
* The size of a maybe value with a variable-sized element type is
* either 0 or strictly greater than 0. The case where the size of the
* maybe value is zero corresponds to the "Nothing" case and the case
* where the size of the maybe value is greater than zero corresponds to
* the "Just" case; in that case, the serialised data of the child value
* forms the first part of the serialised data of the maybe value and is
* followed by a single zero byte. This zero byte is always appended,
* regardless of any zero bytes that may already be at the end of the
* serialised ata of the child value.
*/
static gsize
gvs_variable_sized_maybe_n_children (GVariantSerialised value)
{
return (value.size > 0) ? 1 : 0;
}
static GVariantSerialised
gvs_variable_sized_maybe_get_child (GVariantSerialised value,
gsize index_)
{
/* remove the padding byte and update the type. */
value.type_info = g_variant_type_info_element (value.type_info);
g_variant_type_info_ref (value.type_info);
value.size--;
/* if it's zero-sized then it may as well be NULL */
if (value.size == 0)
value.data = NULL;
return value;
}
static gsize
gvs_variable_sized_maybe_needed_size (GVariantTypeInfo *type_info,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
if (n_children)
{
GVariantSerialised child = { 0, };
gvs_filler (&child, children[0]);
return child.size + 1;
}
else
return 0;
}
static void
gvs_variable_sized_maybe_serialise (GVariantSerialised value,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
if (n_children)
{
GVariantSerialised child = { NULL, value.data, value.size - 1 };
/* write the data for the child. */
gvs_filler (&child, children[0]);
value.data[child.size] = '\0';
}
}
static gboolean
gvs_variable_sized_maybe_is_normal (GVariantSerialised value)
{
if (value.size == 0)
return TRUE;
if (value.data[value.size - 1] != '\0')
return FALSE;
value.type_info = g_variant_type_info_element (value.type_info);
value.size--;
return g_variant_serialised_is_normal (value);
}
/* Arrays {{{2
*
* Just as with maybe types, array types are handled depending on if the
* element type of the array type is a fixed-sized or variable-sized
* type. Similar to maybe types, for convenience, an array value with a
* fixed-sized element type is called a "fixed-sized array" and an array
* value with a variable-sized element type is called a "variable sized
* array".
*/
/* Fixed-sized Array {{{3
*
* For fixed sized arrays, the serialised data is simply a concatenation
* of the serialised data of each element, in order. Since fixed-sized
* values always have a fixed size that is a multiple of their alignment
* requirement no extra padding is required.
*
* In the event that a fixed-sized array is presented with a size that
* is not an integer multiple of the element size then the value of the
* array must be taken as being empty.
*/
static gsize
gvs_fixed_sized_array_n_children (GVariantSerialised value)
{
gsize element_fixed_size;
g_variant_type_info_query_element (value.type_info, NULL,
&element_fixed_size);
if (value.size % element_fixed_size == 0)
return value.size / element_fixed_size;
return 0;
}
static GVariantSerialised
gvs_fixed_sized_array_get_child (GVariantSerialised value,
gsize index_)
{
GVariantSerialised child = { 0, };
child.type_info = g_variant_type_info_element (value.type_info);
g_variant_type_info_query (child.type_info, NULL, &child.size);
child.data = value.data + (child.size * index_);
g_variant_type_info_ref (child.type_info);
return child;
}
static gsize
gvs_fixed_sized_array_needed_size (GVariantTypeInfo *type_info,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
gsize element_fixed_size;
g_variant_type_info_query_element (type_info, NULL, &element_fixed_size);
return element_fixed_size * n_children;
}
static void
gvs_fixed_sized_array_serialise (GVariantSerialised value,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
GVariantSerialised child = { 0, };
gsize i;
child.type_info = g_variant_type_info_element (value.type_info);
g_variant_type_info_query (child.type_info, NULL, &child.size);
child.data = value.data;
for (i = 0; i < n_children; i++)
{
gvs_filler (&child, children[i]);
child.data += child.size;
}
}
static gboolean
gvs_fixed_sized_array_is_normal (GVariantSerialised value)
{
GVariantSerialised child = { 0, };
child.type_info = g_variant_type_info_element (value.type_info);
g_variant_type_info_query (child.type_info, NULL, &child.size);
if (value.size % child.size != 0)
return FALSE;
for (child.data = value.data;
child.data < value.data + value.size;
child.data += child.size)
{
if (!g_variant_serialised_is_normal (child))
return FALSE;
}
return TRUE;
}
/* Variable-sized Array {{{3
*
* Variable sized arrays, containing variable-sized elements, must be
* able to determine the boundaries between the elements. The items
* cannot simply be concatenated. Additionally, we are faced with the
* fact that non-fixed-sized values do not necessarily have a size that
* is a multiple of their alignment requirement, so we may need to
* insert zero-filled padding.
*
* While it is possible to find the start of an item by starting from
* the end of the item before it and padding for alignment, it is not
* generally possible to do the reverse operation. For this reason, we
* record the end point of each element in the array.
*
* GVariant works in terms of "offsets". An offset is a pointer to a
* boundary between two bytes. In 4 bytes of serialised data, there
* would be 5 possible offsets: one at the start ('0'), one between each
* pair of adjacent bytes ('1', '2', '3') and one at the end ('4').
*
* The numeric value of an offset is an unsigned integer given relative
* to the start of the serialised data of the array. Offsets are always
* stored in little endian byte order and are always only as big as they
* need to be. For example, in 255 bytes of serialised data, there are
* 256 offsets. All possibilities can be stored in an 8 bit unsigned
* integer. In 256 bytes of serialised data, however, there are 257
* possible offsets so 16 bit integers must be used. The size of an
* offset is always a power of 2.
*
* The offsets are stored at the end of the serialised data of the
* array. They are simply concatenated on without any particular
* alignment. The size of the offsets is included in the size of the
* serialised data for purposes of determining the size of the offsets.
* This presents a possibly ambiguity; in certain cases, a particular
* value of array could have two different serialised forms.
*
* Imagine an array containing a single string of 253 bytes in length
* (so, 254 bytes including the nul terminator). Now the offset must be
* written. If an 8 bit offset is written, it will bring the size of
* the array's serialised data to 255 -- which means that the use of an
* 8 bit offset was valid. If a 16 bit offset is used then the total
* size of the array will be 256 -- which means that the use of a 16 bit
* offset was valid. Although both of these will be accepted by the
* deserialiser, only the smaller of the two is considered to be in
* normal form and that is the one that the serialiser must produce.
*/
static inline gsize
gvs_read_unaligned_le (guchar *bytes,
guint size)
{
union
{
guchar bytes[GLIB_SIZEOF_SIZE_T];
gsize integer;
} tmpvalue;
tmpvalue.integer = 0;
memcpy (&tmpvalue.bytes, bytes, size);
return GSIZE_FROM_LE (tmpvalue.integer);
}
static inline void
gvs_write_unaligned_le (guchar *bytes,
gsize value,
guint size)
{
union
{
guchar bytes[GLIB_SIZEOF_SIZE_T];
gsize integer;
} tmpvalue;
tmpvalue.integer = GSIZE_TO_LE (value);
memcpy (bytes, &tmpvalue.bytes, size);
}
static guint
gvs_get_offset_size (gsize size)
{
if (size > G_MAXUINT32)
return 8;
else if (size > G_MAXUINT16)
return 4;
else if (size > G_MAXUINT8)
return 2;
else if (size > 0)
return 1;
return 0;
}
static gsize
gvs_calculate_total_size (gsize body_size,
gsize offsets)
{
if (body_size + 1 * offsets <= G_MAXUINT8)
return body_size + 1 * offsets;
if (body_size + 2 * offsets <= G_MAXUINT16)
return body_size + 2 * offsets;
if (body_size + 4 * offsets <= G_MAXUINT32)
return body_size + 4 * offsets;
return body_size + 8 * offsets;
}
static gsize
gvs_variable_sized_array_n_children (GVariantSerialised value)
{
gsize offsets_array_size;
gsize offset_size;
gsize last_end;
if (value.size == 0)
return 0;
offset_size = gvs_get_offset_size (value.size);
last_end = gvs_read_unaligned_le (value.data + value.size -
offset_size, offset_size);
if (last_end > value.size)
return 0;
offsets_array_size = value.size - last_end;
if (offsets_array_size % offset_size)
return 0;
return offsets_array_size / offset_size;
}
static GVariantSerialised
gvs_variable_sized_array_get_child (GVariantSerialised value,
gsize index_)
{
GVariantSerialised child = { 0, };
gsize offset_size;
gsize last_end;
gsize start;
gsize end;
child.type_info = g_variant_type_info_element (value.type_info);
g_variant_type_info_ref (child.type_info);
offset_size = gvs_get_offset_size (value.size);
last_end = gvs_read_unaligned_le (value.data + value.size -
offset_size, offset_size);
if (index_ > 0)
{
guint alignment;
start = gvs_read_unaligned_le (value.data + last_end +
(offset_size * (index_ - 1)),
offset_size);
g_variant_type_info_query (child.type_info, &alignment, NULL);
start += (-start) & alignment;
}
else
start = 0;
end = gvs_read_unaligned_le (value.data + last_end +
(offset_size * index_),
offset_size);
if (start < end && end <= value.size)
{
child.data = value.data + start;
child.size = end - start;
}
return child;
}
static gsize
gvs_variable_sized_array_needed_size (GVariantTypeInfo *type_info,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
guint alignment;
gsize offset;
gsize i;
g_variant_type_info_query (type_info, &alignment, NULL);
offset = 0;
for (i = 0; i < n_children; i++)
{
GVariantSerialised child = { 0, };
offset += (-offset) & alignment;
gvs_filler (&child, children[i]);
offset += child.size;
}
return gvs_calculate_total_size (offset, n_children);
}
static void
gvs_variable_sized_array_serialise (GVariantSerialised value,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
guchar *offset_ptr;
gsize offset_size;
guint alignment;
gsize offset;
gsize i;
g_variant_type_info_query (value.type_info, &alignment, NULL);
offset_size = gvs_get_offset_size (value.size);
offset = 0;
offset_ptr = value.data + value.size - offset_size * n_children;
for (i = 0; i < n_children; i++)
{
GVariantSerialised child = { 0, };
while (offset & alignment)
value.data[offset++] = '\0';
child.data = value.data + offset;
gvs_filler (&child, children[i]);
offset += child.size;
gvs_write_unaligned_le (offset_ptr, offset, offset_size);
offset_ptr += offset_size;
}
}
static gboolean
gvs_variable_sized_array_is_normal (GVariantSerialised value)
{
GVariantSerialised child = { 0, };
gsize offsets_array_size;
guchar *offsets_array;
guint offset_size;
guint alignment;
gsize last_end;
gsize length;
gsize offset;
gsize i;
if (value.size == 0)
return TRUE;
offset_size = gvs_get_offset_size (value.size);
last_end = gvs_read_unaligned_le (value.data + value.size -
offset_size, offset_size);
if (last_end > value.size)
return FALSE;
offsets_array_size = value.size - last_end;
if (offsets_array_size % offset_size)
return FALSE;
offsets_array = value.data + value.size - offsets_array_size;
length = offsets_array_size / offset_size;
if (length == 0)
return FALSE;
child.type_info = g_variant_type_info_element (value.type_info);
g_variant_type_info_query (child.type_info, &alignment, NULL);
offset = 0;
for (i = 0; i < length; i++)
{
gsize this_end;
this_end = gvs_read_unaligned_le (offsets_array + offset_size * i,
offset_size);
if (this_end < offset || this_end > last_end)
return FALSE;
while (offset & alignment)
{
if (!(offset < this_end && value.data[offset] == '\0'))
return FALSE;
offset++;
}
child.data = value.data + offset;
child.size = this_end - offset;
if (child.size == 0)
child.data = NULL;
if (!g_variant_serialised_is_normal (child))
return FALSE;
offset = this_end;
}
g_assert (offset == last_end);
return TRUE;
}
/* Tuples {{{2
*
* Since tuples can contain a mix of variable- and fixed-sized items,
* they are, in terms of serialisation, a hybrid of variable-sized and
* fixed-sized arrays.
*
* Offsets are only stored for variable-sized items. Also, since the
* number of items in a tuple is known from its type, we are able to
* know exactly how many offsets to expect in the serialised data (and
* therefore how much space is taken up by the offset array). This
* means that we know where the end of the serialised data for the last
* item is -- we can just subtract the size of the offset array from the
* total size of the tuple. For this reason, the last item in the tuple
* doesn't need an offset stored.
*
* Tuple offsets are stored in reverse. This design choice allows
* iterator-based deserialisers to be more efficient.
*
* Most of the "heavy lifting" here is handled by the GVariantTypeInfo
* for the tuple. See the notes in gvarianttypeinfo.h.
*/
static gsize
gvs_tuple_n_children (GVariantSerialised value)
{
return g_variant_type_info_n_members (value.type_info);
}
static GVariantSerialised
gvs_tuple_get_child (GVariantSerialised value,
gsize index_)
{
const GVariantMemberInfo *member_info;
GVariantSerialised child = { 0, };
gsize offset_size;
gsize start, end;
member_info = g_variant_type_info_member_info (value.type_info, index_);
child.type_info = g_variant_type_info_ref (member_info->type_info);
offset_size = gvs_get_offset_size (value.size);
/* tuples are the only (potentially) fixed-sized containers, so the
* only ones that have to deal with the possibility of having %NULL
* data with a non-zero %size if errors occurred elsewhere.
*/
if G_UNLIKELY (value.data == NULL && value.size != 0)
{
g_variant_type_info_query (child.type_info, NULL, &child.size);
/* this can only happen in fixed-sized tuples,
* so the child must also be fixed sized.
*/
g_assert (child.size != 0);
child.data = NULL;
return child;
}
if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET)
{
if (offset_size * (member_info->i + 2) > value.size)
return child;
}
else
{
if (offset_size * (member_info->i + 1) > value.size)
{
/* if the child is fixed size, return its size.
* if child is not fixed-sized, return size = 0.
*/
g_variant_type_info_query (child.type_info, NULL, &child.size);
return child;
}
}
if (member_info->i + 1)
start = gvs_read_unaligned_le (value.data + value.size -
offset_size * (member_info->i + 1),
offset_size);
else
start = 0;
start += member_info->a;
start &= member_info->b;
start |= member_info->c;
if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
end = value.size - offset_size * (member_info->i + 1);
else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
{
gsize fixed_size;
g_variant_type_info_query (child.type_info, NULL, &fixed_size);
end = start + fixed_size;
child.size = fixed_size;
}
else /* G_VARIANT_MEMEBER_ENDING_OFFSET */
end = gvs_read_unaligned_le (value.data + value.size -
offset_size * (member_info->i + 2),
offset_size);
if (start < end && end <= value.size)
{
child.data = value.data + start;
child.size = end - start;
}
return child;
}
static gsize
gvs_tuple_needed_size (GVariantTypeInfo *type_info,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
const GVariantMemberInfo *member_info = NULL;
gsize fixed_size;
gsize offset;
gsize i;
g_variant_type_info_query (type_info, NULL, &fixed_size);
if (fixed_size)
return fixed_size;
offset = 0;
for (i = 0; i < n_children; i++)
{
guint alignment;
member_info = g_variant_type_info_member_info (type_info, i);
g_variant_type_info_query (member_info->type_info,
&alignment, &fixed_size);
offset += (-offset) & alignment;
if (fixed_size)
offset += fixed_size;
else
{
GVariantSerialised child = { 0, };
gvs_filler (&child, children[i]);
offset += child.size;
}
}
return gvs_calculate_total_size (offset, member_info->i + 1);
}
static void
gvs_tuple_serialise (GVariantSerialised value,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
gsize offset_size;
gsize offset;
gsize i;
offset_size = gvs_get_offset_size (value.size);
offset = 0;
for (i = 0; i < n_children; i++)
{
const GVariantMemberInfo *member_info;
GVariantSerialised child = { 0, };
guint alignment;
member_info = g_variant_type_info_member_info (value.type_info, i);
g_variant_type_info_query (member_info->type_info, &alignment, NULL);
while (offset & alignment)
value.data[offset++] = '\0';
child.data = value.data + offset;
gvs_filler (&child, children[i]);
offset += child.size;
if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET)
{
value.size -= offset_size;
gvs_write_unaligned_le (value.data + value.size,
offset, offset_size);
}
}
while (offset < value.size)
value.data[offset++] = '\0';
}
static gboolean
gvs_tuple_is_normal (GVariantSerialised value)
{
guint offset_size;
gsize offset_ptr;
gsize length;
gsize offset;
gsize i;
/* as per the comment in gvs_tuple_get_child() */
if G_UNLIKELY (value.data == NULL && value.size != 0)
return FALSE;
offset_size = gvs_get_offset_size (value.size);
length = g_variant_type_info_n_members (value.type_info);
offset_ptr = value.size;
offset = 0;
for (i = 0; i < length; i++)
{
const GVariantMemberInfo *member_info;
GVariantSerialised child;
gsize fixed_size;
guint alignment;
gsize end;
member_info = g_variant_type_info_member_info (value.type_info, i);
child.type_info = member_info->type_info;
g_variant_type_info_query (child.type_info, &alignment, &fixed_size);
while (offset & alignment)
{
if (offset > value.size || value.data[offset] != '\0')
return FALSE;
offset++;
}
child.data = value.data + offset;
switch (member_info->ending_type)
{
case G_VARIANT_MEMBER_ENDING_FIXED:
end = offset + fixed_size;
break;
case G_VARIANT_MEMBER_ENDING_LAST:
end = offset_ptr;
break;
case G_VARIANT_MEMBER_ENDING_OFFSET:
offset_ptr -= offset_size;
if (offset_ptr < offset)
return FALSE;
end = gvs_read_unaligned_le (value.data + offset_ptr, offset_size);
break;
default:
g_assert_not_reached ();
}
if (end < offset || end > offset_ptr)
return FALSE;
child.size = end - offset;
if (child.size == 0)
child.data = NULL;
if (!g_variant_serialised_is_normal (child))
return FALSE;
offset = end;
}
{
gsize fixed_size;
guint alignment;
g_variant_type_info_query (value.type_info, &alignment, &fixed_size);
if (fixed_size)
{
g_assert (fixed_size == value.size);
g_assert (offset_ptr == value.size);
if (i == 0)
{
if (value.data[offset++] != '\0')
return FALSE;
}
else
{
while (offset & alignment)
if (value.data[offset++] != '\0')
return FALSE;
}
g_assert (offset == value.size);
}
}
return offset_ptr == offset;
}
/* Variants {{{2
*
* Variants are stored by storing the serialised data of the child,
* followed by a '\0' character, followed by the type string of the
* child.
*
* In the case that a value is presented that contains no '\0'
* character, or doesn't have a single well-formed definite type string
* following that character, the variant must be taken as containing the
* unit tuple: ().
*/
static inline gsize
gvs_variant_n_children (GVariantSerialised value)
{
return 1;
}
static inline GVariantSerialised
gvs_variant_get_child (GVariantSerialised value,
gsize index_)
{
GVariantSerialised child = { 0, };
/* NOTE: not O(1) and impossible for it to be... */
if (value.size)
{
/* find '\0' character */
for (child.size = value.size - 1; child.size; child.size--)
if (value.data[child.size] == '\0')
break;
/* ensure we didn't just hit the start of the string */
if (value.data[child.size] == '\0')
{
const gchar *type_string = (gchar *) &value.data[child.size + 1];
const gchar *limit = (gchar *) &value.data[value.size];
const gchar *end;
if (g_variant_type_string_scan (type_string, limit, &end) &&
end == limit)
{
const GVariantType *type = (GVariantType *) type_string;
if (g_variant_type_is_definite (type))
{
gsize fixed_size;
child.type_info = g_variant_type_info_get (type);
if (child.size != 0)
/* only set to non-%NULL if size > 0 */
child.data = value.data;
g_variant_type_info_query (child.type_info,
NULL, &fixed_size);
if (!fixed_size || fixed_size == child.size)
return child;
g_variant_type_info_unref (child.type_info);
}
}
}
}
child.type_info = g_variant_type_info_get (G_VARIANT_TYPE_UNIT);
child.data = NULL;
child.size = 1;
return child;
}
static inline gsize
gvs_variant_needed_size (GVariantTypeInfo *type_info,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
GVariantSerialised child = { 0, };
const gchar *type_string;
gvs_filler (&child, children[0]);
type_string = g_variant_type_info_get_type_string (child.type_info);
return child.size + 1 + strlen (type_string);
}
static inline void
gvs_variant_serialise (GVariantSerialised value,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
GVariantSerialised child = { 0, };
const gchar *type_string;
child.data = value.data;
gvs_filler (&child, children[0]);
type_string = g_variant_type_info_get_type_string (child.type_info);
value.data[child.size] = '\0';
memcpy (value.data + child.size + 1, type_string, strlen (type_string));
}
static inline gboolean
gvs_variant_is_normal (GVariantSerialised value)
{
GVariantSerialised child;
gboolean normal;
child = gvs_variant_get_child (value, 0);
normal = (child.data != NULL || child.size == 0) &&
g_variant_serialised_is_normal (child);
g_variant_type_info_unref (child.type_info);
return normal;
}
/* PART 2: Serialiser API {{{1
*
* This is the implementation of the API of the serialiser as advertised
* in gvariant-serialiser.h.
*/
/* Dispatch Utilities {{{2
*
* These macros allow a given function (for example,
* g_variant_serialiser_serialise) to be dispatched to the appropriate
* type-specific function above (fixed/variable-sized maybe,
* fixed/variable-sized array, tuple or variant).
*/
#define DISPATCH_FIXED(type_info, before, after) \
{ \
gsize fixed_size; \
\
g_variant_type_info_query_element (type_info, NULL, \
&fixed_size); \
\
if (fixed_size) \
{ \
before ## fixed_sized ## after \
} \
else \
{ \
before ## variable_sized ## after \
} \
}
#define DISPATCH_CASES(type_info, before, after) \
switch (g_variant_type_info_get_type_char (type_info)) \
{ \
case G_VARIANT_TYPE_INFO_CHAR_MAYBE: \
DISPATCH_FIXED (type_info, before, _maybe ## after) \
\
case G_VARIANT_TYPE_INFO_CHAR_ARRAY: \
DISPATCH_FIXED (type_info, before, _array ## after) \
\
case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY: \
case G_VARIANT_TYPE_INFO_CHAR_TUPLE: \
{ \
before ## tuple ## after \
} \
\
case G_VARIANT_TYPE_INFO_CHAR_VARIANT: \
{ \
before ## variant ## after \
} \
}
/* Serialiser entry points {{{2
*
* These are the functions that are called in order for the serialiser
* to do its thing.
*/
/* < private >
* g_variant_serialised_n_children:
* @serialised: a #GVariantSerialised
*
* For serialised data that represents a container value (maybes,
* tuples, arrays, variants), determine how many child items are inside
* that container.
*
* Returns: the number of children
*/
gsize
g_variant_serialised_n_children (GVariantSerialised serialised)
{
g_variant_serialised_check (serialised);
DISPATCH_CASES (serialised.type_info,
return gvs_/**/,/**/_n_children (serialised);
)
g_assert_not_reached ();
}
/* < private >
* g_variant_serialised_get_child:
* @serialised: a #GVariantSerialised
* @index_: the index of the child to fetch
*
* Extracts a child from a serialised data representing a container
* value.
*
* It is an error to call this function with an index out of bounds.
*
* If the result .data == %NULL and .size > 0 then there has been an
* error extracting the requested fixed-sized value. This number of
* zero bytes needs to be allocated instead.
*
* In the case that .data == %NULL and .size == 0 then a zero-sized
* item of a variable-sized type is being returned.
*
* .data is never non-%NULL if size is 0.
*
* Returns: a #GVariantSerialised for the child
*/
GVariantSerialised
g_variant_serialised_get_child (GVariantSerialised serialised,
gsize index_)
{
GVariantSerialised child;
g_variant_serialised_check (serialised);
if G_LIKELY (index_ < g_variant_serialised_n_children (serialised))
{
DISPATCH_CASES (serialised.type_info,
child = gvs_/**/,/**/_get_child (serialised, index_);
g_assert (child.size || child.data == NULL);
g_variant_serialised_check (child);
return child;
)
g_assert_not_reached ();
}
g_error ("Attempt to access item %"G_GSIZE_FORMAT
" in a container with only %"G_GSIZE_FORMAT" items",
index_, g_variant_serialised_n_children (serialised));
}
/* < private >
* g_variant_serialiser_serialise:
* @serialised: a #GVariantSerialised, properly set up
* @gvs_filler: the filler function
* @children: an array of child items
* @n_children: the size of @children
*
* Writes data in serialised form.
*
* The type_info field of @serialised must be filled in to type info for
* the type that we are serialising.
*
* The size field of @serialised must be filled in with the value
* returned by a previous call to g_variant_serialiser_needed_size().
*
* The data field of @serialised must be a pointer to a properly-aligned
* memory region large enough to serialise into (ie: at least as big as
* the size field).
*
* This function is only resonsible for serialising the top-level
* container. @gvs_filler is called on each child of the container in
* order for all of the data of that child to be filled in.
*/
void
g_variant_serialiser_serialise (GVariantSerialised serialised,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
g_variant_serialised_check (serialised);
DISPATCH_CASES (serialised.type_info,
gvs_/**/,/**/_serialise (serialised, gvs_filler,
children, n_children);
return;
)
g_assert_not_reached ();
}
/* < private >
* g_variant_serialiser_needed_size:
* @type_info: the type to serialise for
* @gvs_filler: the filler function
* @children: an array of child items
* @n_children: the size of @children
*
* Determines how much memory would be needed to serialise this value.
*
* This function is only resonsible for performing calculations for the
* top-level container. @gvs_filler is called on each child of the
* container in order to determine its size.
*/
gsize
g_variant_serialiser_needed_size (GVariantTypeInfo *type_info,
GVariantSerialisedFiller gvs_filler,
const gpointer *children,
gsize n_children)
{
DISPATCH_CASES (type_info,
return gvs_/**/,/**/_needed_size (type_info, gvs_filler,
children, n_children);
)
g_assert_not_reached ();
}
/* Byteswapping {{{2 */
/* < private >
* g_variant_serialised_byteswap:
* @value: a #GVariantSerialised
*
* Byte-swap serialised data. The result of this function is only
* well-defined if the data is in normal form.
*/
void
g_variant_serialised_byteswap (GVariantSerialised serialised)
{
gsize fixed_size;
guint alignment;
g_variant_serialised_check (serialised);
if (!serialised.data)
return;
/* the types we potentially need to byteswap are
* exactly those with alignment requirements.
*/
g_variant_type_info_query (serialised.type_info, &alignment, &fixed_size);
if (!alignment)
return;
/* if fixed size and alignment are equal then we are down
* to the base integer type and we should swap it. the
* only exception to this is if we have a tuple with a
* single item, and then swapping it will be OK anyway.
*/
if (alignment + 1 == fixed_size)
{
switch (fixed_size)
{
case 2:
{
guint16 *ptr = (guint16 *) serialised.data;
g_assert_cmpint (serialised.size, ==, 2);
*ptr = GUINT16_SWAP_LE_BE (*ptr);
}
return;
case 4:
{
guint32 *ptr = (guint32 *) serialised.data;
g_assert_cmpint (serialised.size, ==, 4);
*ptr = GUINT32_SWAP_LE_BE (*ptr);
}
return;
case 8:
{
guint64 *ptr = (guint64 *) serialised.data;
g_assert_cmpint (serialised.size, ==, 8);
*ptr = GUINT64_SWAP_LE_BE (*ptr);
}
return;
default:
g_assert_not_reached ();
}
}
/* else, we have a container that potentially contains
* some children that need to be byteswapped.
*/
else
{
gsize children, i;
children = g_variant_serialised_n_children (serialised);
for (i = 0; i < children; i++)
{
GVariantSerialised child;
child = g_variant_serialised_get_child (serialised, i);
g_variant_serialised_byteswap (child);
g_variant_type_info_unref (child.type_info);
}
}
}
/* Normal form checking {{{2 */
/* < private >
* g_variant_serialised_is_normal:
* @serialised: a #GVariantSerialised
*
* Determines, recursively if @serialised is in normal form. There is
* precisely one normal form of serialised data for each possible value.
*
* It is possible that multiple byte sequences form the serialised data
* for a given value if, for example, the padding bytes are filled in
* with something other than zeros, but only one form is the normal
* form.
*/
gboolean
g_variant_serialised_is_normal (GVariantSerialised serialised)
{
DISPATCH_CASES (serialised.type_info,
return gvs_/**/,/**/_is_normal (serialised);
)
if (serialised.data == NULL)
return FALSE;
/* some hard-coded terminal cases */
switch (g_variant_type_info_get_type_char (serialised.type_info))
{
case 'b': /* boolean */
return serialised.data[0] < 2;
case 's': /* string */
return g_variant_serialiser_is_string (serialised.data,
serialised.size);
case 'o':
return g_variant_serialiser_is_object_path (serialised.data,
serialised.size);
case 'g':
return g_variant_serialiser_is_signature (serialised.data,
serialised.size);
default:
/* all of the other types are fixed-sized numerical types for
* which all possible values are valid (including various NaN
* representations for floating point values).
*/
return TRUE;
}
}
/* Validity-checking functions {{{2
*
* Checks if strings, object paths and signature strings are valid.
*/
/* < private >
* g_variant_serialiser_is_string:
* @data: a possible string
* @size: the size of @data
*
* Ensures that @data is a valid string with a nul terminator at the end
* and no nul bytes embedded.
*/
gboolean
g_variant_serialiser_is_string (gconstpointer data,
gsize size)
{
const gchar *expected_end;
const gchar *end;
if (size == 0)
return FALSE;
expected_end = ((gchar *) data) + size - 1;
if (*expected_end != '\0')
return FALSE;
g_utf8_validate (data, size, &end);
return end == expected_end;
}
/* < private >
* g_variant_serialiser_is_object_path:
* @data: a possible D-Bus object path
* @size: the size of @data
*
* Performs the checks for being a valid string.
*
* Also, ensures that @data is a valid DBus object path, as per the D-Bus
* specification.
*/
gboolean
g_variant_serialiser_is_object_path (gconstpointer data,
gsize size)
{
const gchar *string = data;
gsize i;
if (!g_variant_serialiser_is_string (data, size))
return FALSE;
/* The path must begin with an ASCII '/' (integer 47) character */
if (string[0] != '/')
return FALSE;
for (i = 1; string[i]; i++)
/* Each element must only contain the ASCII characters
* "[A-Z][a-z][0-9]_"
*/
if (g_ascii_isalnum (string[i]) || string[i] == '_')
;
/* must consist of elements separated by slash characters. */
else if (string[i] == '/')
{
/* No element may be the empty string. */
/* Multiple '/' characters cannot occur in sequence. */
if (string[i - 1] == '/')
return FALSE;
}
else
return FALSE;
/* A trailing '/' character is not allowed unless the path is the
* root path (a single '/' character).
*/
if (i > 1 && string[i - 1] == '/')
return FALSE;
return TRUE;
}
/* < private >
* g_variant_serialiser_is_signature:
* @data: a possible D-Bus signature
* @size: the size of @data
*
* Performs the checks for being a valid string.
*
* Also, ensures that @data is a valid D-Bus type signature, as per the
* D-Bus specification.
*/
gboolean
g_variant_serialiser_is_signature (gconstpointer data,
gsize size)
{
const gchar *string = data;
gsize first_invalid;
if (!g_variant_serialiser_is_string (data, size))
return FALSE;
/* make sure no non-definite characters appear */
first_invalid = strspn (string, "ybnqiuxthdvasog(){}");
if (string[first_invalid])
return FALSE;
/* make sure each type string is well-formed */
while (*string)
if (!g_variant_type_string_scan (string, NULL, &string))
return FALSE;
return TRUE;
}
/* Epilogue {{{1 */
/* vim:set foldmethod=marker: */
pkg-config-0.29.1/glib/glib/gmain.h 0000664 0001750 0001750 00000053563 12651243552 013671 0000000 0000000 /* gmain.h - the GLib Main loop
* Copyright (C) 1998-2000 Red Hat, 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; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __G_MAIN_H__
#define __G_MAIN_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
#include
#include
G_BEGIN_DECLS
typedef enum /*< flags >*/
{
G_IO_IN GLIB_SYSDEF_POLLIN,
G_IO_OUT GLIB_SYSDEF_POLLOUT,
G_IO_PRI GLIB_SYSDEF_POLLPRI,
G_IO_ERR GLIB_SYSDEF_POLLERR,
G_IO_HUP GLIB_SYSDEF_POLLHUP,
G_IO_NVAL GLIB_SYSDEF_POLLNVAL
} GIOCondition;
/**
* GMainContext:
*
* The GMainContext struct is an opaque data
* type representing a set of sources to be handled in a main loop.
*/
typedef struct _GMainContext GMainContext;
/**
* GMainLoop:
*
* The GMainLoop struct is an opaque data type
* representing the main event loop of a GLib or GTK+ application.
*/
typedef struct _GMainLoop GMainLoop;
/**
* GSource:
*
* The GSource struct is an opaque data type
* representing an event source.
*/
typedef struct _GSource GSource;
typedef struct _GSourcePrivate GSourcePrivate;
/**
* GSourceCallbackFuncs:
* @ref: Called when a reference is added to the callback object
* @unref: Called when a reference to the callback object is dropped
* @get: Called to extract the callback function and data from the
* callback object.
* The GSourceCallbackFuncs struct contains
* functions for managing callback objects.
*/
typedef struct _GSourceCallbackFuncs GSourceCallbackFuncs;
/**
* GSourceFuncs:
* @prepare: Called before all the file descriptors are polled. If the
* source can determine that it is ready here (without waiting for the
* results of the poll() call) it should return %TRUE. It can also return
* a @timeout_ value which should be the maximum timeout (in milliseconds)
* which should be passed to the poll() call. The actual timeout used will
* be -1 if all sources returned -1, or it will be the minimum of all
* the @timeout_ values returned which were >= 0. Since 2.36 this may
* be %NULL, in which case the effect is as if the function always returns
* %FALSE with a timeout of -1. If @prepare returns a
* timeout and the source also has a 'ready time' set then the
* nearer of the two will be used.
* @check: Called after all the file descriptors are polled. The source
* should return %TRUE if it is ready to be dispatched. Note that some
* time may have passed since the previous prepare function was called,
* so the source should be checked again here. Since 2.36 this may
* be %NULL, in which case the effect is as if the function always returns
* %FALSE.
* @dispatch: Called to dispatch the event source, after it has returned
* %TRUE in either its @prepare or its @check function. The @dispatch
* function is passed in a callback function and data. The callback
* function may be %NULL if the source was never connected to a callback
* using g_source_set_callback(). The @dispatch function should call the
* callback function with @user_data and whatever additional parameters
* are needed for this type of event source.
* @finalize: Called when the source is finalized.
*
* The GSourceFuncs struct contains a table of
* functions used to handle event sources in a generic manner.
*
* For idle sources, the prepare and check functions always return %TRUE
* to indicate that the source is always ready to be processed. The prepare
* function also returns a timeout value of 0 to ensure that the poll() call
* doesn't block (since that would be time wasted which could have been spent
* running the idle function).
*
* For timeout sources, the prepare and check functions both return %TRUE
* if the timeout interval has expired. The prepare function also returns
* a timeout value to ensure that the poll() call doesn't block too long
* and miss the next timeout.
*
* For file descriptor sources, the prepare function typically returns %FALSE,
* since it must wait until poll() has been called before it knows whether
* any events need to be processed. It sets the returned timeout to -1 to
* indicate that it doesn't mind how long the poll() call blocks. In the
* check function, it tests the results of the poll() call to see if the
* required condition has been met, and returns %TRUE if so.
*/
typedef struct _GSourceFuncs GSourceFuncs;
/**
* GPid:
*
* A type which is used to hold a process identification.
*
* On UNIX, processes are identified by a process id (an integer),
* while Windows uses process handles (which are pointers).
*
* GPid is used in GLib only for descendant processes spawned with
* the g_spawn functions.
*/
/**
* GSourceFunc:
* @user_data: data passed to the function, set when the source was
* created with one of the above functions
*
* Specifies the type of function passed to g_timeout_add(),
* g_timeout_add_full(), g_idle_add(), and g_idle_add_full().
*
* Returns: %FALSE if the source should be removed. #G_SOURCE_CONTINUE and
* #G_SOURCE_REMOVE are more memorable names for the return value.
*/
typedef gboolean (*GSourceFunc) (gpointer user_data);
/**
* GChildWatchFunc:
* @pid: the process id of the child process
* @status: Status information about the child process, encoded
* in a platform-specific manner
* @user_data: user data passed to g_child_watch_add()
*
* Prototype of a #GChildWatchSource callback, called when a child
* process has exited. To interpret @status, see the documentation
* for g_spawn_check_exit_status().
*/
typedef void (*GChildWatchFunc) (GPid pid,
gint status,
gpointer user_data);
struct _GSource
{
/*< private >*/
gpointer callback_data;
GSourceCallbackFuncs *callback_funcs;
const GSourceFuncs *source_funcs;
guint ref_count;
GMainContext *context;
gint priority;
guint flags;
guint source_id;
GSList *poll_fds;
GSource *prev;
GSource *next;
char *name;
GSourcePrivate *priv;
};
struct _GSourceCallbackFuncs
{
void (*ref) (gpointer cb_data);
void (*unref) (gpointer cb_data);
void (*get) (gpointer cb_data,
GSource *source,
GSourceFunc *func,
gpointer *data);
};
/**
* GSourceDummyMarshal:
*
* This is just a placeholder for #GClosureMarshal,
* which cannot be used here for dependency reasons.
*/
typedef void (*GSourceDummyMarshal) (void);
struct _GSourceFuncs
{
gboolean (*prepare) (GSource *source,
gint *timeout_);
gboolean (*check) (GSource *source);
gboolean (*dispatch) (GSource *source,
GSourceFunc callback,
gpointer user_data);
void (*finalize) (GSource *source); /* Can be NULL */
/*< private >*/
/* For use by g_source_set_closure */
GSourceFunc closure_callback;
GSourceDummyMarshal closure_marshal; /* Really is of type GClosureMarshal */
};
/* Standard priorities */
/**
* G_PRIORITY_HIGH:
*
* Use this for high priority event sources.
*
* It is not used within GLib or GTK+.
*/
#define G_PRIORITY_HIGH -100
/**
* G_PRIORITY_DEFAULT:
*
* Use this for default priority event sources.
*
* In GLib this priority is used when adding timeout functions
* with g_timeout_add(). In GDK this priority is used for events
* from the X server.
*/
#define G_PRIORITY_DEFAULT 0
/**
* G_PRIORITY_HIGH_IDLE:
*
* Use this for high priority idle functions.
*
* GTK+ uses #G_PRIORITY_HIGH_IDLE + 10 for resizing operations,
* and #G_PRIORITY_HIGH_IDLE + 20 for redrawing operations. (This is
* done to ensure that any pending resizes are processed before any
* pending redraws, so that widgets are not redrawn twice unnecessarily.)
*/
#define G_PRIORITY_HIGH_IDLE 100
/**
* G_PRIORITY_DEFAULT_IDLE:
*
* Use this for default priority idle functions.
*
* In GLib this priority is used when adding idle functions with
* g_idle_add().
*/
#define G_PRIORITY_DEFAULT_IDLE 200
/**
* G_PRIORITY_LOW:
*
* Use this for very low priority background tasks.
*
* It is not used within GLib or GTK+.
*/
#define G_PRIORITY_LOW 300
/**
* G_SOURCE_REMOVE:
*
* Use this macro as the return value of a #GSourceFunc to remove
* the #GSource from the main loop.
*
* Since: 2.32
*/
#define G_SOURCE_REMOVE FALSE
/**
* G_SOURCE_CONTINUE:
*
* Use this macro as the return value of a #GSourceFunc to leave
* the #GSource in the main loop.
*
* Since: 2.32
*/
#define G_SOURCE_CONTINUE TRUE
/* GMainContext: */
GLIB_AVAILABLE_IN_ALL
GMainContext *g_main_context_new (void);
GLIB_AVAILABLE_IN_ALL
GMainContext *g_main_context_ref (GMainContext *context);
GLIB_AVAILABLE_IN_ALL
void g_main_context_unref (GMainContext *context);
GLIB_AVAILABLE_IN_ALL
GMainContext *g_main_context_default (void);
GLIB_AVAILABLE_IN_ALL
gboolean g_main_context_iteration (GMainContext *context,
gboolean may_block);
GLIB_AVAILABLE_IN_ALL
gboolean g_main_context_pending (GMainContext *context);
/* For implementation of legacy interfaces
*/
GLIB_AVAILABLE_IN_ALL
GSource *g_main_context_find_source_by_id (GMainContext *context,
guint source_id);
GLIB_AVAILABLE_IN_ALL
GSource *g_main_context_find_source_by_user_data (GMainContext *context,
gpointer user_data);
GLIB_AVAILABLE_IN_ALL
GSource *g_main_context_find_source_by_funcs_user_data (GMainContext *context,
GSourceFuncs *funcs,
gpointer user_data);
/* Low level functions for implementing custom main loops.
*/
GLIB_AVAILABLE_IN_ALL
void g_main_context_wakeup (GMainContext *context);
GLIB_AVAILABLE_IN_ALL
gboolean g_main_context_acquire (GMainContext *context);
GLIB_AVAILABLE_IN_ALL
void g_main_context_release (GMainContext *context);
GLIB_AVAILABLE_IN_ALL
gboolean g_main_context_is_owner (GMainContext *context);
GLIB_AVAILABLE_IN_ALL
gboolean g_main_context_wait (GMainContext *context,
GCond *cond,
GMutex *mutex);
GLIB_AVAILABLE_IN_ALL
gboolean g_main_context_prepare (GMainContext *context,
gint *priority);
GLIB_AVAILABLE_IN_ALL
gint g_main_context_query (GMainContext *context,
gint max_priority,
gint *timeout_,
GPollFD *fds,
gint n_fds);
GLIB_AVAILABLE_IN_ALL
gint g_main_context_check (GMainContext *context,
gint max_priority,
GPollFD *fds,
gint n_fds);
GLIB_AVAILABLE_IN_ALL
void g_main_context_dispatch (GMainContext *context);
GLIB_AVAILABLE_IN_ALL
void g_main_context_set_poll_func (GMainContext *context,
GPollFunc func);
GLIB_AVAILABLE_IN_ALL
GPollFunc g_main_context_get_poll_func (GMainContext *context);
/* Low level functions for use by source implementations
*/
GLIB_AVAILABLE_IN_ALL
void g_main_context_add_poll (GMainContext *context,
GPollFD *fd,
gint priority);
GLIB_AVAILABLE_IN_ALL
void g_main_context_remove_poll (GMainContext *context,
GPollFD *fd);
GLIB_AVAILABLE_IN_ALL
gint g_main_depth (void);
GLIB_AVAILABLE_IN_ALL
GSource *g_main_current_source (void);
/* GMainContexts for other threads
*/
GLIB_AVAILABLE_IN_ALL
void g_main_context_push_thread_default (GMainContext *context);
GLIB_AVAILABLE_IN_ALL
void g_main_context_pop_thread_default (GMainContext *context);
GLIB_AVAILABLE_IN_ALL
GMainContext *g_main_context_get_thread_default (void);
GLIB_AVAILABLE_IN_ALL
GMainContext *g_main_context_ref_thread_default (void);
/* GMainLoop: */
GLIB_AVAILABLE_IN_ALL
GMainLoop *g_main_loop_new (GMainContext *context,
gboolean is_running);
GLIB_AVAILABLE_IN_ALL
void g_main_loop_run (GMainLoop *loop);
GLIB_AVAILABLE_IN_ALL
void g_main_loop_quit (GMainLoop *loop);
GLIB_AVAILABLE_IN_ALL
GMainLoop *g_main_loop_ref (GMainLoop *loop);
GLIB_AVAILABLE_IN_ALL
void g_main_loop_unref (GMainLoop *loop);
GLIB_AVAILABLE_IN_ALL
gboolean g_main_loop_is_running (GMainLoop *loop);
GLIB_AVAILABLE_IN_ALL
GMainContext *g_main_loop_get_context (GMainLoop *loop);
/* GSource: */
GLIB_AVAILABLE_IN_ALL
GSource *g_source_new (GSourceFuncs *source_funcs,
guint struct_size);
GLIB_AVAILABLE_IN_ALL
GSource *g_source_ref (GSource *source);
GLIB_AVAILABLE_IN_ALL
void g_source_unref (GSource *source);
GLIB_AVAILABLE_IN_ALL
guint g_source_attach (GSource *source,
GMainContext *context);
GLIB_AVAILABLE_IN_ALL
void g_source_destroy (GSource *source);
GLIB_AVAILABLE_IN_ALL
void g_source_set_priority (GSource *source,
gint priority);
GLIB_AVAILABLE_IN_ALL
gint g_source_get_priority (GSource *source);
GLIB_AVAILABLE_IN_ALL
void g_source_set_can_recurse (GSource *source,
gboolean can_recurse);
GLIB_AVAILABLE_IN_ALL
gboolean g_source_get_can_recurse (GSource *source);
GLIB_AVAILABLE_IN_ALL
guint g_source_get_id (GSource *source);
GLIB_AVAILABLE_IN_ALL
GMainContext *g_source_get_context (GSource *source);
GLIB_AVAILABLE_IN_ALL
void g_source_set_callback (GSource *source,
GSourceFunc func,
gpointer data,
GDestroyNotify notify);
GLIB_AVAILABLE_IN_ALL
void g_source_set_funcs (GSource *source,
GSourceFuncs *funcs);
GLIB_AVAILABLE_IN_ALL
gboolean g_source_is_destroyed (GSource *source);
GLIB_AVAILABLE_IN_ALL
void g_source_set_name (GSource *source,
const char *name);
GLIB_AVAILABLE_IN_ALL
const char * g_source_get_name (GSource *source);
GLIB_AVAILABLE_IN_ALL
void g_source_set_name_by_id (guint tag,
const char *name);
GLIB_AVAILABLE_IN_2_36
void g_source_set_ready_time (GSource *source,
gint64 ready_time);
GLIB_AVAILABLE_IN_2_36
gint64 g_source_get_ready_time (GSource *source);
#ifdef G_OS_UNIX
GLIB_AVAILABLE_IN_2_36
gpointer g_source_add_unix_fd (GSource *source,
gint fd,
GIOCondition events);
GLIB_AVAILABLE_IN_2_36
void g_source_modify_unix_fd (GSource *source,
gpointer tag,
GIOCondition new_events);
GLIB_AVAILABLE_IN_2_36
void g_source_remove_unix_fd (GSource *source,
gpointer tag);
GLIB_AVAILABLE_IN_2_36
GIOCondition g_source_query_unix_fd (GSource *source,
gpointer tag);
#endif
/* Used to implement g_source_connect_closure and internally*/
GLIB_AVAILABLE_IN_ALL
void g_source_set_callback_indirect (GSource *source,
gpointer callback_data,
GSourceCallbackFuncs *callback_funcs);
GLIB_AVAILABLE_IN_ALL
void g_source_add_poll (GSource *source,
GPollFD *fd);
GLIB_AVAILABLE_IN_ALL
void g_source_remove_poll (GSource *source,
GPollFD *fd);
GLIB_AVAILABLE_IN_ALL
void g_source_add_child_source (GSource *source,
GSource *child_source);
GLIB_AVAILABLE_IN_ALL
void g_source_remove_child_source (GSource *source,
GSource *child_source);
GLIB_DEPRECATED_IN_2_28_FOR(g_source_get_time)
void g_source_get_current_time (GSource *source,
GTimeVal *timeval);
GLIB_AVAILABLE_IN_ALL
gint64 g_source_get_time (GSource *source);
/* void g_source_connect_closure (GSource *source,
GClosure *closure);
*/
/* Specific source types
*/
GLIB_AVAILABLE_IN_ALL
GSource *g_idle_source_new (void);
GLIB_AVAILABLE_IN_ALL
GSource *g_child_watch_source_new (GPid pid);
GLIB_AVAILABLE_IN_ALL
GSource *g_timeout_source_new (guint interval);
GLIB_AVAILABLE_IN_ALL
GSource *g_timeout_source_new_seconds (guint interval);
/* Miscellaneous functions
*/
GLIB_AVAILABLE_IN_ALL
void g_get_current_time (GTimeVal *result);
GLIB_AVAILABLE_IN_ALL
gint64 g_get_monotonic_time (void);
GLIB_AVAILABLE_IN_ALL
gint64 g_get_real_time (void);
/* Source manipulation by ID */
GLIB_AVAILABLE_IN_ALL
gboolean g_source_remove (guint tag);
GLIB_AVAILABLE_IN_ALL
gboolean g_source_remove_by_user_data (gpointer user_data);
GLIB_AVAILABLE_IN_ALL
gboolean g_source_remove_by_funcs_user_data (GSourceFuncs *funcs,
gpointer user_data);
/* Idles, child watchers and timeouts */
GLIB_AVAILABLE_IN_ALL
guint g_timeout_add_full (gint priority,
guint interval,
GSourceFunc function,
gpointer data,
GDestroyNotify notify);
GLIB_AVAILABLE_IN_ALL
guint g_timeout_add (guint interval,
GSourceFunc function,
gpointer data);
GLIB_AVAILABLE_IN_ALL
guint g_timeout_add_seconds_full (gint priority,
guint interval,
GSourceFunc function,
gpointer data,
GDestroyNotify notify);
GLIB_AVAILABLE_IN_ALL
guint g_timeout_add_seconds (guint interval,
GSourceFunc function,
gpointer data);
GLIB_AVAILABLE_IN_ALL
guint g_child_watch_add_full (gint priority,
GPid pid,
GChildWatchFunc function,
gpointer data,
GDestroyNotify notify);
GLIB_AVAILABLE_IN_ALL
guint g_child_watch_add (GPid pid,
GChildWatchFunc function,
gpointer data);
GLIB_AVAILABLE_IN_ALL
guint g_idle_add (GSourceFunc function,
gpointer data);
GLIB_AVAILABLE_IN_ALL
guint g_idle_add_full (gint priority,
GSourceFunc function,
gpointer data,
GDestroyNotify notify);
GLIB_AVAILABLE_IN_ALL
gboolean g_idle_remove_by_data (gpointer data);
GLIB_AVAILABLE_IN_ALL
void g_main_context_invoke_full (GMainContext *context,
gint priority,
GSourceFunc function,
gpointer data,
GDestroyNotify notify);
GLIB_AVAILABLE_IN_ALL
void g_main_context_invoke (GMainContext *context,
GSourceFunc function,
gpointer data);
/* Hook for GClosure / GSource integration. Don't touch */
GLIB_VAR GSourceFuncs g_timeout_funcs;
GLIB_VAR GSourceFuncs g_child_watch_funcs;
GLIB_VAR GSourceFuncs g_idle_funcs;
#ifdef G_OS_UNIX
GLIB_VAR GSourceFuncs g_unix_signal_funcs;
GLIB_VAR GSourceFuncs g_unix_fd_source_funcs;
#endif
G_END_DECLS
#endif /* __G_MAIN_H__ */
pkg-config-0.29.1/glib/glib/gerror.h 0000664 0001750 0001750 00000007760 12651243552 014074 0000000 0000000 /* gerror.h - Error reporting system
*
* Copyright 2000 Red Hat, Inc.
*
* The Gnome 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 of the
* License, or (at your option) any later version.
*
* The Gnome 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 Gnome Library; see the file COPYING.LIB. If not,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __G_ERROR_H__
#define __G_ERROR_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
#include
G_BEGIN_DECLS
/**
* GError:
* @domain: error domain, e.g. #G_FILE_ERROR
* @code: error code, e.g. %G_FILE_ERROR_NOENT
* @message: human-readable informative error message
*
* The GError structure contains
* information about an error that has occurred.
*/
typedef struct _GError GError;
struct _GError
{
GQuark domain;
gint code;
gchar *message;
};
GLIB_AVAILABLE_IN_ALL
GError* g_error_new (GQuark domain,
gint code,
const gchar *format,
...) G_GNUC_PRINTF (3, 4);
GLIB_AVAILABLE_IN_ALL
GError* g_error_new_literal (GQuark domain,
gint code,
const gchar *message);
GLIB_AVAILABLE_IN_ALL
GError* g_error_new_valist (GQuark domain,
gint code,
const gchar *format,
va_list args) G_GNUC_PRINTF(3, 0);
GLIB_AVAILABLE_IN_ALL
void g_error_free (GError *error);
GLIB_AVAILABLE_IN_ALL
GError* g_error_copy (const GError *error);
GLIB_AVAILABLE_IN_ALL
gboolean g_error_matches (const GError *error,
GQuark domain,
gint code);
/* if (err) *err = g_error_new(domain, code, format, ...), also has
* some sanity checks.
*/
GLIB_AVAILABLE_IN_ALL
void g_set_error (GError **err,
GQuark domain,
gint code,
const gchar *format,
...) G_GNUC_PRINTF (4, 5);
GLIB_AVAILABLE_IN_ALL
void g_set_error_literal (GError **err,
GQuark domain,
gint code,
const gchar *message);
/* if (dest) *dest = src; also has some sanity checks.
*/
GLIB_AVAILABLE_IN_ALL
void g_propagate_error (GError **dest,
GError *src);
/* if (err && *err) { g_error_free(*err); *err = NULL; } */
GLIB_AVAILABLE_IN_ALL
void g_clear_error (GError **err);
/* if (err) prefix the formatted string to the ->message */
GLIB_AVAILABLE_IN_ALL
void g_prefix_error (GError **err,
const gchar *format,
...) G_GNUC_PRINTF (2, 3);
/* g_propagate_error then g_error_prefix on dest */
GLIB_AVAILABLE_IN_ALL
void g_propagate_prefixed_error (GError **dest,
GError *src,
const gchar *format,
...) G_GNUC_PRINTF (3, 4);
G_END_DECLS
#endif /* __G_ERROR_H__ */
pkg-config-0.29.1/glib/glib/gvarianttype.c 0000664 0001750 0001750 00000120053 12651243552 015273 0000000 0000000 /*
* Copyright © 2007, 2008 Ryan Lortie
* Copyright © 2009, 2010 Codethink Limited
*
* This 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 of the licence, 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ryan Lortie
*/
#include "config.h"
#include "gvarianttype.h"
#include
#include
#include
/**
* SECTION:gvarianttype
* @title: GVariantType
* @short_description: introduction to the GVariant type system
* @see_also: #GVariantType, #GVariant
*
* This section introduces the GVariant type system. It is based, in
* large part, on the D-Bus type system, with two major changes and some minor
* lifting of restrictions. The DBus
* specification, therefore, provides a significant amount of
* information that is useful when working with GVariant.
*
* The first major change with respect to the D-Bus type system is the
* introduction of maybe (or "nullable") types. Any type in GVariant can be
* converted to a maybe type, in which case, "nothing" (or "null") becomes a
* valid value. Maybe types have been added by introducing the
* character "m" to type strings.
*
* The second major change is that the GVariant type system supports the
* concept of "indefinite types" -- types that are less specific than
* the normal types found in D-Bus. For example, it is possible to speak
* of "an array of any type" in GVariant, where the D-Bus type system
* would require you to speak of "an array of integers" or "an array of
* strings". Indefinite types have been added by introducing the
* characters "*", "?" and
* "r" to type strings.
*
* Finally, all arbitrary restrictions relating to the complexity of
* types are lifted along with the restriction that dictionary entries
* may only appear nested inside of arrays.
*
* Just as in D-Bus, GVariant types are described with strings ("type
* strings"). Subject to the differences mentioned above, these strings
* are of the same form as those found in DBus. Note, however: D-Bus
* always works in terms of messages and therefore individual type
* strings appear nowhere in its interface. Instead, "signatures"
* are a concatenation of the strings of the type of each argument in a
* message. GVariant deals with single values directly so GVariant type
* strings always describe the type of exactly one value. This means
* that a D-Bus signature string is generally not a valid GVariant type
* string -- except in the case that it is the signature of a message
* containing exactly one argument.
*
* An indefinite type is similar in spirit to what may be called an
* abstract type in other type systems. No value can exist that has an
* indefinite type as its type, but values can exist that have types
* that are subtypes of indefinite types. That is to say,
* g_variant_get_type() will never return an indefinite type, but
* calling g_variant_is_of_type() with an indefinite type may return
* %TRUE. For example, you cannot have a value that represents "an
* array of no particular type", but you can have an "array of integers"
* which certainly matches the type of "an array of no particular type",
* since "array of integers" is a subtype of "array of no particular
* type".
*
* This is similar to how instances of abstract classes may not
* directly exist in other type systems, but instances of their
* non-abstract subtypes may. For example, in GTK, no object that has
* the type of #GtkBin can exist (since #GtkBin is an abstract class),
* but a #GtkWindow can certainly be instantiated, and you would say
* that the #GtkWindow is a #GtkBin (since #GtkWindow is a subclass of
* #GtkBin).
*
* A detailed description of GVariant type strings is given here:
*
*
* GVariant Type Strings
*
* A GVariant type string can be any of the following:
*
*
*
*
* any basic type string (listed below)
*
*
*
*
* "v", "r" or
* "*"
*
*
*
*
* one of the characters 'a' or
* 'm', followed by another type string
*
*
*
*
* the character '(', followed by a concatenation
* of zero or more other type strings, followed by the character
* ')'
*
*
*
*
* the character '{', followed by a basic type
* string (see below), followed by another type string, followed by
* the character '}'
*
*
*
*
* A basic type string describes a basic type (as per
* g_variant_type_is_basic()) and is always a single
* character in length. The valid basic type strings are
* "b", "y",
* "n", "q",
* "i", "u",
* "x", "t",
* "h", "d",
* "s", "o",
* "g" and "?".
*
*
* The above definition is recursive to arbitrary depth.
* "aaaaai" and "(ui(nq((y)))s)"
* are both valid type strings, as is
* "a(aa(ui)(qna{ya(yd)}))".
*
*
* The meaning of each of the characters is as follows:
*
*
*
*
*
*
*
* Character
*
*
*
*
* Meaning
*
*
*
*
*
*
* b
*
*
*
*
* the type string of %G_VARIANT_TYPE_BOOLEAN; a boolean value.
*
*
*
*
*
*
* y
*
*
*
*
* the type string of %G_VARIANT_TYPE_BYTE; a byte.
*
*
*
*
*
*
* n
*
*
*
*
* the type string of %G_VARIANT_TYPE_INT16; a signed 16 bit
* integer.
*
*
*
*
*
*
* q
*
*
*
*
* the type string of %G_VARIANT_TYPE_UINT16; an unsigned 16 bit
* integer.
*
*
*
*
*
*
* i
*
*
*
*
* the type string of %G_VARIANT_TYPE_INT32; a signed 32 bit
* integer.
*
*
*
*
*
*
* u
*
*
*
*
* the type string of %G_VARIANT_TYPE_UINT32; an unsigned 32 bit
* integer.
*
*
*
*
*
*
* x
*
*
*
*
* the type string of %G_VARIANT_TYPE_INT64; a signed 64 bit
* integer.
*
*
*
*
*
*
* t
*
*
*
*
* the type string of %G_VARIANT_TYPE_UINT64; an unsigned 64 bit
* integer.
*
*
*
*
*
*
* h
*
*
*
*
* the type string of %G_VARIANT_TYPE_HANDLE; a signed 32 bit
* value that, by convention, is used as an index into an array
* of file descriptors that are sent alongside a D-Bus message.
*
*
*
*
*
*
* d
*
*
*
*
* the type string of %G_VARIANT_TYPE_DOUBLE; a double precision
* floating point value.
*
*
*
*
*
*
* s
*
*
*
*
* the type string of %G_VARIANT_TYPE_STRING; a string.
*
*
*
*
*
*
* o
*
*
*
*
* the type string of %G_VARIANT_TYPE_OBJECT_PATH; a string in
* the form of a D-Bus object path.
*
*
*
*
*
*
* g
*
*
*
*
* the type string of %G_VARIANT_TYPE_STRING; a string in the
* form of a D-Bus type signature.
*
*
*
*
*
*
* ?
*
*
*
*
* the type string of %G_VARIANT_TYPE_BASIC; an indefinite type
* that is a supertype of any of the basic types.
*
*
*
*
*
*
* v
*
*
*
*
* the type string of %G_VARIANT_TYPE_VARIANT; a container type
* that contain any other type of value.
*
*
*
*
*
*
* a
*
*
*
*
* used as a prefix on another type string to mean an array of
* that type; the type string "ai", for
* example, is the type of an array of 32 bit signed integers.
*
*
*
*
*
*
* m
*
*
*
*
* used as a prefix on another type string to mean a "maybe", or
* "nullable", version of that type; the type string
* "ms", for example, is the type of a value
* that maybe contains a string, or maybe contains nothing.
*
*
*
*
*
*
* ()
*
*
*
*
* used to enclose zero or more other concatenated type strings
* to create a tuple type; the type string
* "(is)", for example, is the type of a pair
* of an integer and a string.
*
*
*
*
*
*
* r
*
*
*
*
* the type string of %G_VARIANT_TYPE_TUPLE; an indefinite type
* that is a supertype of any tuple type, regardless of the
* number of items.
*
*
*
*
*
*
* {}
*
*
*
*
* used to enclose a basic type string concatenated with another
* type string to create a dictionary entry type, which usually
* appears inside of an array to form a dictionary; the type
* string "a{sd}", for example, is the type of
* a dictionary that maps strings to double precision floating
* point values.
*
*
* The first type (the basic type) is the key type and the second
* type is the value type. The reason that the first type is
* restricted to being a basic type is so that it can easily be
* hashed.
*
*
*
*
*
*
* *
*
*
*
*
* the type string of %G_VARIANT_TYPE_ANY; the indefinite type
* that is a supertype of all types. Note that, as with all type
* strings, this character represents exactly one type. It
* cannot be used inside of tuples to mean "any number of items".
*
*
*
*
*
*
*
* Any type string of a container that contains an indefinite type is,
* itself, an indefinite type. For example, the type string
* "a*" (corresponding to %G_VARIANT_TYPE_ARRAY) is
* an indefinite type that is a supertype of every array type.
* "(*s)" is a supertype of all tuples that
* contain exactly two items where the second item is a string.
*
*
* "a{?*}" is an indefinite type that is a
* supertype of all arrays containing dictionary entries where the key
* is any basic type and the value is any type at all. This is, by
* definition, a dictionary, so this type string corresponds to
* %G_VARIANT_TYPE_DICTIONARY. Note that, due to the restriction that
* the key of a dictionary entry must be a basic type,
* "{**}" is not a valid type string.
*
*
*/
static gboolean
g_variant_type_check (const GVariantType *type)
{
if (type == NULL)
return FALSE;
#if 0
return g_variant_type_string_scan ((const gchar *) type, NULL, NULL);
#else
return TRUE;
#endif
}
/**
* g_variant_type_string_scan:
* @string: a pointer to any string
* @limit: (allow-none): the end of @string, or %NULL
* @endptr: (out) (allow-none): location to store the end pointer, or %NULL
*
* Scan for a single complete and valid GVariant type string in @string.
* The memory pointed to by @limit (or bytes beyond it) is never
* accessed.
*
* If a valid type string is found, @endptr is updated to point to the
* first character past the end of the string that was found and %TRUE
* is returned.
*
* If there is no valid type string starting at @string, or if the type
* string does not end before @limit then %FALSE is returned.
*
* For the simple case of checking if a string is a valid type string,
* see g_variant_type_string_is_valid().
*
* Returns: %TRUE if a valid type string was found
*
* Since: 2.24
**/
gboolean
g_variant_type_string_scan (const gchar *string,
const gchar *limit,
const gchar **endptr)
{
g_return_val_if_fail (string != NULL, FALSE);
if (string == limit || *string == '\0')
return FALSE;
switch (*string++)
{
case '(':
while (string == limit || *string != ')')
if (!g_variant_type_string_scan (string, limit, &string))
return FALSE;
string++;
break;
case '{':
if (string == limit || *string == '\0' || /* { */
!strchr ("bynqihuxtdsog?", *string++) || /* key */
!g_variant_type_string_scan (string, limit, &string) || /* value */
string == limit || *string++ != '}') /* } */
return FALSE;
break;
case 'm': case 'a':
return g_variant_type_string_scan (string, limit, endptr);
case 'b': case 'y': case 'n': case 'q': case 'i': case 'u':
case 'x': case 't': case 'd': case 's': case 'o': case 'g':
case 'v': case 'r': case '*': case '?': case 'h':
break;
default:
return FALSE;
}
if (endptr != NULL)
*endptr = string;
return TRUE;
}
/**
* g_variant_type_string_is_valid:
* @type_string: a pointer to any string
*
* Checks if @type_string is a valid GVariant type string. This call is
* equivalent to calling g_variant_type_string_scan() and confirming
* that the following character is a nul terminator.
*
* Returns: %TRUE if @type_string is exactly one valid type string
*
* Since 2.24
**/
gboolean
g_variant_type_string_is_valid (const gchar *type_string)
{
const gchar *endptr;
g_return_val_if_fail (type_string != NULL, FALSE);
if (!g_variant_type_string_scan (type_string, NULL, &endptr))
return FALSE;
return *endptr == '\0';
}
/**
* g_variant_type_free:
* @type: (allow-none): a #GVariantType, or %NULL
*
* Frees a #GVariantType that was allocated with
* g_variant_type_copy(), g_variant_type_new() or one of the container
* type constructor functions.
*
* In the case that @type is %NULL, this function does nothing.
*
* Since 2.24
**/
void
g_variant_type_free (GVariantType *type)
{
g_return_if_fail (type == NULL || g_variant_type_check (type));
g_free (type);
}
/**
* g_variant_type_copy:
* @type: a #GVariantType
*
* Makes a copy of a #GVariantType. It is appropriate to call
* g_variant_type_free() on the return value. @type may not be %NULL.
*
* Returns: (transfer full): a new #GVariantType
*
* Since 2.24
**/
GVariantType *
g_variant_type_copy (const GVariantType *type)
{
gsize length;
gchar *new;
g_return_val_if_fail (g_variant_type_check (type), NULL);
length = g_variant_type_get_string_length (type);
new = g_malloc (length + 1);
memcpy (new, type, length);
new[length] = '\0';
return (GVariantType *) new;
}
/**
* g_variant_type_new:
* @type_string: a valid GVariant type string
*
* Creates a new #GVariantType corresponding to the type string given
* by @type_string. It is appropriate to call g_variant_type_free() on
* the return value.
*
* It is a programmer error to call this function with an invalid type
* string. Use g_variant_type_string_is_valid() if you are unsure.
*
* Returns: (transfer full): a new #GVariantType
*
* Since: 2.24
*/
GVariantType *
g_variant_type_new (const gchar *type_string)
{
g_return_val_if_fail (type_string != NULL, NULL);
return g_variant_type_copy (G_VARIANT_TYPE (type_string));
}
/**
* g_variant_type_get_string_length:
* @type: a #GVariantType
*
* Returns the length of the type string corresponding to the given
* @type. This function must be used to determine the valid extent of
* the memory region returned by g_variant_type_peek_string().
*
* Returns: the length of the corresponding type string
*
* Since 2.24
**/
gsize
g_variant_type_get_string_length (const GVariantType *type)
{
const gchar *type_string = (const gchar *) type;
gint brackets = 0;
gsize index = 0;
g_return_val_if_fail (g_variant_type_check (type), 0);
do
{
while (type_string[index] == 'a' || type_string[index] == 'm')
index++;
if (type_string[index] == '(' || type_string[index] == '{')
brackets++;
else if (type_string[index] == ')' || type_string[index] == '}')
brackets--;
index++;
}
while (brackets);
return index;
}
/*
This function is not introspectable, it returns something that
is not an array and neither a string
*/
/**
* g_variant_type_peek_string: (skip)
* @type: a #GVariantType
*
* Returns the type string corresponding to the given @type. The
* result is not nul-terminated; in order to determine its length you
* must call g_variant_type_get_string_length().
*
* To get a nul-terminated string, see g_variant_type_dup_string().
*
* Returns: the corresponding type string (not nul-terminated)
*
* Since 2.24
**/
const gchar *
g_variant_type_peek_string (const GVariantType *type)
{
g_return_val_if_fail (g_variant_type_check (type), NULL);
return (const gchar *) type;
}
/**
* g_variant_type_dup_string:
* @type: a #GVariantType
*
* Returns a newly-allocated copy of the type string corresponding to
* @type. The returned string is nul-terminated. It is appropriate to
* call g_free() on the return value.
*
* Returns: (transfer full): the corresponding type string
*
* Since 2.24
**/
gchar *
g_variant_type_dup_string (const GVariantType *type)
{
g_return_val_if_fail (g_variant_type_check (type), NULL);
return g_strndup (g_variant_type_peek_string (type),
g_variant_type_get_string_length (type));
}
/**
* g_variant_type_is_definite:
* @type: a #GVariantType
*
* Determines if the given @type is definite (ie: not indefinite).
*
* A type is definite if its type string does not contain any indefinite
* type characters ('*', '?', or 'r').
*
* A #GVariant instance may not have an indefinite type, so calling
* this function on the result of g_variant_get_type() will always
* result in %TRUE being returned. Calling this function on an
* indefinite type like %G_VARIANT_TYPE_ARRAY, however, will result in
* %FALSE being returned.
*
* Returns: %TRUE if @type is definite
*
* Since 2.24
**/
gboolean
g_variant_type_is_definite (const GVariantType *type)
{
const gchar *type_string;
gsize type_length;
gsize i;
g_return_val_if_fail (g_variant_type_check (type), FALSE);
type_length = g_variant_type_get_string_length (type);
type_string = g_variant_type_peek_string (type);
for (i = 0; i < type_length; i++)
if (type_string[i] == '*' ||
type_string[i] == '?' ||
type_string[i] == 'r')
return FALSE;
return TRUE;
}
/**
* g_variant_type_is_container:
* @type: a #GVariantType
*
* Determines if the given @type is a container type.
*
* Container types are any array, maybe, tuple, or dictionary
* entry types plus the variant type.
*
* This function returns %TRUE for any indefinite type for which every
* definite subtype is a container -- %G_VARIANT_TYPE_ARRAY, for
* example.
*
* Returns: %TRUE if @type is a container type
*
* Since 2.24
**/
gboolean
g_variant_type_is_container (const GVariantType *type)
{
gchar first_char;
g_return_val_if_fail (g_variant_type_check (type), FALSE);
first_char = g_variant_type_peek_string (type)[0];
switch (first_char)
{
case 'a':
case 'm':
case 'r':
case '(':
case '{':
case 'v':
return TRUE;
default:
return FALSE;
}
}
/**
* g_variant_type_is_basic:
* @type: a #GVariantType
*
* Determines if the given @type is a basic type.
*
* Basic types are booleans, bytes, integers, doubles, strings, object
* paths and signatures.
*
* Only a basic type may be used as the key of a dictionary entry.
*
* This function returns %FALSE for all indefinite types except
* %G_VARIANT_TYPE_BASIC.
*
* Returns: %TRUE if @type is a basic type
*
* Since 2.24
**/
gboolean
g_variant_type_is_basic (const GVariantType *type)
{
gchar first_char;
g_return_val_if_fail (g_variant_type_check (type), FALSE);
first_char = g_variant_type_peek_string (type)[0];
switch (first_char)
{
case 'b':
case 'y':
case 'n':
case 'q':
case 'i':
case 'h':
case 'u':
case 't':
case 'x':
case 'd':
case 's':
case 'o':
case 'g':
case '?':
return TRUE;
default:
return FALSE;
}
}
/**
* g_variant_type_is_maybe:
* @type: a #GVariantType
*
* Determines if the given @type is a maybe type. This is true if the
* type string for @type starts with an 'm'.
*
* This function returns %TRUE for any indefinite type for which every
* definite subtype is a maybe type -- %G_VARIANT_TYPE_MAYBE, for
* example.
*
* Returns: %TRUE if @type is a maybe type
*
* Since 2.24
**/
gboolean
g_variant_type_is_maybe (const GVariantType *type)
{
g_return_val_if_fail (g_variant_type_check (type), FALSE);
return g_variant_type_peek_string (type)[0] == 'm';
}
/**
* g_variant_type_is_array:
* @type: a #GVariantType
*
* Determines if the given @type is an array type. This is true if the
* type string for @type starts with an 'a'.
*
* This function returns %TRUE for any indefinite type for which every
* definite subtype is an array type -- %G_VARIANT_TYPE_ARRAY, for
* example.
*
* Returns: %TRUE if @type is an array type
*
* Since 2.24
**/
gboolean
g_variant_type_is_array (const GVariantType *type)
{
g_return_val_if_fail (g_variant_type_check (type), FALSE);
return g_variant_type_peek_string (type)[0] == 'a';
}
/**
* g_variant_type_is_tuple:
* @type: a #GVariantType
*
* Determines if the given @type is a tuple type. This is true if the
* type string for @type starts with a '(' or if @type is
* %G_VARIANT_TYPE_TUPLE.
*
* This function returns %TRUE for any indefinite type for which every
* definite subtype is a tuple type -- %G_VARIANT_TYPE_TUPLE, for
* example.
*
* Returns: %TRUE if @type is a tuple type
*
* Since 2.24
**/
gboolean
g_variant_type_is_tuple (const GVariantType *type)
{
gchar type_char;
g_return_val_if_fail (g_variant_type_check (type), FALSE);
type_char = g_variant_type_peek_string (type)[0];
return type_char == 'r' || type_char == '(';
}
/**
* g_variant_type_is_dict_entry:
* @type: a #GVariantType
*
* Determines if the given @type is a dictionary entry type. This is
* true if the type string for @type starts with a '{'.
*
* This function returns %TRUE for any indefinite type for which every
* definite subtype is a dictionary entry type --
* %G_VARIANT_TYPE_DICT_ENTRY, for example.
*
* Returns: %TRUE if @type is a dictionary entry type
*
* Since 2.24
**/
gboolean
g_variant_type_is_dict_entry (const GVariantType *type)
{
g_return_val_if_fail (g_variant_type_check (type), FALSE);
return g_variant_type_peek_string (type)[0] == '{';
}
/**
* g_variant_type_is_variant:
* @type: a #GVariantType
*
* Determines if the given @type is the variant type.
*
* Returns: %TRUE if @type is the variant type
*
* Since 2.24
**/
gboolean
g_variant_type_is_variant (const GVariantType *type)
{
g_return_val_if_fail (g_variant_type_check (type), FALSE);
return g_variant_type_peek_string (type)[0] == 'v';
}
/**
* g_variant_type_hash:
* @type: (type GVariantType): a #GVariantType
*
* Hashes @type.
*
* The argument type of @type is only #gconstpointer to allow use with
* #GHashTable without function pointer casting. A valid
* #GVariantType must be provided.
*
* Returns: the hash value
*
* Since 2.24
**/
guint
g_variant_type_hash (gconstpointer type)
{
const gchar *type_string;
guint value = 0;
gsize length;
gsize i;
g_return_val_if_fail (g_variant_type_check (type), 0);
type_string = g_variant_type_peek_string (type);
length = g_variant_type_get_string_length (type);
for (i = 0; i < length; i++)
value = (value << 5) - value + type_string[i];
return value;
}
/**
* g_variant_type_equal:
* @type1: (type GVariantType): a #GVariantType
* @type2: (type GVariantType): a #GVariantType
*
* Compares @type1 and @type2 for equality.
*
* Only returns %TRUE if the types are exactly equal. Even if one type
* is an indefinite type and the other is a subtype of it, %FALSE will
* be returned if they are not exactly equal. If you want to check for
* subtypes, use g_variant_type_is_subtype_of().
*
* The argument types of @type1 and @type2 are only #gconstpointer to
* allow use with #GHashTable without function pointer casting. For
* both arguments, a valid #GVariantType must be provided.
*
* Returns: %TRUE if @type1 and @type2 are exactly equal
*
* Since 2.24
**/
gboolean
g_variant_type_equal (gconstpointer type1,
gconstpointer type2)
{
const gchar *string1, *string2;
gsize size1, size2;
g_return_val_if_fail (g_variant_type_check (type1), FALSE);
g_return_val_if_fail (g_variant_type_check (type2), FALSE);
if (type1 == type2)
return TRUE;
size1 = g_variant_type_get_string_length (type1);
size2 = g_variant_type_get_string_length (type2);
if (size1 != size2)
return FALSE;
string1 = g_variant_type_peek_string (type1);
string2 = g_variant_type_peek_string (type2);
return memcmp (string1, string2, size1) == 0;
}
/**
* g_variant_type_is_subtype_of:
* @type: a #GVariantType
* @supertype: a #GVariantType
*
* Checks if @type is a subtype of @supertype.
*
* This function returns %TRUE if @type is a subtype of @supertype. All
* types are considered to be subtypes of themselves. Aside from that,
* only indefinite types can have subtypes.
*
* Returns: %TRUE if @type is a subtype of @supertype
*
* Since 2.24
**/
gboolean
g_variant_type_is_subtype_of (const GVariantType *type,
const GVariantType *supertype)
{
const gchar *supertype_string;
const gchar *supertype_end;
const gchar *type_string;
g_return_val_if_fail (g_variant_type_check (type), FALSE);
g_return_val_if_fail (g_variant_type_check (supertype), FALSE);
supertype_string = g_variant_type_peek_string (supertype);
type_string = g_variant_type_peek_string (type);
supertype_end = supertype_string +
g_variant_type_get_string_length (supertype);
/* we know that type and supertype are both well-formed, so it's
* safe to treat this merely as a text processing problem.
*/
while (supertype_string < supertype_end)
{
char supertype_char = *supertype_string++;
if (supertype_char == *type_string)
type_string++;
else if (*type_string == ')')
return FALSE;
else
{
const GVariantType *target_type = (GVariantType *) type_string;
switch (supertype_char)
{
case 'r':
if (!g_variant_type_is_tuple (target_type))
return FALSE;
break;
case '*':
break;
case '?':
if (!g_variant_type_is_basic (target_type))
return FALSE;
break;
default:
return FALSE;
}
type_string += g_variant_type_get_string_length (target_type);
}
}
return TRUE;
}
/**
* g_variant_type_element:
* @type: an array or maybe #GVariantType
*
* Determines the element type of an array or maybe type.
*
* This function may only be used with array or maybe types.
*
* Returns: (transfer none): the element type of @type
*
* Since 2.24
**/
const GVariantType *
g_variant_type_element (const GVariantType *type)
{
const gchar *type_string;
g_return_val_if_fail (g_variant_type_check (type), NULL);
type_string = g_variant_type_peek_string (type);
g_assert (type_string[0] == 'a' || type_string[0] == 'm');
return (const GVariantType *) &type_string[1];
}
/**
* g_variant_type_first:
* @type: a tuple or dictionary entry #GVariantType
*
* Determines the first item type of a tuple or dictionary entry
* type.
*
* This function may only be used with tuple or dictionary entry types,
* but must not be used with the generic tuple type
* %G_VARIANT_TYPE_TUPLE.
*
* In the case of a dictionary entry type, this returns the type of
* the key.
*
* %NULL is returned in case of @type being %G_VARIANT_TYPE_UNIT.
*
* This call, together with g_variant_type_next() provides an iterator
* interface over tuple and dictionary entry types.
*
* Returns: (transfer none): the first item type of @type, or %NULL
*
* Since 2.24
**/
const GVariantType *
g_variant_type_first (const GVariantType *type)
{
const gchar *type_string;
g_return_val_if_fail (g_variant_type_check (type), NULL);
type_string = g_variant_type_peek_string (type);
g_assert (type_string[0] == '(' || type_string[0] == '{');
if (type_string[1] == ')')
return NULL;
return (const GVariantType *) &type_string[1];
}
/**
* g_variant_type_next:
* @type: a #GVariantType from a previous call
*
* Determines the next item type of a tuple or dictionary entry
* type.
*
* @type must be the result of a previous call to
* g_variant_type_first() or g_variant_type_next().
*
* If called on the key type of a dictionary entry then this call
* returns the value type. If called on the value type of a dictionary
* entry then this call returns %NULL.
*
* For tuples, %NULL is returned when @type is the last item in a tuple.
*
* Returns: (transfer none): the next #GVariantType after @type, or %NULL
*
* Since 2.24
**/
const GVariantType *
g_variant_type_next (const GVariantType *type)
{
const gchar *type_string;
g_return_val_if_fail (g_variant_type_check (type), NULL);
type_string = g_variant_type_peek_string (type);
type_string += g_variant_type_get_string_length (type);
if (*type_string == ')' || *type_string == '}')
return NULL;
return (const GVariantType *) type_string;
}
/**
* g_variant_type_n_items:
* @type: a tuple or dictionary entry #GVariantType
*
* Determines the number of items contained in a tuple or
* dictionary entry type.
*
* This function may only be used with tuple or dictionary entry types,
* but must not be used with the generic tuple type
* %G_VARIANT_TYPE_TUPLE.
*
* In the case of a dictionary entry type, this function will always
* return 2.
*
* Returns: the number of items in @type
*
* Since 2.24
**/
gsize
g_variant_type_n_items (const GVariantType *type)
{
gsize count = 0;
g_return_val_if_fail (g_variant_type_check (type), 0);
for (type = g_variant_type_first (type);
type;
type = g_variant_type_next (type))
count++;
return count;
}
/**
* g_variant_type_key:
* @type: a dictionary entry #GVariantType
*
* Determines the key type of a dictionary entry type.
*
* This function may only be used with a dictionary entry type. Other
* than the additional restriction, this call is equivalent to
* g_variant_type_first().
*
* Returns: (transfer none): the key type of the dictionary entry
*
* Since 2.24
**/
const GVariantType *
g_variant_type_key (const GVariantType *type)
{
const gchar *type_string;
g_return_val_if_fail (g_variant_type_check (type), NULL);
type_string = g_variant_type_peek_string (type);
g_assert (type_string[0] == '{');
return (const GVariantType *) &type_string[1];
}
/**
* g_variant_type_value:
* @type: a dictionary entry #GVariantType
*
* Determines the value type of a dictionary entry type.
*
* This function may only be used with a dictionary entry type.
*
* Returns: (transfer none): the value type of the dictionary entry
*
* Since 2.24
**/
const GVariantType *
g_variant_type_value (const GVariantType *type)
{
const gchar *type_string;
g_return_val_if_fail (g_variant_type_check (type), NULL);
type_string = g_variant_type_peek_string (type);
g_assert (type_string[0] == '{');
return g_variant_type_next (g_variant_type_key (type));
}
/**
* g_variant_type_new_tuple:
* @items: (array length=length): an array of #GVariantTypes, one for each item
* @length: the length of @items, or -1
*
* Constructs a new tuple type, from @items.
*
* @length is the number of items in @items, or -1 to indicate that
* @items is %NULL-terminated.
*
* It is appropriate to call g_variant_type_free() on the return value.
*
* Returns: (transfer full): a new tuple #GVariantType
*
* Since 2.24
**/
static GVariantType *
g_variant_type_new_tuple_slow (const GVariantType * const *items,
gint length)
{
/* the "slow" version is needed in case the static buffer of 1024
* bytes is exceeded when running the normal version. this will
* happen only in truly insane code, so it can be slow.
*/
GString *string;
gsize i;
string = g_string_new ("(");
for (i = 0; i < length; i++)
{
const GVariantType *type;
gsize size;
g_return_val_if_fail (g_variant_type_check (items[i]), NULL);
type = items[i];
size = g_variant_type_get_string_length (type);
g_string_append_len (string, (const gchar *) type, size);
}
g_string_append_c (string, ')');
return (GVariantType *) g_string_free (string, FALSE);
}
GVariantType *
g_variant_type_new_tuple (const GVariantType * const *items,
gint length)
{
char buffer[1024];
gsize offset;
gsize i;
g_return_val_if_fail (length == 0 || items != NULL, NULL);
if (length < 0)
for (length = 0; items[length] != NULL; length++);
offset = 0;
buffer[offset++] = '(';
for (i = 0; i < length; i++)
{
const GVariantType *type;
gsize size;
g_return_val_if_fail (g_variant_type_check (items[i]), NULL);
type = items[i];
size = g_variant_type_get_string_length (type);
if (offset + size >= sizeof buffer) /* leave room for ')' */
return g_variant_type_new_tuple_slow (items, length);
memcpy (&buffer[offset], type, size);
offset += size;
}
g_assert (offset < sizeof buffer);
buffer[offset++] = ')';
return (GVariantType *) g_memdup (buffer, offset);
}
/**
* g_variant_type_new_array: (constructor)
* @element: a #GVariantType
*
* Constructs the type corresponding to an array of elements of the
* type @type.
*
* It is appropriate to call g_variant_type_free() on the return value.
*
* Returns: (transfer full): a new array #GVariantType
*
* Since 2.24
**/
GVariantType *
g_variant_type_new_array (const GVariantType *element)
{
gsize size;
gchar *new;
g_return_val_if_fail (g_variant_type_check (element), NULL);
size = g_variant_type_get_string_length (element);
new = g_malloc (size + 1);
new[0] = 'a';
memcpy (new + 1, element, size);
return (GVariantType *) new;
}
/**
* g_variant_type_new_maybe: (constructor)
* @element: a #GVariantType
*
* Constructs the type corresponding to a maybe instance containing
* type @type or Nothing.
*
* It is appropriate to call g_variant_type_free() on the return value.
*
* Returns: (transfer full): a new maybe #GVariantType
*
* Since 2.24
**/
GVariantType *
g_variant_type_new_maybe (const GVariantType *element)
{
gsize size;
gchar *new;
g_return_val_if_fail (g_variant_type_check (element), NULL);
size = g_variant_type_get_string_length (element);
new = g_malloc (size + 1);
new[0] = 'm';
memcpy (new + 1, element, size);
return (GVariantType *) new;
}
/**
* g_variant_type_new_dict_entry: (constructor)
* @key: a basic #GVariantType
* @value: a #GVariantType
*
* Constructs the type corresponding to a dictionary entry with a key
* of type @key and a value of type @value.
*
* It is appropriate to call g_variant_type_free() on the return value.
*
* Returns: (transfer full): a new dictionary entry #GVariantType
*
* Since 2.24
**/
GVariantType *
g_variant_type_new_dict_entry (const GVariantType *key,
const GVariantType *value)
{
gsize keysize, valsize;
gchar *new;
g_return_val_if_fail (g_variant_type_check (key), NULL);
g_return_val_if_fail (g_variant_type_check (value), NULL);
keysize = g_variant_type_get_string_length (key);
valsize = g_variant_type_get_string_length (value);
new = g_malloc (1 + keysize + valsize + 1);
new[0] = '{';
memcpy (new + 1, key, keysize);
memcpy (new + 1 + keysize, value, valsize);
new[1 + keysize + valsize] = '}';
return (GVariantType *) new;
}
/* private */
const GVariantType *
g_variant_type_checked_ (const gchar *type_string)
{
g_return_val_if_fail (g_variant_type_string_is_valid (type_string), NULL);
return (const GVariantType *) type_string;
}
pkg-config-0.29.1/glib/glib/genviron.h 0000664 0001750 0001750 00000005523 12651243552 014416 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __G_ENVIRON_H__
#define __G_ENVIRON_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
G_BEGIN_DECLS
GLIB_AVAILABLE_IN_ALL
const gchar * g_getenv (const gchar *variable);
GLIB_AVAILABLE_IN_ALL
gboolean g_setenv (const gchar *variable,
const gchar *value,
gboolean overwrite);
GLIB_AVAILABLE_IN_ALL
void g_unsetenv (const gchar *variable);
GLIB_AVAILABLE_IN_ALL
gchar ** g_listenv (void);
GLIB_AVAILABLE_IN_ALL
gchar ** g_get_environ (void);
GLIB_AVAILABLE_IN_ALL
const gchar * g_environ_getenv (gchar **envp,
const gchar *variable);
GLIB_AVAILABLE_IN_ALL
gchar ** g_environ_setenv (gchar **envp,
const gchar *variable,
const gchar *value,
gboolean overwrite) G_GNUC_WARN_UNUSED_RESULT;
GLIB_AVAILABLE_IN_ALL
gchar ** g_environ_unsetenv (gchar **envp,
const gchar *variable) G_GNUC_WARN_UNUSED_RESULT;
#ifdef G_OS_WIN32
#define g_getenv g_getenv_utf8
#define g_setenv g_setenv_utf8
#define g_unsetenv g_unsetenv_utf8
GLIB_AVAILABLE_IN_ALL
const gchar *g_getenv_utf8 (const gchar *variable);
GLIB_AVAILABLE_IN_ALL
gboolean g_setenv_utf8 (const gchar *variable,
const gchar *value,
gboolean overwrite);
GLIB_AVAILABLE_IN_ALL
void g_unsetenv_utf8 (const gchar *variable);
#endif
G_END_DECLS
#endif /* __G_ENVIRON_H__ */
pkg-config-0.29.1/glib/glib/gbase64.c 0000664 0001750 0001750 00000033501 12651243552 014012 0000000 0000000 /* gbase64.c - Base64 encoding/decoding
*
* Copyright (C) 2006 Alexander Larsson
* Copyright (C) 2000-2003 Ximian 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; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* This is based on code in camel, written by:
* Michael Zucchi
* Jeffrey Stedfast
*/
#include "config.h"
#include
#include "gbase64.h"
#include "gtestutils.h"
#include "glibintl.h"
/**
* SECTION:base64
* @title: Base64 Encoding
* @short_description: encodes and decodes data in Base64 format
*
* Base64 is an encoding that allows a sequence of arbitrary bytes to be
* encoded as a sequence of printable ASCII characters. For the definition
* of Base64, see RFC
* 1421 or RFC
* 2045. Base64 is most commonly used as a MIME transfer encoding
* for email.
*
* GLib supports incremental encoding using g_base64_encode_step() and
* g_base64_encode_close(). Incremental decoding can be done with
* g_base64_decode_step(). To encode or decode data in one go, use
* g_base64_encode() or g_base64_decode(). To avoid memory allocation when
* decoding, you can use g_base64_decode_inplace().
*
* Support for Base64 encoding has been added in GLib 2.12.
*/
static const char base64_alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/**
* g_base64_encode_step:
* @in: (array length=len) (element-type guint8): the binary data to encode
* @len: the length of @in
* @break_lines: whether to break long lines
* @out: (out) (array) (element-type guint8): pointer to destination buffer
* @state: (inout): Saved state between steps, initialize to 0
* @save: (inout): Saved state between steps, initialize to 0
*
* Incrementally encode a sequence of binary data into its Base-64 stringified
* representation. By calling this function multiple times you can convert
* data in chunks to avoid having to have the full encoded data in memory.
*
* When all of the data has been converted you must call
* g_base64_encode_close() to flush the saved state.
*
* The output buffer must be large enough to fit all the data that will
* be written to it. Due to the way base64 encodes you will need
* at least: (@len / 3 + 1) * 4 + 4 bytes (+ 4 may be needed in case of
* non-zero state). If you enable line-breaking you will need at least:
* ((@len / 3 + 1) * 4 + 4) / 72 + 1 bytes of extra space.
*
* @break_lines is typically used when putting base64-encoded data in emails.
* It breaks the lines at 72 columns instead of putting all of the text on
* the same line. This avoids problems with long lines in the email system.
* Note however that it breaks the lines with LF
* characters, not CR LF sequences, so the result cannot
* be passed directly to SMTP or certain other protocols.
*
* Return value: The number of bytes of output that was written
*
* Since: 2.12
*/
gsize
g_base64_encode_step (const guchar *in,
gsize len,
gboolean break_lines,
gchar *out,
gint *state,
gint *save)
{
char *outptr;
const guchar *inptr;
g_return_val_if_fail (in != NULL, 0);
g_return_val_if_fail (out != NULL, 0);
g_return_val_if_fail (state != NULL, 0);
g_return_val_if_fail (save != NULL, 0);
if (len <= 0)
return 0;
inptr = in;
outptr = out;
if (len + ((char *) save) [0] > 2)
{
const guchar *inend = in+len-2;
int c1, c2, c3;
int already;
already = *state;
switch (((char *) save) [0])
{
case 1:
c1 = ((unsigned char *) save) [1];
goto skip1;
case 2:
c1 = ((unsigned char *) save) [1];
c2 = ((unsigned char *) save) [2];
goto skip2;
}
/*
* yes, we jump into the loop, no i'm not going to change it,
* it's beautiful!
*/
while (inptr < inend)
{
c1 = *inptr++;
skip1:
c2 = *inptr++;
skip2:
c3 = *inptr++;
*outptr++ = base64_alphabet [ c1 >> 2 ];
*outptr++ = base64_alphabet [ c2 >> 4 |
((c1&0x3) << 4) ];
*outptr++ = base64_alphabet [ ((c2 &0x0f) << 2) |
(c3 >> 6) ];
*outptr++ = base64_alphabet [ c3 & 0x3f ];
/* this is a bit ugly ... */
if (break_lines && (++already) >= 19)
{
*outptr++ = '\n';
already = 0;
}
}
((char *)save)[0] = 0;
len = 2 - (inptr - inend);
*state = already;
}
if (len>0)
{
char *saveout;
/* points to the slot for the next char to save */
saveout = & (((char *)save)[1]) + ((char *)save)[0];
/* len can only be 0 1 or 2 */
switch(len)
{
case 2: *saveout++ = *inptr++;
case 1: *saveout++ = *inptr++;
}
((char *)save)[0] += len;
}
return outptr - out;
}
/**
* g_base64_encode_close:
* @break_lines: whether to break long lines
* @out: (out) (array) (element-type guint8): pointer to destination buffer
* @state: (inout): Saved state from g_base64_encode_step()
* @save: (inout): Saved state from g_base64_encode_step()
*
* Flush the status from a sequence of calls to g_base64_encode_step().
*
* The output buffer must be large enough to fit all the data that will
* be written to it. It will need up to 4 bytes, or up to 5 bytes if
* line-breaking is enabled.
*
* Return value: The number of bytes of output that was written
*
* Since: 2.12
*/
gsize
g_base64_encode_close (gboolean break_lines,
gchar *out,
gint *state,
gint *save)
{
int c1, c2;
char *outptr = out;
g_return_val_if_fail (out != NULL, 0);
g_return_val_if_fail (state != NULL, 0);
g_return_val_if_fail (save != NULL, 0);
c1 = ((unsigned char *) save) [1];
c2 = ((unsigned char *) save) [2];
switch (((char *) save) [0])
{
case 2:
outptr [2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
g_assert (outptr [2] != 0);
goto skip;
case 1:
outptr[2] = '=';
skip:
outptr [0] = base64_alphabet [ c1 >> 2 ];
outptr [1] = base64_alphabet [ c2 >> 4 | ( (c1&0x3) << 4 )];
outptr [3] = '=';
outptr += 4;
break;
}
if (break_lines)
*outptr++ = '\n';
*save = 0;
*state = 0;
return outptr - out;
}
/**
* g_base64_encode:
* @data: (array length=len) (element-type guint8): the binary data to encode
* @len: the length of @data
*
* Encode a sequence of binary data into its Base-64 stringified
* representation.
*
* Return value: (transfer full): a newly allocated, zero-terminated Base-64
* encoded string representing @data. The returned string must
* be freed with g_free().
*
* Since: 2.12
*/
gchar *
g_base64_encode (const guchar *data,
gsize len)
{
gchar *out;
gint state = 0, outlen;
gint save = 0;
g_return_val_if_fail (data != NULL || len == 0, NULL);
/* We can use a smaller limit here, since we know the saved state is 0,
+1 is needed for trailing \0, also check for unlikely integer overflow */
if (len >= ((G_MAXSIZE - 1) / 4 - 1) * 3)
g_error("%s: input too large for Base64 encoding (%"G_GSIZE_FORMAT" chars)",
G_STRLOC, len);
out = g_malloc ((len / 3 + 1) * 4 + 1);
outlen = g_base64_encode_step (data, len, FALSE, out, &state, &save);
outlen += g_base64_encode_close (FALSE, out + outlen, &state, &save);
out[outlen] = '\0';
return (gchar *) out;
}
static const unsigned char mime_base64_rank[256] = {
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
};
/**
* g_base64_decode_step:
* @in: (array length=len) (element-type guint8): binary input data
* @len: max length of @in data to decode
* @out: (out) (array) (element-type guint8): output buffer
* @state: (inout): Saved state between steps, initialize to 0
* @save: (inout): Saved state between steps, initialize to 0
*
* Incrementally decode a sequence of binary data from its Base-64 stringified
* representation. By calling this function multiple times you can convert
* data in chunks to avoid having to have the full encoded data in memory.
*
* The output buffer must be large enough to fit all the data that will
* be written to it. Since base64 encodes 3 bytes in 4 chars you need
* at least: (@len / 4) * 3 + 3 bytes (+ 3 may be needed in case of non-zero
* state).
*
* Return value: The number of bytes of output that was written
*
* Since: 2.12
**/
gsize
g_base64_decode_step (const gchar *in,
gsize len,
guchar *out,
gint *state,
guint *save)
{
const guchar *inptr;
guchar *outptr;
const guchar *inend;
guchar c, rank;
guchar last[2];
unsigned int v;
int i;
g_return_val_if_fail (in != NULL, 0);
g_return_val_if_fail (out != NULL, 0);
g_return_val_if_fail (state != NULL, 0);
g_return_val_if_fail (save != NULL, 0);
if (len <= 0)
return 0;
inend = (const guchar *)in+len;
outptr = out;
/* convert 4 base64 bytes to 3 normal bytes */
v=*save;
i=*state;
last[0] = last[1] = 0;
/* we use the sign in the state to determine if we got a padding character
in the previous sequence */
if (i < 0)
{
i = -i;
last[0] = '=';
}
inptr = (const guchar *)in;
while (inptr < inend)
{
c = *inptr++;
rank = mime_base64_rank [c];
if (rank != 0xff)
{
last[1] = last[0];
last[0] = c;
v = (v<<6) | rank;
i++;
if (i==4)
{
*outptr++ = v>>16;
if (last[1] != '=')
*outptr++ = v>>8;
if (last[0] != '=')
*outptr++ = v;
i=0;
}
}
}
*save = v;
*state = last[0] == '=' ? -i : i;
return outptr - out;
}
/**
* g_base64_decode:
* @text: zero-terminated string with base64 text to decode
* @out_len: (out): The length of the decoded data is written here
*
* Decode a sequence of Base-64 encoded text into binary data. Note
* that the returned binary data is not necessarily zero-terminated,
* so it should not be used as a character string.
*
* Return value: (transfer full) (array length=out_len) (element-type guint8):
* newly allocated buffer containing the binary data
* that @text represents. The returned buffer must
* be freed with g_free().
*
* Since: 2.12
*/
guchar *
g_base64_decode (const gchar *text,
gsize *out_len)
{
guchar *ret;
gsize input_length;
gint state = 0;
guint save = 0;
g_return_val_if_fail (text != NULL, NULL);
g_return_val_if_fail (out_len != NULL, NULL);
input_length = strlen (text);
/* We can use a smaller limit here, since we know the saved state is 0,
+1 used to avoid calling g_malloc0(0), and hence returning NULL */
ret = g_malloc0 ((input_length / 4) * 3 + 1);
*out_len = g_base64_decode_step (text, input_length, ret, &state, &save);
return ret;
}
/**
* g_base64_decode_inplace:
* @text: (inout) (array length=out_len) (element-type guint8): zero-terminated
* string with base64 text to decode
* @out_len: (inout): The length of the decoded data is written here
*
* Decode a sequence of Base-64 encoded text into binary data
* by overwriting the input data.
*
* Return value: (transfer none): The binary data that @text responds. This pointer
* is the same as the input @text.
*
* Since: 2.20
*/
guchar *
g_base64_decode_inplace (gchar *text,
gsize *out_len)
{
gint input_length, state = 0;
guint save = 0;
g_return_val_if_fail (text != NULL, NULL);
g_return_val_if_fail (out_len != NULL, NULL);
input_length = strlen (text);
g_return_val_if_fail (input_length > 1, NULL);
*out_len = g_base64_decode_step (text, input_length, (guchar *) text, &state, &save);
return (guchar *) text;
}
pkg-config-0.29.1/glib/glib/gpattern.c 0000664 0001750 0001750 00000030272 12651243552 014405 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997, 1999 Peter Mattis, Red Hat, Inc.
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include
#include "gpattern.h"
#include "gmacros.h"
#include "gmessages.h"
#include "gmem.h"
#include "gunicode.h"
#include "gutils.h"
/**
* SECTION:patterns
* @title: Glob-style pattern matching
* @short_description: matches strings against patterns containing '*'
* (wildcard) and '?' (joker)
*
* The g_pattern_match* functions match a string
* against a pattern containing '*' and '?' wildcards with similar
* semantics as the standard glob() function: '*' matches an arbitrary,
* possibly empty, string, '?' matches an arbitrary character.
*
* Note that in contrast to glob(), the '/' character
* can be matched by the wildcards, there are no
* '[...]' character ranges and '*' and '?' can
* not be escaped to include them literally in a
* pattern.
*
* When multiple strings must be matched against the same pattern, it
* is better to compile the pattern to a #GPatternSpec using
* g_pattern_spec_new() and use g_pattern_match_string() instead of
* g_pattern_match_simple(). This avoids the overhead of repeated
* pattern compilation.
**/
/**
* GPatternSpec:
*
* A GPatternSpec is the 'compiled' form of a
* pattern. This structure is opaque and its fields cannot be accessed
* directly.
**/
/* keep enum and structure of gpattern.c and patterntest.c in sync */
typedef enum
{
G_MATCH_ALL, /* "*A?A*" */
G_MATCH_ALL_TAIL, /* "*A?AA" */
G_MATCH_HEAD, /* "AAAA*" */
G_MATCH_TAIL, /* "*AAAA" */
G_MATCH_EXACT, /* "AAAAA" */
G_MATCH_LAST
} GMatchType;
struct _GPatternSpec
{
GMatchType match_type;
guint pattern_length;
guint min_length;
guint max_length;
gchar *pattern;
};
/* --- functions --- */
static inline gboolean
g_pattern_ph_match (const gchar *match_pattern,
const gchar *match_string,
gboolean *wildcard_reached_p)
{
register const gchar *pattern, *string;
register gchar ch;
pattern = match_pattern;
string = match_string;
ch = *pattern;
pattern++;
while (ch)
{
switch (ch)
{
case '?':
if (!*string)
return FALSE;
string = g_utf8_next_char (string);
break;
case '*':
*wildcard_reached_p = TRUE;
do
{
ch = *pattern;
pattern++;
if (ch == '?')
{
if (!*string)
return FALSE;
string = g_utf8_next_char (string);
}
}
while (ch == '*' || ch == '?');
if (!ch)
return TRUE;
do
{
gboolean next_wildcard_reached = FALSE;
while (ch != *string)
{
if (!*string)
return FALSE;
string = g_utf8_next_char (string);
}
string++;
if (g_pattern_ph_match (pattern, string, &next_wildcard_reached))
return TRUE;
if (next_wildcard_reached)
/* the forthcoming pattern substring up to the next wildcard has
* been matched, but a mismatch occoured for the rest of the
* pattern, following the next wildcard.
* there's no need to advance the current match position any
* further if the rest pattern will not match.
*/
return FALSE;
}
while (*string);
break;
default:
if (ch == *string)
string++;
else
return FALSE;
break;
}
ch = *pattern;
pattern++;
}
return *string == 0;
}
/**
* g_pattern_match:
* @pspec: a #GPatternSpec
* @string_length: the length of @string (in bytes, i.e. strlen(),
* not g_utf8_strlen())
* @string: the UTF-8 encoded string to match
* @string_reversed: (allow-none): the reverse of @string or %NULL
*
* Matches a string against a compiled pattern. Passing the correct
* length of the string given is mandatory. The reversed string can be
* omitted by passing %NULL, this is more efficient if the reversed
* version of the string to be matched is not at hand, as
* g_pattern_match() will only construct it if the compiled pattern
* requires reverse matches.
*
* Note that, if the user code will (possibly) match a string against a
* multitude of patterns containing wildcards, chances are high that
* some patterns will require a reversed string. In this case, it's
* more efficient to provide the reversed string to avoid multiple
* constructions thereof in the various calls to g_pattern_match().
*
* Note also that the reverse of a UTF-8 encoded string can in general
* not be obtained by g_strreverse(). This works
* only if the string doesn't contain any multibyte characters. GLib
* offers the g_utf8_strreverse() function to reverse UTF-8 encoded
* strings.
*
* Returns: %TRUE if @string matches @pspec
**/
gboolean
g_pattern_match (GPatternSpec *pspec,
guint string_length,
const gchar *string,
const gchar *string_reversed)
{
g_return_val_if_fail (pspec != NULL, FALSE);
g_return_val_if_fail (string != NULL, FALSE);
if (string_length < pspec->min_length ||
string_length > pspec->max_length)
return FALSE;
switch (pspec->match_type)
{
gboolean dummy;
case G_MATCH_ALL:
return g_pattern_ph_match (pspec->pattern, string, &dummy);
case G_MATCH_ALL_TAIL:
if (string_reversed)
return g_pattern_ph_match (pspec->pattern, string_reversed, &dummy);
else
{
gboolean result;
gchar *tmp;
tmp = g_utf8_strreverse (string, string_length);
result = g_pattern_ph_match (pspec->pattern, tmp, &dummy);
g_free (tmp);
return result;
}
case G_MATCH_HEAD:
if (pspec->pattern_length == string_length)
return strcmp (pspec->pattern, string) == 0;
else if (pspec->pattern_length)
return strncmp (pspec->pattern, string, pspec->pattern_length) == 0;
else
return TRUE;
case G_MATCH_TAIL:
if (pspec->pattern_length)
return strcmp (pspec->pattern, string + (string_length - pspec->pattern_length)) == 0;
else
return TRUE;
case G_MATCH_EXACT:
if (pspec->pattern_length != string_length)
return FALSE;
else
return strcmp (pspec->pattern, string) == 0;
default:
g_return_val_if_fail (pspec->match_type < G_MATCH_LAST, FALSE);
return FALSE;
}
}
/**
* g_pattern_spec_new:
* @pattern: a zero-terminated UTF-8 encoded string
*
* Compiles a pattern to a #GPatternSpec.
*
* Returns: a newly-allocated #GPatternSpec
**/
GPatternSpec*
g_pattern_spec_new (const gchar *pattern)
{
GPatternSpec *pspec;
gboolean seen_joker = FALSE, seen_wildcard = FALSE, more_wildcards = FALSE;
gint hw_pos = -1, tw_pos = -1, hj_pos = -1, tj_pos = -1;
gboolean follows_wildcard = FALSE;
guint pending_jokers = 0;
const gchar *s;
gchar *d;
guint i;
g_return_val_if_fail (pattern != NULL, NULL);
/* canonicalize pattern and collect necessary stats */
pspec = g_new (GPatternSpec, 1);
pspec->pattern_length = strlen (pattern);
pspec->min_length = 0;
pspec->max_length = 0;
pspec->pattern = g_new (gchar, pspec->pattern_length + 1);
d = pspec->pattern;
for (i = 0, s = pattern; *s != 0; s++)
{
switch (*s)
{
case '*':
if (follows_wildcard) /* compress multiple wildcards */
{
pspec->pattern_length--;
continue;
}
follows_wildcard = TRUE;
if (hw_pos < 0)
hw_pos = i;
tw_pos = i;
break;
case '?':
pending_jokers++;
pspec->min_length++;
pspec->max_length += 4; /* maximum UTF-8 character length */
continue;
default:
for (; pending_jokers; pending_jokers--, i++) {
*d++ = '?';
if (hj_pos < 0)
hj_pos = i;
tj_pos = i;
}
follows_wildcard = FALSE;
pspec->min_length++;
pspec->max_length++;
break;
}
*d++ = *s;
i++;
}
for (; pending_jokers; pending_jokers--) {
*d++ = '?';
if (hj_pos < 0)
hj_pos = i;
tj_pos = i;
}
*d++ = 0;
seen_joker = hj_pos >= 0;
seen_wildcard = hw_pos >= 0;
more_wildcards = seen_wildcard && hw_pos != tw_pos;
if (seen_wildcard)
pspec->max_length = G_MAXUINT;
/* special case sole head/tail wildcard or exact matches */
if (!seen_joker && !more_wildcards)
{
if (pspec->pattern[0] == '*')
{
pspec->match_type = G_MATCH_TAIL;
memmove (pspec->pattern, pspec->pattern + 1, --pspec->pattern_length);
pspec->pattern[pspec->pattern_length] = 0;
return pspec;
}
if (pspec->pattern_length > 0 &&
pspec->pattern[pspec->pattern_length - 1] == '*')
{
pspec->match_type = G_MATCH_HEAD;
pspec->pattern[--pspec->pattern_length] = 0;
return pspec;
}
if (!seen_wildcard)
{
pspec->match_type = G_MATCH_EXACT;
return pspec;
}
}
/* now just need to distinguish between head or tail match start */
tw_pos = pspec->pattern_length - 1 - tw_pos; /* last pos to tail distance */
tj_pos = pspec->pattern_length - 1 - tj_pos; /* last pos to tail distance */
if (seen_wildcard)
pspec->match_type = tw_pos > hw_pos ? G_MATCH_ALL_TAIL : G_MATCH_ALL;
else /* seen_joker */
pspec->match_type = tj_pos > hj_pos ? G_MATCH_ALL_TAIL : G_MATCH_ALL;
if (pspec->match_type == G_MATCH_ALL_TAIL) {
gchar *tmp = pspec->pattern;
pspec->pattern = g_utf8_strreverse (pspec->pattern, pspec->pattern_length);
g_free (tmp);
}
return pspec;
}
/**
* g_pattern_spec_free:
* @pspec: a #GPatternSpec
*
* Frees the memory allocated for the #GPatternSpec.
**/
void
g_pattern_spec_free (GPatternSpec *pspec)
{
g_return_if_fail (pspec != NULL);
g_free (pspec->pattern);
g_free (pspec);
}
/**
* g_pattern_spec_equal:
* @pspec1: a #GPatternSpec
* @pspec2: another #GPatternSpec
*
* Compares two compiled pattern specs and returns whether they will
* match the same set of strings.
*
* Returns: Whether the compiled patterns are equal
**/
gboolean
g_pattern_spec_equal (GPatternSpec *pspec1,
GPatternSpec *pspec2)
{
g_return_val_if_fail (pspec1 != NULL, FALSE);
g_return_val_if_fail (pspec2 != NULL, FALSE);
return (pspec1->pattern_length == pspec2->pattern_length &&
pspec1->match_type == pspec2->match_type &&
strcmp (pspec1->pattern, pspec2->pattern) == 0);
}
/**
* g_pattern_match_string:
* @pspec: a #GPatternSpec
* @string: the UTF-8 encoded string to match
*
* Matches a string against a compiled pattern. If the string is to be
* matched against more than one pattern, consider using
* g_pattern_match() instead while supplying the reversed string.
*
* Returns: %TRUE if @string matches @pspec
**/
gboolean
g_pattern_match_string (GPatternSpec *pspec,
const gchar *string)
{
g_return_val_if_fail (pspec != NULL, FALSE);
g_return_val_if_fail (string != NULL, FALSE);
return g_pattern_match (pspec, strlen (string), string, NULL);
}
/**
* g_pattern_match_simple:
* @pattern: the UTF-8 encoded pattern
* @string: the UTF-8 encoded string to match
*
* Matches a string against a pattern given as a string. If this
* function is to be called in a loop, it's more efficient to compile
* the pattern once with g_pattern_spec_new() and call
* g_pattern_match_string() repeatedly.
*
* Returns: %TRUE if @string matches @pspec
**/
gboolean
g_pattern_match_simple (const gchar *pattern,
const gchar *string)
{
GPatternSpec *pspec;
gboolean ergo;
g_return_val_if_fail (pattern != NULL, FALSE);
g_return_val_if_fail (string != NULL, FALSE);
pspec = g_pattern_spec_new (pattern);
ergo = g_pattern_match (pspec, strlen (string), string, NULL);
g_pattern_spec_free (pspec);
return ergo;
}
pkg-config-0.29.1/glib/glib/giochannel.h 0000664 0001750 0001750 00000033756 12651243552 014707 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __G_IOCHANNEL_H__
#define __G_IOCHANNEL_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
#include
#include
G_BEGIN_DECLS
/* GIOChannel
*/
typedef struct _GIOChannel GIOChannel;
typedef struct _GIOFuncs GIOFuncs;
typedef enum
{
G_IO_ERROR_NONE,
G_IO_ERROR_AGAIN,
G_IO_ERROR_INVAL,
G_IO_ERROR_UNKNOWN
} GIOError;
#define G_IO_CHANNEL_ERROR g_io_channel_error_quark()
typedef enum
{
/* Derived from errno */
G_IO_CHANNEL_ERROR_FBIG,
G_IO_CHANNEL_ERROR_INVAL,
G_IO_CHANNEL_ERROR_IO,
G_IO_CHANNEL_ERROR_ISDIR,
G_IO_CHANNEL_ERROR_NOSPC,
G_IO_CHANNEL_ERROR_NXIO,
G_IO_CHANNEL_ERROR_OVERFLOW,
G_IO_CHANNEL_ERROR_PIPE,
/* Other */
G_IO_CHANNEL_ERROR_FAILED
} GIOChannelError;
typedef enum
{
G_IO_STATUS_ERROR,
G_IO_STATUS_NORMAL,
G_IO_STATUS_EOF,
G_IO_STATUS_AGAIN
} GIOStatus;
typedef enum
{
G_SEEK_CUR,
G_SEEK_SET,
G_SEEK_END
} GSeekType;
typedef enum
{
G_IO_FLAG_APPEND = 1 << 0,
G_IO_FLAG_NONBLOCK = 1 << 1,
G_IO_FLAG_IS_READABLE = 1 << 2, /* Read only flag */
G_IO_FLAG_IS_WRITABLE = 1 << 3, /* Read only flag */
G_IO_FLAG_IS_WRITEABLE = 1 << 3, /* Misspelling in 2.29.10 and earlier */
G_IO_FLAG_IS_SEEKABLE = 1 << 4, /* Read only flag */
G_IO_FLAG_MASK = (1 << 5) - 1,
G_IO_FLAG_GET_MASK = G_IO_FLAG_MASK,
G_IO_FLAG_SET_MASK = G_IO_FLAG_APPEND | G_IO_FLAG_NONBLOCK
} GIOFlags;
struct _GIOChannel
{
/*< private >*/
gint ref_count;
GIOFuncs *funcs;
gchar *encoding;
GIConv read_cd;
GIConv write_cd;
gchar *line_term; /* String which indicates the end of a line of text */
guint line_term_len; /* So we can have null in the line term */
gsize buf_size;
GString *read_buf; /* Raw data from the channel */
GString *encoded_read_buf; /* Channel data converted to UTF-8 */
GString *write_buf; /* Data ready to be written to the file */
gchar partial_write_buf[6]; /* UTF-8 partial characters, null terminated */
/* Group the flags together, immediately after partial_write_buf, to save memory */
guint use_buffer : 1; /* The encoding uses the buffers */
guint do_encode : 1; /* The encoding uses the GIConv coverters */
guint close_on_unref : 1; /* Close the channel on final unref */
guint is_readable : 1; /* Cached GIOFlag */
guint is_writeable : 1; /* ditto */
guint is_seekable : 1; /* ditto */
gpointer reserved1;
gpointer reserved2;
};
typedef gboolean (*GIOFunc) (GIOChannel *source,
GIOCondition condition,
gpointer data);
struct _GIOFuncs
{
GIOStatus (*io_read) (GIOChannel *channel,
gchar *buf,
gsize count,
gsize *bytes_read,
GError **err);
GIOStatus (*io_write) (GIOChannel *channel,
const gchar *buf,
gsize count,
gsize *bytes_written,
GError **err);
GIOStatus (*io_seek) (GIOChannel *channel,
gint64 offset,
GSeekType type,
GError **err);
GIOStatus (*io_close) (GIOChannel *channel,
GError **err);
GSource* (*io_create_watch) (GIOChannel *channel,
GIOCondition condition);
void (*io_free) (GIOChannel *channel);
GIOStatus (*io_set_flags) (GIOChannel *channel,
GIOFlags flags,
GError **err);
GIOFlags (*io_get_flags) (GIOChannel *channel);
};
GLIB_AVAILABLE_IN_ALL
void g_io_channel_init (GIOChannel *channel);
GLIB_AVAILABLE_IN_ALL
GIOChannel *g_io_channel_ref (GIOChannel *channel);
GLIB_AVAILABLE_IN_ALL
void g_io_channel_unref (GIOChannel *channel);
GLIB_DEPRECATED_FOR(g_io_channel_read_chars)
GIOError g_io_channel_read (GIOChannel *channel,
gchar *buf,
gsize count,
gsize *bytes_read);
GLIB_DEPRECATED_FOR(g_io_channel_write_chars)
GIOError g_io_channel_write (GIOChannel *channel,
const gchar *buf,
gsize count,
gsize *bytes_written);
GLIB_DEPRECATED_FOR(g_io_channel_seek_position)
GIOError g_io_channel_seek (GIOChannel *channel,
gint64 offset,
GSeekType type);
GLIB_DEPRECATED_FOR(g_io_channel_shutdown)
void g_io_channel_close (GIOChannel *channel);
GLIB_AVAILABLE_IN_ALL
GIOStatus g_io_channel_shutdown (GIOChannel *channel,
gboolean flush,
GError **err);
GLIB_AVAILABLE_IN_ALL
guint g_io_add_watch_full (GIOChannel *channel,
gint priority,
GIOCondition condition,
GIOFunc func,
gpointer user_data,
GDestroyNotify notify);
GLIB_AVAILABLE_IN_ALL
GSource * g_io_create_watch (GIOChannel *channel,
GIOCondition condition);
GLIB_AVAILABLE_IN_ALL
guint g_io_add_watch (GIOChannel *channel,
GIOCondition condition,
GIOFunc func,
gpointer user_data);
/* character encoding conversion involved functions.
*/
GLIB_AVAILABLE_IN_ALL
void g_io_channel_set_buffer_size (GIOChannel *channel,
gsize size);
GLIB_AVAILABLE_IN_ALL
gsize g_io_channel_get_buffer_size (GIOChannel *channel);
GLIB_AVAILABLE_IN_ALL
GIOCondition g_io_channel_get_buffer_condition (GIOChannel *channel);
GLIB_AVAILABLE_IN_ALL
GIOStatus g_io_channel_set_flags (GIOChannel *channel,
GIOFlags flags,
GError **error);
GLIB_AVAILABLE_IN_ALL
GIOFlags g_io_channel_get_flags (GIOChannel *channel);
GLIB_AVAILABLE_IN_ALL
void g_io_channel_set_line_term (GIOChannel *channel,
const gchar *line_term,
gint length);
GLIB_AVAILABLE_IN_ALL
const gchar * g_io_channel_get_line_term (GIOChannel *channel,
gint *length);
GLIB_AVAILABLE_IN_ALL
void g_io_channel_set_buffered (GIOChannel *channel,
gboolean buffered);
GLIB_AVAILABLE_IN_ALL
gboolean g_io_channel_get_buffered (GIOChannel *channel);
GLIB_AVAILABLE_IN_ALL
GIOStatus g_io_channel_set_encoding (GIOChannel *channel,
const gchar *encoding,
GError **error);
GLIB_AVAILABLE_IN_ALL
const gchar * g_io_channel_get_encoding (GIOChannel *channel);
GLIB_AVAILABLE_IN_ALL
void g_io_channel_set_close_on_unref (GIOChannel *channel,
gboolean do_close);
GLIB_AVAILABLE_IN_ALL
gboolean g_io_channel_get_close_on_unref (GIOChannel *channel);
GLIB_AVAILABLE_IN_ALL
GIOStatus g_io_channel_flush (GIOChannel *channel,
GError **error);
GLIB_AVAILABLE_IN_ALL
GIOStatus g_io_channel_read_line (GIOChannel *channel,
gchar **str_return,
gsize *length,
gsize *terminator_pos,
GError **error);
GLIB_AVAILABLE_IN_ALL
GIOStatus g_io_channel_read_line_string (GIOChannel *channel,
GString *buffer,
gsize *terminator_pos,
GError **error);
GLIB_AVAILABLE_IN_ALL
GIOStatus g_io_channel_read_to_end (GIOChannel *channel,
gchar **str_return,
gsize *length,
GError **error);
GLIB_AVAILABLE_IN_ALL
GIOStatus g_io_channel_read_chars (GIOChannel *channel,
gchar *buf,
gsize count,
gsize *bytes_read,
GError **error);
GLIB_AVAILABLE_IN_ALL
GIOStatus g_io_channel_read_unichar (GIOChannel *channel,
gunichar *thechar,
GError **error);
GLIB_AVAILABLE_IN_ALL
GIOStatus g_io_channel_write_chars (GIOChannel *channel,
const gchar *buf,
gssize count,
gsize *bytes_written,
GError **error);
GLIB_AVAILABLE_IN_ALL
GIOStatus g_io_channel_write_unichar (GIOChannel *channel,
gunichar thechar,
GError **error);
GLIB_AVAILABLE_IN_ALL
GIOStatus g_io_channel_seek_position (GIOChannel *channel,
gint64 offset,
GSeekType type,
GError **error);
GLIB_AVAILABLE_IN_ALL
GIOChannel* g_io_channel_new_file (const gchar *filename,
const gchar *mode,
GError **error);
/* Error handling */
GLIB_AVAILABLE_IN_ALL
GQuark g_io_channel_error_quark (void);
GLIB_AVAILABLE_IN_ALL
GIOChannelError g_io_channel_error_from_errno (gint en);
/* On Unix, IO channels created with this function for any file
* descriptor or socket.
*
* On Win32, this can be used either for files opened with the MSVCRT
* (the Microsoft run-time C library) _open() or _pipe, including file
* descriptors 0, 1 and 2 (corresponding to stdin, stdout and stderr),
* or for Winsock SOCKETs. If the parameter is a legal file
* descriptor, it is assumed to be such, otherwise it should be a
* SOCKET. This relies on SOCKETs and file descriptors not
* overlapping. If you want to be certain, call either
* g_io_channel_win32_new_fd() or g_io_channel_win32_new_socket()
* instead as appropriate.
*
* The term file descriptor as used in the context of Win32 refers to
* the emulated Unix-like file descriptors MSVCRT provides. The native
* corresponding concept is file HANDLE. There isn't as of yet a way to
* get GIOChannels for Win32 file HANDLEs.
*/
GLIB_AVAILABLE_IN_ALL
GIOChannel* g_io_channel_unix_new (int fd);
GLIB_AVAILABLE_IN_ALL
gint g_io_channel_unix_get_fd (GIOChannel *channel);
/* Hook for GClosure / GSource integration. Don't touch */
GLIB_VAR GSourceFuncs g_io_watch_funcs;
#ifdef G_OS_WIN32
/* You can use this "pseudo file descriptor" in a GPollFD to add
* polling for Windows messages. GTK applications should not do that.
*/
#define G_WIN32_MSG_HANDLE 19981206
/* Use this to get a GPollFD from a GIOChannel, so that you can call
* g_io_channel_win32_poll(). After calling this you should only use
* g_io_channel_read() to read from the GIOChannel, i.e. never read()
* from the underlying file descriptor. For SOCKETs, it is possible to call
* recv().
*/
GLIB_AVAILABLE_IN_ALL
void g_io_channel_win32_make_pollfd (GIOChannel *channel,
GIOCondition condition,
GPollFD *fd);
/* This can be used to wait a until at least one of the channels is readable.
* On Unix you would do a select() on the file descriptors of the channels.
*/
GLIB_AVAILABLE_IN_ALL
gint g_io_channel_win32_poll (GPollFD *fds,
gint n_fds,
gint timeout_);
/* Create an IO channel for Windows messages for window handle hwnd. */
#if GLIB_SIZEOF_VOID_P == 8
/* We use gsize here so that it is still an integer type and not a
* pointer, like the guint in the traditional prototype. We can't use
* intptr_t as that is not portable enough.
*/
GLIB_AVAILABLE_IN_ALL
GIOChannel *g_io_channel_win32_new_messages (gsize hwnd);
#else
GLIB_AVAILABLE_IN_ALL
GIOChannel *g_io_channel_win32_new_messages (guint hwnd);
#endif
/* Create an IO channel for C runtime (emulated Unix-like) file
* descriptors. After calling g_io_add_watch() on a IO channel
* returned by this function, you shouldn't call read() on the file
* descriptor. This is because adding polling for a file descriptor is
* implemented on Win32 by starting a thread that sits blocked in a
* read() from the file descriptor most of the time. All reads from
* the file descriptor should be done by this internal GLib
* thread. Your code should call only g_io_channel_read_chars().
*/
GLIB_AVAILABLE_IN_ALL
GIOChannel* g_io_channel_win32_new_fd (gint fd);
/* Get the C runtime file descriptor of a channel. */
GLIB_AVAILABLE_IN_ALL
gint g_io_channel_win32_get_fd (GIOChannel *channel);
/* Create an IO channel for a winsock socket. The parameter should be
* a SOCKET. Contrary to IO channels for file descriptors (on *Win32),
* you can use normal recv() or recvfrom() on sockets even if GLib
* is polling them.
*/
GLIB_AVAILABLE_IN_ALL
GIOChannel *g_io_channel_win32_new_socket (gint socket);
GLIB_DEPRECATED_FOR(g_io_channel_win32_new_socket)
GIOChannel *g_io_channel_win32_new_stream_socket (gint socket);
GLIB_AVAILABLE_IN_ALL
void g_io_channel_win32_set_debug (GIOChannel *channel,
gboolean flag);
#endif
#ifdef G_OS_WIN32
#define g_io_channel_new_file g_io_channel_new_file_utf8
GLIB_AVAILABLE_IN_ALL
GIOChannel *g_io_channel_new_file_utf8 (const gchar *filename,
const gchar *mode,
GError **error);
#endif
G_END_DECLS
#endif /* __G_IOCHANNEL_H__ */
pkg-config-0.29.1/glib/glib/gslist.c 0000664 0001750 0001750 00000061224 12651243552 014067 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
/*
* MT safe
*/
#include "config.h"
#include "gslist.h"
#include "gtestutils.h"
#include "gslice.h"
/**
* SECTION:linked_lists_single
* @title: Singly-Linked Lists
* @short_description: linked lists that can be iterated in one direction
*
* The #GSList structure and its associated functions provide a
* standard singly-linked list data structure.
*
* Each element in the list contains a piece of data, together with a
* pointer which links to the next element in the list. Using this
* pointer it is possible to move through the list in one direction
* only (unlike the Doubly-Linked Lists which
* allow movement in both directions).
*
* The data contained in each element can be either integer values, by
* using one of the Type
* Conversion Macros, or simply pointers to any type of data.
*
* List elements are allocated from the slice allocator, which is more
* efficient than allocating elements individually.
*
* Note that most of the #GSList functions expect to be passed a
* pointer to the first element in the list. The functions which insert
* elements return the new start of the list, which may have changed.
*
* There is no function to create a #GSList. %NULL is considered to be
* the empty list so you simply set a #GSList* to %NULL.
*
* To add elements, use g_slist_append(), g_slist_prepend(),
* g_slist_insert() and g_slist_insert_sorted().
*
* To remove elements, use g_slist_remove().
*
* To find elements in the list use g_slist_last(), g_slist_next(),
* g_slist_nth(), g_slist_nth_data(), g_slist_find() and
* g_slist_find_custom().
*
* To find the index of an element use g_slist_position() and
* g_slist_index().
*
* To call a function for each element in the list use
* g_slist_foreach().
*
* To free the entire list, use g_slist_free().
**/
/**
* GSList:
* @data: holds the element's data, which can be a pointer to any kind
* of data, or any integer value using the Type Conversion
* Macros.
* @next: contains the link to the next element in the list.
*
* The #GSList struct is used for each element in the singly-linked
* list.
**/
/**
* g_slist_next:
* @slist: an element in a #GSList.
*
* A convenience macro to get the next element in a #GSList.
*
* Returns: the next element, or %NULL if there are no more elements.
**/
#define _g_slist_alloc0() g_slice_new0 (GSList)
#define _g_slist_alloc() g_slice_new (GSList)
#define _g_slist_free1(slist) g_slice_free (GSList, slist)
/**
* g_slist_alloc:
*
* Allocates space for one #GSList element. It is called by the
* g_slist_append(), g_slist_prepend(), g_slist_insert() and
* g_slist_insert_sorted() functions and so is rarely used on its own.
*
* Returns: a pointer to the newly-allocated #GSList element.
**/
GSList*
g_slist_alloc (void)
{
return _g_slist_alloc0 ();
}
/**
* g_slist_free:
* @list: a #GSList
*
* Frees all of the memory used by a #GSList.
* The freed elements are returned to the slice allocator.
*
*
* If list elements contain dynamically-allocated memory,
* you should either use g_slist_free_full() or free them manually
* first.
*
*/
void
g_slist_free (GSList *list)
{
g_slice_free_chain (GSList, list, next);
}
/**
* g_slist_free_1:
* @list: a #GSList element
*
* Frees one #GSList element.
* It is usually used after g_slist_remove_link().
*/
/**
* g_slist_free1:
*
* A macro which does the same as g_slist_free_1().
*
* Since: 2.10
**/
void
g_slist_free_1 (GSList *list)
{
_g_slist_free1 (list);
}
/**
* g_slist_free_full:
* @list: a pointer to a #GSList
* @free_func: the function to be called to free each element's data
*
* Convenience method, which frees all the memory used by a #GSList, and
* calls the specified destroy function on every element's data.
*
* Since: 2.28
**/
void
g_slist_free_full (GSList *list,
GDestroyNotify free_func)
{
g_slist_foreach (list, (GFunc) free_func, NULL);
g_slist_free (list);
}
/**
* g_slist_append:
* @list: a #GSList
* @data: the data for the new element
*
* Adds a new element on to the end of the list.
*
*
* The return value is the new start of the list, which may
* have changed, so make sure you store the new value.
*
*
*
* Note that g_slist_append() has to traverse the entire list
* to find the end, which is inefficient when adding multiple
* elements. A common idiom to avoid the inefficiency is to prepend
* the elements and reverse the list when all elements have been added.
*
*
* |[
* /* Notice that these are initialized to the empty list. */
* GSList *list = NULL, *number_list = NULL;
*
* /* This is a list of strings. */
* list = g_slist_append (list, "first");
* list = g_slist_append (list, "second");
*
* /* This is a list of integers. */
* number_list = g_slist_append (number_list, GINT_TO_POINTER (27));
* number_list = g_slist_append (number_list, GINT_TO_POINTER (14));
* ]|
*
* Returns: the new start of the #GSList
*/
GSList*
g_slist_append (GSList *list,
gpointer data)
{
GSList *new_list;
GSList *last;
new_list = _g_slist_alloc ();
new_list->data = data;
new_list->next = NULL;
if (list)
{
last = g_slist_last (list);
/* g_assert (last != NULL); */
last->next = new_list;
return list;
}
else
return new_list;
}
/**
* g_slist_prepend:
* @list: a #GSList
* @data: the data for the new element
*
* Adds a new element on to the start of the list.
*
*
* The return value is the new start of the list, which
* may have changed, so make sure you store the new value.
*
*
* |[
* /* Notice that it is initialized to the empty list. */
* GSList *list = NULL;
* list = g_slist_prepend (list, "last");
* list = g_slist_prepend (list, "first");
* ]|
*
* Returns: the new start of the #GSList
*/
GSList*
g_slist_prepend (GSList *list,
gpointer data)
{
GSList *new_list;
new_list = _g_slist_alloc ();
new_list->data = data;
new_list->next = list;
return new_list;
}
/**
* g_slist_insert:
* @list: a #GSList
* @data: the data for the new element
* @position: the position to insert the element.
* If this is negative, or is larger than the number
* of elements in the list, the new element is added on
* to the end of the list.
*
* Inserts a new element into the list at the given position.
*
* Returns: the new start of the #GSList
*/
GSList*
g_slist_insert (GSList *list,
gpointer data,
gint position)
{
GSList *prev_list;
GSList *tmp_list;
GSList *new_list;
if (position < 0)
return g_slist_append (list, data);
else if (position == 0)
return g_slist_prepend (list, data);
new_list = _g_slist_alloc ();
new_list->data = data;
if (!list)
{
new_list->next = NULL;
return new_list;
}
prev_list = NULL;
tmp_list = list;
while ((position-- > 0) && tmp_list)
{
prev_list = tmp_list;
tmp_list = tmp_list->next;
}
new_list->next = prev_list->next;
prev_list->next = new_list;
return list;
}
/**
* g_slist_insert_before:
* @slist: a #GSList
* @sibling: node to insert @data before
* @data: data to put in the newly-inserted node
*
* Inserts a node before @sibling containing @data.
*
* Returns: the new head of the list.
*/
GSList*
g_slist_insert_before (GSList *slist,
GSList *sibling,
gpointer data)
{
if (!slist)
{
slist = _g_slist_alloc ();
slist->data = data;
slist->next = NULL;
g_return_val_if_fail (sibling == NULL, slist);
return slist;
}
else
{
GSList *node, *last = NULL;
for (node = slist; node; last = node, node = last->next)
if (node == sibling)
break;
if (!last)
{
node = _g_slist_alloc ();
node->data = data;
node->next = slist;
return node;
}
else
{
node = _g_slist_alloc ();
node->data = data;
node->next = last->next;
last->next = node;
return slist;
}
}
}
/**
* g_slist_concat:
* @list1: a #GSList
* @list2: the #GSList to add to the end of the first #GSList
*
* Adds the second #GSList onto the end of the first #GSList.
* Note that the elements of the second #GSList are not copied.
* They are used directly.
*
* Returns: the start of the new #GSList
*/
GSList *
g_slist_concat (GSList *list1, GSList *list2)
{
if (list2)
{
if (list1)
g_slist_last (list1)->next = list2;
else
list1 = list2;
}
return list1;
}
/**
* g_slist_remove:
* @list: a #GSList
* @data: the data of the element to remove
*
* Removes an element from a #GSList.
* If two elements contain the same data, only the first is removed.
* If none of the elements contain the data, the #GSList is unchanged.
*
* Returns: the new start of the #GSList
*/
GSList*
g_slist_remove (GSList *list,
gconstpointer data)
{
GSList *tmp, *prev = NULL;
tmp = list;
while (tmp)
{
if (tmp->data == data)
{
if (prev)
prev->next = tmp->next;
else
list = tmp->next;
g_slist_free_1 (tmp);
break;
}
prev = tmp;
tmp = prev->next;
}
return list;
}
/**
* g_slist_remove_all:
* @list: a #GSList
* @data: data to remove
*
* Removes all list nodes with data equal to @data.
* Returns the new head of the list. Contrast with
* g_slist_remove() which removes only the first node
* matching the given data.
*
* Returns: new head of @list
*/
GSList*
g_slist_remove_all (GSList *list,
gconstpointer data)
{
GSList *tmp, *prev = NULL;
tmp = list;
while (tmp)
{
if (tmp->data == data)
{
GSList *next = tmp->next;
if (prev)
prev->next = next;
else
list = next;
g_slist_free_1 (tmp);
tmp = next;
}
else
{
prev = tmp;
tmp = prev->next;
}
}
return list;
}
static inline GSList*
_g_slist_remove_link (GSList *list,
GSList *link)
{
GSList *tmp;
GSList *prev;
prev = NULL;
tmp = list;
while (tmp)
{
if (tmp == link)
{
if (prev)
prev->next = tmp->next;
if (list == tmp)
list = list->next;
tmp->next = NULL;
break;
}
prev = tmp;
tmp = tmp->next;
}
return list;
}
/**
* g_slist_remove_link:
* @list: a #GSList
* @link_: an element in the #GSList
*
* Removes an element from a #GSList, without
* freeing the element. The removed element's next
* link is set to %NULL, so that it becomes a
* self-contained list with one element.
*
* Removing arbitrary nodes from a singly-linked list
* requires time that is proportional to the length of the list
* (ie. O(n)). If you find yourself using g_slist_remove_link()
* frequently, you should consider a different data structure, such
* as the doubly-linked #GList.
*
* Returns: the new start of the #GSList, without the element
*/
GSList*
g_slist_remove_link (GSList *list,
GSList *link_)
{
return _g_slist_remove_link (list, link_);
}
/**
* g_slist_delete_link:
* @list: a #GSList
* @link_: node to delete
*
* Removes the node link_ from the list and frees it.
* Compare this to g_slist_remove_link() which removes the node
* without freeing it.
*
* Removing arbitrary nodes from a singly-linked list
* requires time that is proportional to the length of the list
* (ie. O(n)). If you find yourself using g_slist_delete_link()
* frequently, you should consider a different data structure, such
* as the doubly-linked #GList.
*
* Returns: the new head of @list
*/
GSList*
g_slist_delete_link (GSList *list,
GSList *link_)
{
list = _g_slist_remove_link (list, link_);
_g_slist_free1 (link_);
return list;
}
/**
* g_slist_copy:
* @list: a #GSList
*
* Copies a #GSList.
*
*
* Note that this is a "shallow" copy. If the list elements
* consist of pointers to data, the pointers are copied but
* the actual data isn't. See g_slist_copy_deep() if you need
* to copy the data as well.
*
*
* Returns: a copy of @list
*/
GSList*
g_slist_copy (GSList *list)
{
return g_slist_copy_deep (list, NULL, NULL);
}
/**
* g_slist_copy_deep:
* @list: a #GSList
* @func: a copy function used to copy every element in the list
* @user_data: user data passed to the copy function @func, or #NULL
*
* Makes a full (deep) copy of a #GSList.
*
* In contrast with g_slist_copy(), this function uses @func to make a copy of
* each list element, in addition to copying the list container itself.
*
* @func, as a #GCopyFunc, takes two arguments, the data to be copied and a user
* pointer. It's safe to pass #NULL as user_data, if the copy function takes only
* one argument.
*
* For instance, if @list holds a list of GObjects, you can do:
* |[
* another_list = g_slist_copy_deep (list, (GCopyFunc) g_object_ref, NULL);
* ]|
*
* And, to entirely free the new list, you could do:
* |[
* g_slist_free_full (another_list, g_object_unref);
* ]|
*
* Returns: a full copy of @list, use #g_slist_free_full to free it
*
* Since: 2.34
*/
GSList*
g_slist_copy_deep (GSList *list, GCopyFunc func, gpointer user_data)
{
GSList *new_list = NULL;
if (list)
{
GSList *last;
new_list = _g_slist_alloc ();
if (func)
new_list->data = func (list->data, user_data);
else
new_list->data = list->data;
last = new_list;
list = list->next;
while (list)
{
last->next = _g_slist_alloc ();
last = last->next;
if (func)
last->data = func (list->data, user_data);
else
last->data = list->data;
list = list->next;
}
last->next = NULL;
}
return new_list;
}
/**
* g_slist_reverse:
* @list: a #GSList
*
* Reverses a #GSList.
*
* Returns: the start of the reversed #GSList
*/
GSList*
g_slist_reverse (GSList *list)
{
GSList *prev = NULL;
while (list)
{
GSList *next = list->next;
list->next = prev;
prev = list;
list = next;
}
return prev;
}
/**
* g_slist_nth:
* @list: a #GSList
* @n: the position of the element, counting from 0
*
* Gets the element at the given position in a #GSList.
*
* Returns: the element, or %NULL if the position is off
* the end of the #GSList
*/
GSList*
g_slist_nth (GSList *list,
guint n)
{
while (n-- > 0 && list)
list = list->next;
return list;
}
/**
* g_slist_nth_data:
* @list: a #GSList
* @n: the position of the element
*
* Gets the data of the element at the given position.
*
* Returns: the element's data, or %NULL if the position
* is off the end of the #GSList
*/
gpointer
g_slist_nth_data (GSList *list,
guint n)
{
while (n-- > 0 && list)
list = list->next;
return list ? list->data : NULL;
}
/**
* g_slist_find:
* @list: a #GSList
* @data: the element data to find
*
* Finds the element in a #GSList which
* contains the given data.
*
* Returns: the found #GSList element,
* or %NULL if it is not found
*/
GSList*
g_slist_find (GSList *list,
gconstpointer data)
{
while (list)
{
if (list->data == data)
break;
list = list->next;
}
return list;
}
/**
* g_slist_find_custom:
* @list: a #GSList
* @data: user data passed to the function
* @func: the function to call for each element.
* It should return 0 when the desired element is found
*
* Finds an element in a #GSList, using a supplied function to
* find the desired element. It iterates over the list, calling
* the given function which should return 0 when the desired
* element is found. The function takes two #gconstpointer arguments,
* the #GSList element's data as the first argument and the
* given user data.
*
* Returns: the found #GSList element, or %NULL if it is not found
*/
GSList*
g_slist_find_custom (GSList *list,
gconstpointer data,
GCompareFunc func)
{
g_return_val_if_fail (func != NULL, list);
while (list)
{
if (! func (list->data, data))
return list;
list = list->next;
}
return NULL;
}
/**
* g_slist_position:
* @list: a #GSList
* @llink: an element in the #GSList
*
* Gets the position of the given element
* in the #GSList (starting from 0).
*
* Returns: the position of the element in the #GSList,
* or -1 if the element is not found
*/
gint
g_slist_position (GSList *list,
GSList *llink)
{
gint i;
i = 0;
while (list)
{
if (list == llink)
return i;
i++;
list = list->next;
}
return -1;
}
/**
* g_slist_index:
* @list: a #GSList
* @data: the data to find
*
* Gets the position of the element containing
* the given data (starting from 0).
*
* Returns: the index of the element containing the data,
* or -1 if the data is not found
*/
gint
g_slist_index (GSList *list,
gconstpointer data)
{
gint i;
i = 0;
while (list)
{
if (list->data == data)
return i;
i++;
list = list->next;
}
return -1;
}
/**
* g_slist_last:
* @list: a #GSList
*
* Gets the last element in a #GSList.
*
*
* This function iterates over the whole list.
*
*
* Returns: the last element in the #GSList,
* or %NULL if the #GSList has no elements
*/
GSList*
g_slist_last (GSList *list)
{
if (list)
{
while (list->next)
list = list->next;
}
return list;
}
/**
* g_slist_length:
* @list: a #GSList
*
* Gets the number of elements in a #GSList.
*
*
* This function iterates over the whole list to
* count its elements.
*
*
* Returns: the number of elements in the #GSList
*/
guint
g_slist_length (GSList *list)
{
guint length;
length = 0;
while (list)
{
length++;
list = list->next;
}
return length;
}
/**
* g_slist_foreach:
* @list: a #GSList
* @func: the function to call with each element's data
* @user_data: user data to pass to the function
*
* Calls a function for each element of a #GSList.
*/
void
g_slist_foreach (GSList *list,
GFunc func,
gpointer user_data)
{
while (list)
{
GSList *next = list->next;
(*func) (list->data, user_data);
list = next;
}
}
static GSList*
g_slist_insert_sorted_real (GSList *list,
gpointer data,
GFunc func,
gpointer user_data)
{
GSList *tmp_list = list;
GSList *prev_list = NULL;
GSList *new_list;
gint cmp;
g_return_val_if_fail (func != NULL, list);
if (!list)
{
new_list = _g_slist_alloc ();
new_list->data = data;
new_list->next = NULL;
return new_list;
}
cmp = ((GCompareDataFunc) func) (data, tmp_list->data, user_data);
while ((tmp_list->next) && (cmp > 0))
{
prev_list = tmp_list;
tmp_list = tmp_list->next;
cmp = ((GCompareDataFunc) func) (data, tmp_list->data, user_data);
}
new_list = _g_slist_alloc ();
new_list->data = data;
if ((!tmp_list->next) && (cmp > 0))
{
tmp_list->next = new_list;
new_list->next = NULL;
return list;
}
if (prev_list)
{
prev_list->next = new_list;
new_list->next = tmp_list;
return list;
}
else
{
new_list->next = list;
return new_list;
}
}
/**
* g_slist_insert_sorted:
* @list: a #GSList
* @data: the data for the new element
* @func: the function to compare elements in the list.
* It should return a number > 0 if the first parameter
* comes after the second parameter in the sort order.
*
* Inserts a new element into the list, using the given
* comparison function to determine its position.
*
* Returns: the new start of the #GSList
*/
GSList*
g_slist_insert_sorted (GSList *list,
gpointer data,
GCompareFunc func)
{
return g_slist_insert_sorted_real (list, data, (GFunc) func, NULL);
}
/**
* g_slist_insert_sorted_with_data:
* @list: a #GSList
* @data: the data for the new element
* @func: the function to compare elements in the list.
* It should return a number > 0 if the first parameter
* comes after the second parameter in the sort order.
* @user_data: data to pass to comparison function
*
* Inserts a new element into the list, using the given
* comparison function to determine its position.
*
* Returns: the new start of the #GSList
*
* Since: 2.10
*/
GSList*
g_slist_insert_sorted_with_data (GSList *list,
gpointer data,
GCompareDataFunc func,
gpointer user_data)
{
return g_slist_insert_sorted_real (list, data, (GFunc) func, user_data);
}
static GSList *
g_slist_sort_merge (GSList *l1,
GSList *l2,
GFunc compare_func,
gpointer user_data)
{
GSList list, *l;
gint cmp;
l=&list;
while (l1 && l2)
{
cmp = ((GCompareDataFunc) compare_func) (l1->data, l2->data, user_data);
if (cmp <= 0)
{
l=l->next=l1;
l1=l1->next;
}
else
{
l=l->next=l2;
l2=l2->next;
}
}
l->next= l1 ? l1 : l2;
return list.next;
}
static GSList *
g_slist_sort_real (GSList *list,
GFunc compare_func,
gpointer user_data)
{
GSList *l1, *l2;
if (!list)
return NULL;
if (!list->next)
return list;
l1 = list;
l2 = list->next;
while ((l2 = l2->next) != NULL)
{
if ((l2 = l2->next) == NULL)
break;
l1=l1->next;
}
l2 = l1->next;
l1->next = NULL;
return g_slist_sort_merge (g_slist_sort_real (list, compare_func, user_data),
g_slist_sort_real (l2, compare_func, user_data),
compare_func,
user_data);
}
/**
* g_slist_sort:
* @list: a #GSList
* @compare_func: the comparison function used to sort the #GSList.
* This function is passed the data from 2 elements of the #GSList
* and should return 0 if they are equal, a negative value if the
* first element comes before the second, or a positive value if
* the first element comes after the second.
*
* Sorts a #GSList using the given comparison function.
*
* Returns: the start of the sorted #GSList
*/
GSList *
g_slist_sort (GSList *list,
GCompareFunc compare_func)
{
return g_slist_sort_real (list, (GFunc) compare_func, NULL);
}
/**
* g_slist_sort_with_data:
* @list: a #GSList
* @compare_func: comparison function
* @user_data: data to pass to comparison function
*
* Like g_slist_sort(), but the sort function accepts a user data argument.
*
* Returns: new head of the list
*/
GSList *
g_slist_sort_with_data (GSList *list,
GCompareDataFunc compare_func,
gpointer user_data)
{
return g_slist_sort_real (list, (GFunc) compare_func, user_data);
}
pkg-config-0.29.1/glib/glib/ggettext.h 0000664 0001750 0001750 00000004676 12651243552 014432 0000000 0000000 /* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __G_GETTEXT_H__
#define __G_GETTEXT_H__
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only can be included directly."
#endif
#include
G_BEGIN_DECLS
GLIB_AVAILABLE_IN_ALL
const gchar *g_strip_context (const gchar *msgid,
const gchar *msgval) G_GNUC_FORMAT(1);
GLIB_AVAILABLE_IN_ALL
const gchar *g_dgettext (const gchar *domain,
const gchar *msgid) G_GNUC_FORMAT(2);
GLIB_AVAILABLE_IN_ALL
const gchar *g_dcgettext (const gchar *domain,
const gchar *msgid,
gint category) G_GNUC_FORMAT(2);
GLIB_AVAILABLE_IN_ALL
const gchar *g_dngettext (const gchar *domain,
const gchar *msgid,
const gchar *msgid_plural,
gulong n) G_GNUC_FORMAT(3);
GLIB_AVAILABLE_IN_ALL
const gchar *g_dpgettext (const gchar *domain,
const gchar *msgctxtid,
gsize msgidoffset) G_GNUC_FORMAT(2);
GLIB_AVAILABLE_IN_ALL
const gchar *g_dpgettext2 (const gchar *domain,
const gchar *context,
const gchar *msgid) G_GNUC_FORMAT(3);
G_END_DECLS
#endif /* __G_GETTEXT_H__ */
pkg-config-0.29.1/glib/glib/glib.rc 0000664 0001750 0001750 00000001370 12665370350 013657 0000000 0000000 #include
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,38,2,0
PRODUCTVERSION 2,38,2,0
FILEFLAGSMASK 0
FILEFLAGS 0
FILEOS VOS__WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904B0"
BEGIN
VALUE "CompanyName", "The GLib developer community"
VALUE "FileDescription", "GLib"
VALUE "FileVersion", "2.38.2.0"
VALUE "InternalName", "libglib-2.0-0"
VALUE "LegalCopyright", "Copyright © 1995-2011 Peter Mattis, Spencer Kimball, Josh MacDonald and others."
VALUE "OriginalFilename", "libglib-2.0-0.dll"
VALUE "ProductName", "GLib"
VALUE "ProductVersion", "2.38.2"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
pkg-config-0.29.1/glib/glib/gmain-internal.h 0000664 0001750 0001750 00000002114 12651243552 015465 0000000 0000000 /* gmain-internal.h - GLib-internal mainloop API
* Copyright (C) 2011 Red Hat, 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; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __G_MAIN_INTERNAL_H__
#define __G_MAIN_INTERNAL_H__
#if !defined (GLIB_COMPILATION)
#error "This is a private header"
#endif
#include "gmain.h"
G_BEGIN_DECLS
GSource *_g_main_create_unix_signal_watch (int signum);
G_END_DECLS
#endif /* __G_MAIN_H__ */
pkg-config-0.29.1/glib/glib/glib-mirroring-tab/ 0000775 0001750 0001750 00000000000 12665370347 016170 5 0000000 0000000 pkg-config-0.29.1/glib/glib/glib-mirroring-tab/gen-mirroring-tab.c 0000664 0001750 0001750 00000011331 12651243552 021566 0000000 0000000 /* gen-mirroring-tab.c - generate gmirroringtable.h for glib
* copied from FriBidi.
*
* $Id$
* $Author$
* $Date$
* $Revision$
* $Source$
*
* Author:
* Behdad Esfahbod, 2001, 2002, 2004
*
* Copyright (C) 2004 Sharif FarsiWeb, Inc
* Copyright (C) 2001,2002,2004 Behdad Esfahbod
*
* This 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.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library, in a file named COPYING; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA
*
* For licensing issues, contact .
*/
#include
#include